Files
fzarifian b968ec8aa5 feat: implémentation initiale du reverse proxy de maintenance
Reverse proxy Nginx (image stable-alpine) qui sert l'app upstream ou une
page de maintenance 503 selon l'IP du client.

- Modes whitelist/blacklist commutables via MAINTENANCE_MODE
- Liste IPv4 via MAINTENANCE_IP_LIST (séparée par virgules, validée au boot)
- Logique en directives Nginx natives (geo + map), zéro Lua/njs
- Page statique sobre HTML+CSS inline, zéro JS, zéro réseau sortant
- Log dédié /var/log/nginx/maintenance.log pour les requêtes bloquées
- Validation des env vars dans /docker-entrypoint.d/10-init.sh
- Stack Docker + docker-compose pour dev local et tests
- 6 cas de tests d'intégration (whitelist/blacklist x autorisée/bloquée + log + nginx -t)
- Lint shellcheck propre sur tous les scripts shell
2026-05-05 13:52:13 +02:00

50 lines
1.7 KiB
Plaintext

include /etc/nginx/snippets/maintenance-log.conf;
# Liste des IP générée au boot par scripts/build-ip-list.sh à partir
# de MAINTENANCE_IP_LIST. Définit la variable $ip_in_list (0 ou 1).
include /etc/nginx/snippets/_generated_geo.conf;
# Décision finale en croisant le mode et l'appartenance à la liste.
# whitelist : on bloque si l'IP n'est PAS dans la liste (ip_in_list=0)
# blacklist : on bloque si l'IP EST dans la liste (ip_in_list=1)
map "${MAINTENANCE_MODE}:$ip_in_list" $is_in_maintenance {
default 0;
"whitelist:0" 1;
"blacklist:1" 1;
}
server {
listen ${LISTEN_PORT};
server_name ${SERVER_NAME};
access_log /var/log/nginx/access.log combined;
access_log /var/log/nginx/maintenance.log maintenance_log if=$is_in_maintenance;
error_log /var/log/nginx/error.log warn;
error_page 503 /__maintenance.html;
# Page statique servie uniquement via error_page (jamais directement accessible).
location = /__maintenance.html {
internal;
root /usr/share/nginx/html;
try_files /maintenance.html =500;
add_header Retry-After 3600 always;
add_header Cache-Control "no-store" always;
}
location / {
# if + return est l'un des seuls usages sûrs de `if` en location (cf. If is Evil).
if ($is_in_maintenance) {
return 503;
}
proxy_pass http://${UPSTREAM_HOST};
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
}
}