Nginx Configuration Pattern¶
Three-file convention¶
Every site managed by Aether uses three nginx config files:
| File | Purpose | Managed by |
|---|---|---|
<site>.conf.full |
Production config (HTTPS, proxy/static, headers) | Git (aether repo) |
<site>.conf.temp |
Maintenance mode (HTTP only, returns 503, allows certbot) | Git (aether repo) |
<site>.conf |
Active config — symlink-like copy of either .full or .temp |
Operator (manual or *-init) |
nginx/conf.d/
├── aletheia-prod.conf.full ← git-tracked template (HTTPS)
├── aletheia-prod.conf.temp ← git-tracked template (maintenance)
├── aletheia-prod.conf ← ACTIVE (copy of .full or .temp, NOT in git)
├── monitoring.conf.full
├── monitoring.conf.temp
├── monitoring.conf ← ACTIVE
├── docs.conf.full
├── docs.conf.temp
└── docs.conf ← ACTIVE
Why the active .conf is not in git¶
The active config is a deliberate operator choice:
- During initial setup, sites start in
.tempmode (HTTP only) so certbot can obtain SSL certs - After cert acquisition, the operator switches to
.full(HTTPS) - For maintenance windows, the operator switches back to
.temp make deployintentionally does NOT overwrite the active.conf— it only updates the templates
If make deploy overwrote active configs, it could:
- Break a site that's intentionally in maintenance mode
- Activate HTTPS before SSL certs exist
- Disrupt a controlled rollout
Lifecycle¶
1. First-time setup (new service)¶
Each service has a make *-init target that handles the full bootstrap:
# Pattern used by umami-init, helios-init, docs-init:
cp .conf.temp → .conf # Start in maintenance mode (HTTP)
restart nginx # Apply config
certbot obtain cert # Get SSL certificate
cp .conf.full → .conf # Switch to production (HTTPS)
reload nginx # Apply without downtime
2. Fresh server (setup.sh)¶
setup.sh does this for ALL sites at once:
- Step 10: copies all .conf.temp → .conf (maintenance mode)
- Step 15: starts nginx
- Step 16: obtains SSL certs for all domains
- Step 16: copies all .conf.full → .conf (production mode)
3. Day-to-day config changes¶
# Edit the template in the repo
vim nginx/conf.d/aletheia-prod.conf.full
# Deploy templates to server (does NOT touch active .conf)
make deploy
# If the change affects the active config, manually activate:
sudo cp /opt/docker/nginx/conf.d/aletheia-prod.conf.full \
/opt/docker/nginx/conf.d/aletheia-prod.conf
docker exec nginx-proxy nginx -t && docker exec nginx-proxy nginx -s reload
4. Maintenance mode¶
# Switch to maintenance (returns 503 to all requests)
sudo cp /opt/docker/nginx/conf.d/aletheia-prod.conf.temp \
/opt/docker/nginx/conf.d/aletheia-prod.conf
docker exec nginx-proxy nginx -s reload
# ... do maintenance ...
# Switch back to production
sudo cp /opt/docker/nginx/conf.d/aletheia-prod.conf.full \
/opt/docker/nginx/conf.d/aletheia-prod.conf
docker exec nginx-proxy nginx -s reload
Current sites¶
| Site | Domain | Config prefix |
|---|---|---|
| Aletheia prod | aletheia.groupe-suffren.com | aletheia-prod |
| Aletheia staging | aletheia-staging.groupe-suffren.com | aletheia-staging |
| Aletheia dev | aletheia-dev.groupe-suffren.com | aletheia-dev |
| Helios prod | cabinet-dentaire-aubagne.fr, etc. | helios-prod |
| Helios staging | cda-staging.groupe-suffren.com, etc. | helios-staging |
| Helios dev | cda-dev.groupe-suffren.com, etc. | helios-dev |
| Monitoring | monitoring.groupe-suffren.com | monitoring |
| Analytics | analytics.groupe-suffren.com | analytics |
| Documentation | docs.groupe-suffren.com | docs |
Volume mounts¶
Nginx runs in a Docker container (nginx-proxy). It can only serve files that are mounted as volumes in nginx/docker-compose.yml:
volumes:
- ./conf.d:/etc/nginx/conf.d:ro # configs
- aletheia-prod-static:/data/aletheia/... # app static files
- /opt/docker/mnemosyne/site:/data/docs:ro # docs site
If you add a new static site, you must:
1. Add the volume mount to docker-compose.yml
2. Run make deploy to copy the compose file
3. Recreate nginx: make restart-nginx (reload is not enough for new volumes)