From 3a5d73a4851b1d151f53dd97776f59042be7d046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Pedro?= Date: Thu, 22 Jan 2026 16:39:02 -0300 Subject: [PATCH] feat(proxy): Implement Zero-Downtime Reload Strategy - Added scripts/reload.sh and reload.ps1 for safe configuration updates - Implemented 'nginx -t' validation before reload to prevent crashes - Leveraged 'nginx -s reload' for process-level Blue-Green updates - Updated documentation (README.md, GEMINI.md) with new usage instructions - Fixed nginx.conf to properly scope snippet includes - Restored missing SSL components (options-ssl-nginx.conf, dhparams) to enable local validation --- .gemini/GEMINI.md | 7 +++++++ .gemini/TODO.md | 5 +++-- README.md | 6 ++++++ certbot/conf/options-ssl-nginx.conf | 7 +++++++ certbot/conf/ssl-dhparams.pem | 8 ++++++++ fail2ban/db/fail2ban.sqlite3 | Bin 73728 -> 73728 bytes nginx.conf | 8 +++++++- scripts/reload.ps1 | 24 ++++++++++++++++++++++++ scripts/reload.sh | 26 ++++++++++++++++++++++++++ 9 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 certbot/conf/options-ssl-nginx.conf create mode 100644 certbot/conf/ssl-dhparams.pem create mode 100644 scripts/reload.ps1 create mode 100644 scripts/reload.sh diff --git a/.gemini/GEMINI.md b/.gemini/GEMINI.md index b8f9c1a..9400795 100644 --- a/.gemini/GEMINI.md +++ b/.gemini/GEMINI.md @@ -117,6 +117,13 @@ docker compose logs nginx-proxy | grep "SSL" docker compose exec nginx-proxy /scripts/renew_ssl.sh ``` +**Reload Zero-Downtime (Blue-Green Logic):** +Este comando valida a configuração e executa um reload gracioso (`nginx -s reload`), onde novos workers assumem as novas configurações enquanto os antigos terminam as requisições correntes. +```bash +./scripts/reload.sh # Linux +./scripts/reload.ps1 # Windows PowerShell +``` + **Banir um IP manualmente:** ```bash docker compose exec fail2ban fail2ban-client set nginx-badbots banip 1.2.3.4 diff --git a/.gemini/TODO.md b/.gemini/TODO.md index ae757af..5b022ef 100644 --- a/.gemini/TODO.md +++ b/.gemini/TODO.md @@ -14,5 +14,6 @@ ## 3. Atualizações Zero-Downtime (Sem Queda) **Objetivo:** Criar um método para atualizar configurações de sites sem que clientes externos percam a conexão. -- **Cenário Atual:** Restart do container ou reload podem causar breves interrupções se não gerenciados corretamente. -- **Solução Proposta:** Implementar scripts de "Reload Suave" (`nginx -s reload`) com validação prévia (`nginx -t`) automatizada, garantindo que conexões ativas terminem graciosamente. +- **Status:** ✅ Concluído. +- **Solução Implementada:** Script `./scripts/reload.sh` que executa `nginx -t` e `nginx -s reload` (Reload Suave/Process-Level Blue-Green). +- **Como usar:** Execute `./scripts/reload.sh` após alterar qualquer `.conf`. diff --git a/README.md b/README.md index bbf1b04..b64cb49 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,12 @@ O sistema gerencia isso automaticamente, mas você pode intervir manualmente se docker compose exec nginx-proxy /scripts/renew_ssl.sh ``` +- **Reload sem Downtime (Recomendado)**: + Para aplicar alterações de configuração (vhosts, SSL) sem derrubar conexões ativas: + ```bash + ./scripts/reload.sh + ``` + ### 5. Monitorar e Debugar - **Verificar Status dos Containers**: diff --git a/certbot/conf/options-ssl-nginx.conf b/certbot/conf/options-ssl-nginx.conf new file mode 100644 index 0000000..d29fcfd --- /dev/null +++ b/certbot/conf/options-ssl-nginx.conf @@ -0,0 +1,7 @@ +ssl_session_cache shared:le_nginx_SSL:1m; +ssl_session_timeout 1440m; + +ssl_protocols TLSv1.2 TLSv1.3; +ssl_prefer_server_ciphers off; + +ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"; diff --git a/certbot/conf/ssl-dhparams.pem b/certbot/conf/ssl-dhparams.pem new file mode 100644 index 0000000..da1f689 --- /dev/null +++ b/certbot/conf/ssl-dhparams.pem @@ -0,0 +1,8 @@ +-----BEGIN DH PARAMETERS----- +MIIBDAKCAQEA7aEz2xmnoIbgtStbhLjO2kIgHb+mXbTBJi2aXSnMlih9Q2WWfEOY +TrSw98BLop6l/6FS9XqCNAaB06AQLYIrXx1V3MtT1x9JcHfwbgKacDsEf+B+yYXS +Avv8G6j6t4k0s7ovg9tVEpRr1n8YCDj1bWv1iiQjfotmzeex6NNE9rX31GvRpRhP +jY+I9JDU0xG7GA16dNYYkq7kNPF7f1HmpFZOPiqox+IoMxZPlMZsKfRxmWpNPbgy +Pmzbrf7i3Wj9gjjGbPSvJ5dnaz4XGqUxAXemAXhjQ9TLVEig2NNo8LeYp/1r22+H +Wls/ddseH7N2lOr3M4oHsaUo4vsKG/SAfwIBAgICAOE= +-----END DH PARAMETERS----- diff --git a/fail2ban/db/fail2ban.sqlite3 b/fail2ban/db/fail2ban.sqlite3 index 861018c85efc1ca29df6dcfd2c8214be21b7ddbf..d9b223b34a09d3f374c74d4f0f14a6e2255bb3f0 100644 GIT binary patch delta 111 zcmZoTz|wGlWr8&0zKJrqBGR{f%e1puMJBGmu@ diff --git a/nginx.conf b/nginx.conf index 6207474..35e084c 100644 --- a/nginx.conf +++ b/nginx.conf @@ -29,7 +29,13 @@ http { ssl_session_cache shared:SSL:60m; # Include Snippets - include /etc/nginx/snippets/*.conf; + # Include Snippets (Global HTTP context) + # Excludes acme_challenge.conf which is server-context only + include /etc/nginx/snippets/cache_zones.conf; + include /etc/nginx/snippets/log_formats.conf; + include /etc/nginx/snippets/rate_limit.conf; + include /etc/nginx/snippets/security_maps.conf; + # include /etc/nginx/snippets/custom_errors.conf; # Optional globally # Global Fallback Logs error_log /var/log/nginx/error.log warn; diff --git a/scripts/reload.ps1 b/scripts/reload.ps1 new file mode 100644 index 0000000..5d6d5a7 --- /dev/null +++ b/scripts/reload.ps1 @@ -0,0 +1,24 @@ +$ContainerName = "nginx-proxy" + +Write-Host "[Reload] Checking configuration in $ContainerName..." -ForegroundColor Cyan + +# 1. Validate Configuration +docker exec $ContainerName nginx -t +if ($LASTEXITCODE -eq 0) { + Write-Host "[Reload] Configuration is VALID." -ForegroundColor Green + + # 2. Graceful Reload + Write-Host "[Reload] Triggering graceful reload..." -ForegroundColor Cyan + docker exec $ContainerName nginx -s reload + + if ($LASTEXITCODE -eq 0) { + Write-Host "[Reload] ✅ Reload signal sent successfully." -ForegroundColor Green + Write-Host "[Reload] Zero-downtime update in progress." -ForegroundColor Green + } else { + Write-Host "[Reload] ❌ Failed to send reload signal." -ForegroundColor Red + exit 1 + } +} else { + Write-Host "[Reload] ❌ Configuration is INVALID. Aborting reload." -ForegroundColor Red + exit 1 +} diff --git a/scripts/reload.sh b/scripts/reload.sh new file mode 100644 index 0000000..c739f94 --- /dev/null +++ b/scripts/reload.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# Zero-Downtime Reload Script +# Validates config first, then reloads NGINX gracefully. + +CONTAINER_NAME="nginx-proxy" + +echo "[Reload] Checking configuration in $CONTAINER_NAME..." + +# 1. Validate Configuration (nginx -t) +if docker exec "$CONTAINER_NAME" nginx -t; then + echo "[Reload] Configuration is VALID." +else + echo "[Reload] ❌ Configuration is INVALID. Aborting reload." + exit 1 +fi + +# 2. Graceful Reload (nginx -s reload) +# This starts new workers with new config, while old workers finish requests. +echo "[Reload] Triggering graceful reload..." +if docker exec "$CONTAINER_NAME" nginx -s reload; then + echo "[Reload] ✅ Reload signal sent successfully." + echo "[Reload] Zero-downtime update in progress." +else + echo "[Reload] ❌ Failed to send reload signal." + exit 1 +fi