Initialization¶
Overview¶
setup.sh is the single entry point for provisioning a server — whether from scratch
or recovering from a failure. It handles Docker, security hardening, directory structure,
secrets, networks, shared services, nginx, monitoring, Umami, and the docs site.
There are also per-service bootstrap targets (helios-init, umami-init, docs-init)
for adding services to an already-running server.
Setup Modes¶
Fresh install¶
For a brand new server with no existing data.
cd /opt/docker/aether/repo
sudo ./setup.sh # interactive — choose option 1
sudo ./setup.sh --fresh # non-interactive
What it does:
- Generates new passwords for all databases and Django SECRET_KEYs
- Creates PostgreSQL init script with generated credentials
- Prompts for basic auth username/password (staging/dev)
- Generates a new age keypair for secret encryption
- Encrypts all secrets into
.encfiles (commit and push these)
After completion:
- Save the age private key from
/opt/docker/.age-key.txtto the password manager - Edit env files for external services (SMTP, Sentry, API keys)
- Clone app repos and deploy (see post-setup checklist below)
- Commit and push the
.encfiles
Server migration / recovery¶
For rebuilding from an existing deployment with encrypted secrets in git.
cd /opt/docker/aether/repo
sudo ./setup.sh # interactive — choose option 2, paste age key
sudo ./setup.sh --recover AGE-SECRET-KEY-... # non-interactive
What it does:
- Writes the age key to
/opt/docker/.age-key.txt - Decrypts all
.encfiles to their server locations (make decrypt) - All existing passwords and credentials are restored (database dumps will work)
After completion: restore databases and media, clone app repos, deploy. See disaster recovery for the full procedure.
What Setup Handles¶
| Step | What | Notes |
|---|---|---|
| 1 | Docker CE | Installs + enables, adds debian to docker group |
| 2 | Utilities | git, apache2-utils, cron, fail2ban, iptables-persistent, age, sops |
| 3 | Swap | 11 GB swap file, vm.swappiness=10 |
| 4 | Unattended upgrades | Automatic Debian security patches |
| 5 | SSH hardening | Port 57361, key-only auth (checks for keys first) |
| 6 | Firewall | systemd service applying iptables after Docker starts |
| 7 | fail2ban | sshd + 4 nginx jails |
| 8 | Kernel hardening | rp_filter, log_martians via sysctl |
| 9 | Directory structure | All /opt/docker/ directories |
| 10 | Config deployment | make deploy — all configs copied to server |
| 11 | Secrets | Fresh: generate. Recovery: decrypt from .enc files |
| 12 | Docker networks | backend, web, monitoring |
| 13 | Shared services | PostgreSQL + Redis started, readiness check |
| 14 | Static volumes | aletheia-{prod,staging,dev}-static |
| 15 | Nginx | Started in maintenance mode (.conf.temp) |
| 16 | SSL certificates | Certbot for all *.groupe-suffren.com domains, then activates .conf.full |
| 17 | Monitoring + Umami + Docs | All started |
| 18 | Firewall rules | Applied after Docker is running |
| 19 | Backup cron | Daily at 02:00 |
| 20 | Encrypt (fresh only) | Encrypts generated secrets into .enc files |
Bootstrap Targets¶
These are for adding a specific service to an already-running server.
helios-init¶
Bootstraps Helios directories, env files, nginx configs, and monitoring rules.
What it does:
- Creates
/opt/docker/helios/{repo,envs}/ - Generates
.env.{prod,staging,dev}with newREVALIDATION_SECRETvalues - Deploys Helios nginx configs (
.conf.fulland.conf.temp) - Deploys Helios monitoring rules (
helios.rules.yml) - Reloads nginx and Prometheus
After completion:
- Copy the printed
REVALIDATION_SECRETvalues into the matching Aletheia env files - Clone the Helios repo to
/opt/docker/helios/repo/ - Run
make encryptto persist the new secrets - Obtain SSL certificates for practice domains (not handled by
setup.sh)
umami-init¶
Bootstraps Umami analytics from scratch — database, container, SSL, nginx.
What it does (7 steps):
- Creates directories, deploys docker-compose and nginx configs
- Creates
umamidatabase and user in PostgreSQL - Activates temp nginx config (HTTP only)
- Obtains SSL certificate for
analytics.groupe-suffren.com - Activates full nginx config (HTTPS)
- Starts the Umami container
- Verifies the container is running
After completion:
- Visit
https://analytics.groupe-suffren.com - Change the default password (default:
admin/umami) - Add websites and note the UUIDs for Helios env vars
- Run
make encryptto persist the.env
docs-init¶
Bootstraps the Mnemosyne documentation site — venv, build, SSL, nginx.
What it does (5 steps):
- Creates
/opt/docker/mnemosyne/, installs MkDocs Material in a venv - Assembles docs from all repos and builds the static site
- Deploys nginx configs, starts nginx with temp config
- Obtains SSL certificate for
docs.groupe-suffren.com - Activates full nginx config (HTTPS)
After completion: site is live at https://docs.groupe-suffren.com.
Rebuild with make docs-build, test locally with make docs-serve (port 8888).
Post-Setup Checklist¶
Fresh install¶
- [ ] Reconnect via new SSH port:
ssh -p 57361 debian@<server-ip> - [ ] Save age key to password manager:
cat /opt/docker/.age-key.txt - [ ] Edit env files for external services (SMTP, Sentry, Teams webhook):
/opt/docker/aletheia/envs/.env.prod/opt/docker/monitoring/.env
- [ ] Clone app repos and deploy:
git clone git@github.com:baudry-suffren/aletheia_v2.git /opt/docker/aletheia/repogit clone git@github.com:baudry-suffren/helios.git /opt/docker/helios/repo
- [ ] Create Django superuser:
docker exec -it aletheia-prod-web python manage.py createsuperuser - [ ] Change Umami default password at
https://analytics.groupe-suffren.com - [ ] Commit and push
.encfiles from the aether repo - [ ] Test backup cron:
/opt/docker/backups/scripts/backup.sh - [ ] Verify all environments accessible in browser
- [ ] Check
make diffshows no drift
Recovery¶
- [ ] Reconnect via SSH port 57361
- [ ] Verify secrets decrypted:
ls /opt/docker/shared/.env /opt/docker/aletheia/envs/.env.prod - [ ] Restore databases from backup (see disaster recovery)
- [ ] Restore media files
- [ ] Clone app repos and deploy
- [ ] Verify all environments accessible
- [ ] Check
make diffshows no drift - [ ] Verify backup cron is installed:
crontab -l | grep backup
Troubleshooting¶
setup.sh fails at Docker install: Check internet connectivity and Debian version. Docker CE requires Debian 12+.
SSL certificates fail:
DNS must point to the server before certbot can validate. Check with dig +short <domain>.
Sites remain in HTTP maintenance mode until certs are obtained. Retry manually:
docker exec certbot certbot certonly --webroot -w /var/www/certbot \
--non-interactive --agree-tos --email admin@groupe-suffren.com -d <domain>
PostgreSQL fails to start:
Check if port 5432 is already in use: ss -tlnp | grep 5432.
Check logs: docker logs shared_postgres.
"Permission denied" on env files:
Env files should be owned by debian:debian with mode 600. Fix: