# Maintenance Proxy Reverse proxy Nginx qui, selon l'adresse IP du client, **redirige les requêtes vers une application locale** (proxy_pass) **ou affiche une page de maintenance statique** avec un code HTTP `503 Service Unavailable`. Cas d'usage typique : exposer une application en pré-production à une équipe interne uniquement, ou bloquer ponctuellement quelques IP indésirables pendant un correctif. > Pour la spécification complète et les règles de contribution, voir [PROMPT.md](PROMPT.md). --- ## Quickstart ### Avec docker-compose (dev local) ```bash docker compose up --build # → http://localhost:8080 ``` Par défaut, la stack démarre en mode `whitelist` avec `127.0.0.1` autorisée et un upstream factice qui sert une page « UPSTREAM_OK ». Édite `docker-compose.yml` pour brancher ton vraie app. ### Avec docker run ```bash docker build -t maintenance-proxy . docker run --rm -p 8080:8080 \ -e MAINTENANCE_MODE=whitelist \ -e MAINTENANCE_IP_LIST="81.92.47.8,10.0.0.42" \ -e UPSTREAM_HOST="host.docker.internal:3000" \ maintenance-proxy ``` --- ## Variables d'environnement | Variable | Obligatoire | Défaut | Description | |---|---|---|---| | `MAINTENANCE_MODE` | ✅ | — | `whitelist` (seules les IP listées passent) ou `blacklist` (les IP listées sont bloquées). | | `MAINTENANCE_IP_LIST` | ✅ | — | Liste d'IPv4 individuelles séparées par des virgules. Espaces tolérés. Ex : `81.92.47.8, 10.0.0.42`. | | `UPSTREAM_HOST` | ✅ | — | Cible du `proxy_pass` au format `host:port`. Ex : `127.0.0.1:3000`. | | `LISTEN_PORT` | ❌ | `8080` | Port d'écoute du conteneur. | | `SERVER_NAME` | ❌ | `_` | `server_name` Nginx. | Le conteneur **refuse de démarrer** si une variable obligatoire est absente, si `MAINTENANCE_MODE` n'est pas `whitelist` ou `blacklist`, ou si une IP est syntaxiquement invalide. --- ## Comportement - Réponse `503 Service Unavailable` + en-tête `Retry-After: 3600` quand l'IP doit voir la maintenance. - Toute le domaine est concerné, sans exclusion (ni assets, ni healthcheck). - Un log dédié `/var/log/nginx/maintenance.log` (à l'intérieur du conteneur) ne contient **que** les requêtes ayant abouti sur la page de maintenance. - Pas de bypass token, pas de cookie magique : seul critère = IP source (`$remote_addr`). - Nginx est censé être directement exposé au client. Aucune confiance accordée à `X-Forwarded-For` reçu de l'extérieur. ### Ajouter ou retirer une IP 1. Modifier `MAINTENANCE_IP_LIST` (env var ou `docker-compose.yml`). 2. Redémarrer le conteneur : `docker compose up -d --force-recreate proxy`. Pas de hot-reload : les changements de liste exigent un restart (validation et regen du snippet `geo` au boot). --- ## Tests ```bash ./tests/run.sh ``` 6 cas couverts : - whitelist + IP autorisée → 200 (proxy) - whitelist + IP non autorisée → 503 (maintenance) - blacklist + IP listée → 503 (maintenance) - blacklist + IP non listée → 200 (proxy) - log dédié `maintenance.log` n'est rempli que sur les 503 - `nginx -t` valide la conf templatée ## Lint ```bash ./scripts/lint.sh ``` Lance `shellcheck` sur tous les scripts puis `nginx -t` dans un conteneur jetable. --- ## Architecture Voir [PROMPT.md](PROMPT.md) §3 pour le détail. En bref : ``` nginx/templates/default.conf.template # template envsubst nginx/snippets/maintenance-log.conf # log_format dédié public/maintenance.html # page statique sobre, zéro JS scripts/build-ip-list.sh # MAINTENANCE_IP_LIST → snippet `geo` scripts/entrypoint.sh # validation env + génération snippet Dockerfile # nginx:stable-alpine + assemblage ```