Based on ansible-django-stack.
Ansible to deploy FragDenStaat.de - a Django app with Postgres database, ElasticSearch search engine, Celery+RabbitMQ background queue, Redis server and a full email server with postfix and dovecot on Ubuntu 22.04.
python -m venv ansible-env
source ansible-env/bin/activate
pip install -r requirements.txt
Copy local_vars/local_config.yml.example
to local_vars/local_config.yml
and set your SSH username.
Run this to deploy FragDenStaat.de
ansible-playbook playbooks/fragdenstaat.de.yml -v
There are tags available:
deploy-web
– updates app and reloads app serverdeploy-backend
– likedeploy-web
but also restarts workersdeploy-frontend
- rebuilds frontend and reloads app servernginx
– rebuilds nginx config and reload nginx
Use like this:
ansible-playbook fragdenstaat.de.yml -v -t deploy-web -t deploy-frontend
Secrets are managed with ansible-vault
.
Edit production secrets:
ansible-vault edit group_vars/all/secrets.yml
Make sure vpn server is setup.
Setup VPN server:
ansible-playbook -v playbooks/vpnserver.yml
Store public key in host variables file in host_vars/
under the key host_data.wg_publickey
Run this script to add a client:
ansible-playbook -v playbooks/vpn_add_client.yml
After it's done, a client configuration file is in your local directory and the public key has been recorded in encrypted form env_vars/vpnclients.yml
.
You should commit env_vars/vpnclients.yml
.
Update the peers on the server:
ansible-playbook -v playbooks/vpnserver.yml
flowchart TB
subgraph brooke
brookessh[[SSH access]]
appserver[Gunicorn/Uvicorn]
brookenginx[nginx frontend server]
appworker[Celery Worker]
wireguard[Wireguard VPN]
db[Postgres Database]
postfix["Postfix (SMTP)"]
dovecot["Dovecot (IMAP)"]
redis[Redis Broker]
memcached[memcached Cache]
rabbitmq[RabbitMQ Queue]
brookessd[(SSD storage)]
end
subgraph brooke
brookenginx-->appserver
brookenginx-->brookessd
appserver-->db
nfsmount-- media files -->nfs
appserver-->nfsmount
appserver-->rabbitmq
appserver-->memcached
appserver-- mail download -->dovecot
appserver-- Websocket Channel Layer Group -->redis
rabbitmq<-->appworker
postfix-- check deliverability -->db
db-->brookessd
postfix-->brookessd
dovecot-->brookessd
appworker-->db
appworker-->nfsmount
appworker-- fetch mail -->dovecot
appworker-- Mail Log reading -->brookessd
wireguard-->brookenginx
brooke-cronbackup[Cron Backup Task]
brookessd-- mail storage --> brooke-cronbackup
brookessd-- database dumps --> brooke-cronbackup
nfsmount
brooke-graylog-sidecar[[graylog sidecar]]
brooke-prometheus-exporter[[prometheus exporter]]
end
subgraph schoch
schochssh[[SSH access]]
schochnginx[nginx frontend server]
schochnginx--authenticating access --> appserver
schochnginx-->schochhdd[(HDD storage)]
nfs<-->schochhdd[(HDD storage)]-->schoch-cronbackup[Cron Backup Task]
schoch-graylog-sidecar[[graylog sidecar]]
schoch-prometheus-exporter[[prometheus exporter]]
end
subgraph schaar
schaarssh[[SSH access]]
fdsbot[Slack fdsbot]
schaarnginx
db-->dbreplica[Postgres Database Replica]
schaar-graylog-sidecar[[graylog sidecar]]
schaar-prometheus-exporter[[prometheus exporter]]
docker-->schaar-cronbackup[Cron Backup Task]
end
subgraph schaar
schaarnginx[nginx frontend server]
subgraph docker
schaarnginx-->weblate
schaarnginx-->fds-forum
schaarnginx-->fds-ogimage
schaarnginx-->metabase
end
metabase-- reporting schema views -->db
end
subgraph fds-es1
fdses01ssh[[SSH access]]
elasticsearch[Elasticsearch server]<-->appworker
elasticsearch-->fdses01ssd[(SSD storage)]
fds-es1-graylog-sidecar[[graylog sidecar]]
fds-es1-prometheus-exporter[[prometheus exporter]]
end
subgraph internet
slack([Slack])==>fdsbot-->brookessh
user([User])== media.frag-den-staat.de ==>schochnginx
user== fragdenstaat.de / static.frag-den-staat.de ==>brookenginx
user== ogimage.frag-den-staat.de ==>schaarnginx
mailuser([Email])==>postfix
fdsstaff([FDS staff])==>dovecot
fdsstaff==>schaarnginx
fdsstaff==>wireguard
end
subgraph backupstorage
backup[(backup storage)]
brooke-cronbackup-->backup
schoch-cronbackup-->backup
schaar-cronbackup-->backup
end
subgraph fds-tst
fdsstaff==>fds-tstwireguard[Wireguard VPN]-->fds-tstnginx[nginx reverse proxy]
fdsstaff==>fds-tstmail[SMTP proxy]
end
subgraph fds-tst
subgraph fds-tstvm[VMs]
fds-tstmail-->brooke-tst
fds-tstnginx-->brooke-tst
fds-tstnginx-->schaar-tst
fds-tstnginx-->schoch-tst
fds-tstnginx-->fds-es01-tst
end
end
subgraph fds-mon
fdsstaff==>fds-monwireguard-->fds-monnginx
fds-monwireguard[Wireguard VPN]
fds-monnginx[Nginx reverse proxy]
end
subgraph fds-mon
subgraph fds-mondocker[docker]
fds-monnginx-->sentry
fds-monnginx-->grafana
fds-monnginx-->graylog
fds-monnginx-->prometheus
end
end