104 lines
3.6 KiB
Markdown
104 lines
3.6 KiB
Markdown
|
|
# 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
|
||
|
|
```
|