Skip to content

Commit 2e98d1e

Browse files
nkaurelienclaude
andcommitted
feat(nginx-certbot): add Nginx reverse proxy with Let's Encrypt SSL
- Add Docker Compose configuration for Nginx + Certbot - Include init script for first certificate generation - Auto-renewal every 12h, nginx reload every 6h - Add MkDocs documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 12bf8a0 commit 2e98d1e

7 files changed

Lines changed: 360 additions & 0 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Nginx + Certbot
2+
3+
Reverse proxy Nginx avec certificats SSL Let's Encrypt automatiques.
4+
5+
## Quick Start
6+
7+
```bash
8+
cd nginx-certbot
9+
10+
# 1. Configurer le domaine dans nginx/conf.d/default.conf
11+
# 2. Configurer init-letsencrypt.sh (domaine + email)
12+
13+
# 3. Initialiser le certificat
14+
./init-letsencrypt.sh
15+
16+
# 4. Démarrer
17+
docker compose up -d
18+
```
19+
20+
## Ports
21+
22+
| Service | Port | Description |
23+
|---------|------|-------------|
24+
| HTTP | 80 | Redirection vers HTTPS |
25+
| HTTPS | 443 | Trafic SSL |
26+
27+
## Architecture
28+
29+
```mermaid
30+
graph LR
31+
A[Client] --> B[Nginx:80/443]
32+
B --> C[Certbot]
33+
B --> D[App Backend]
34+
C --> E[Let's Encrypt]
35+
```
36+
37+
## Fonctionnement
38+
39+
### Renouvellement automatique
40+
41+
- **Certbot** vérifie le renouvellement toutes les **12 heures**
42+
- **Nginx** recharge sa configuration toutes les **6 heures**
43+
- Certificats renouvelés automatiquement avant expiration
44+
45+
### Challenge ACME
46+
47+
```nginx
48+
location /.well-known/acme-challenge/ {
49+
root /var/www/certbot;
50+
}
51+
```
52+
53+
## Configuration
54+
55+
### Variables
56+
57+
| Variable | Description |
58+
|----------|-------------|
59+
| `domains` | Liste des domaines |
60+
| `email` | Email pour Let's Encrypt |
61+
| `staging` | Mode test (évite rate limits) |
62+
63+
### Exemple proxy vers application
64+
65+
```nginx
66+
server {
67+
listen 443 ssl;
68+
server_name app.example.com;
69+
70+
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
71+
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
72+
73+
location / {
74+
proxy_pass http://app:8080;
75+
proxy_set_header Host $host;
76+
proxy_set_header X-Real-IP $remote_addr;
77+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
78+
proxy_set_header X-Forwarded-Proto $scheme;
79+
}
80+
}
81+
```
82+
83+
## Volumes
84+
85+
| Chemin | Description |
86+
|--------|-------------|
87+
| `./nginx/conf.d` | Configuration Nginx |
88+
| `./certbot/conf` | Certificats SSL |
89+
| `./certbot/www` | Challenge ACME |
90+
91+
## Mode Staging
92+
93+
Pour les tests, activez le mode staging :
94+
95+
```bash
96+
# Dans init-letsencrypt.sh
97+
staging=1
98+
```
99+
100+
## Liens
101+
102+
- [Certbot](https://certbot.eff.org/)
103+
- [Let's Encrypt](https://letsencrypt.org/)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ nav:
107107
- Socket Proxy: services/api-management/traefik/socket-proxy.md
108108
- Kong: services/api-management/kong.md
109109
- Hasura: services/api-management/hasura.md
110+
- Nginx + Certbot: services/api-management/nginx-certbot.md
110111

111112
- Orchestration:
112113
- Overview: services/orchestration/index.md

nginx-certbot/.env.example

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Nginx Certbot Configuration
2+
3+
# Domain(s) for SSL certificate
4+
DOMAIN=example.com
5+
6+
# Email for Let's Encrypt notifications
7+
CERTBOT_EMAIL=your-email@example.com
8+
9+
# Use staging server (1=yes, 0=no)
10+
# Set to 1 for testing to avoid rate limits
11+
STAGING=0

nginx-certbot/README.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Nginx + Certbot (Let's Encrypt)
2+
3+
Reverse proxy Nginx avec gestion automatique des certificats SSL via Certbot/Let's Encrypt.
4+
5+
## Quick Start
6+
7+
### 1. Configuration
8+
9+
Éditer les fichiers de configuration :
10+
11+
```bash
12+
# Modifier le domaine dans nginx/conf.d/default.conf
13+
# Remplacer "example.com" par votre domaine
14+
15+
# Modifier init-letsencrypt.sh
16+
# - domains=(votre-domaine.com www.votre-domaine.com)
17+
# - email="votre-email@example.com"
18+
```
19+
20+
### 2. Première initialisation
21+
22+
```bash
23+
# Générer le premier certificat
24+
./init-letsencrypt.sh
25+
```
26+
27+
### 3. Démarrage
28+
29+
```bash
30+
docker compose up -d
31+
```
32+
33+
## Fonctionnement
34+
35+
- **Nginx** : Reverse proxy avec SSL termination
36+
- **Certbot** : Renouvellement automatique des certificats (toutes les 12h)
37+
- **Auto-reload** : Nginx recharge la config toutes les 6h
38+
39+
## Structure
40+
41+
```
42+
nginx-certbot/
43+
├── compose.yml
44+
├── init-letsencrypt.sh # Script d'initialisation
45+
├── nginx/
46+
│ └── conf.d/
47+
│ └── default.conf # Configuration Nginx
48+
└── certbot/
49+
├── conf/ # Certificats Let's Encrypt
50+
└── www/ # Challenge ACME
51+
```
52+
53+
## Ajouter un nouveau site
54+
55+
1. Créer un fichier dans `nginx/conf.d/` (ex: `mysite.conf`)
56+
2. Ajouter le domaine dans `init-letsencrypt.sh`
57+
3. Relancer le script d'initialisation
58+
59+
### Exemple de configuration proxy
60+
61+
```nginx
62+
server {
63+
listen 80;
64+
server_name myapp.example.com;
65+
66+
location /.well-known/acme-challenge/ {
67+
root /var/www/certbot;
68+
}
69+
70+
location / {
71+
return 301 https://$host$request_uri;
72+
}
73+
}
74+
75+
server {
76+
listen 443 ssl;
77+
server_name myapp.example.com;
78+
79+
ssl_certificate /etc/letsencrypt/live/myapp.example.com/fullchain.pem;
80+
ssl_certificate_key /etc/letsencrypt/live/myapp.example.com/privkey.pem;
81+
82+
location / {
83+
proxy_pass http://myapp:8080;
84+
proxy_set_header Host $host;
85+
proxy_set_header X-Real-IP $remote_addr;
86+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
87+
proxy_set_header X-Forwarded-Proto $scheme;
88+
}
89+
}
90+
```
91+
92+
## Mode staging
93+
94+
Pour les tests, utilisez le serveur staging de Let's Encrypt pour éviter les rate limits :
95+
96+
```bash
97+
# Dans init-letsencrypt.sh
98+
staging=1
99+
```
100+
101+
## Liens
102+
103+
- [Certbot Documentation](https://certbot.eff.org/docs/)
104+
- [Let's Encrypt](https://letsencrypt.org/)
105+
- [Nginx Documentation](https://nginx.org/en/docs/)

nginx-certbot/compose.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
services:
2+
nginx:
3+
image: nginx:latest
4+
container_name: nginx-proxy
5+
restart: unless-stopped
6+
volumes:
7+
- ./nginx/conf.d:/etc/nginx/conf.d:ro
8+
- ./certbot/conf:/etc/letsencrypt
9+
- ./certbot/www:/var/www/certbot
10+
ports:
11+
- "80:80"
12+
- "443:443"
13+
networks:
14+
- proxy-net
15+
command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
16+
17+
certbot:
18+
image: certbot/certbot
19+
container_name: certbot
20+
restart: unless-stopped
21+
volumes:
22+
- ./certbot/conf:/etc/letsencrypt
23+
- ./certbot/www:/var/www/certbot
24+
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done'"
25+
networks:
26+
- proxy-net
27+
28+
networks:
29+
proxy-net:
30+
driver: bridge

nginx-certbot/init-letsencrypt.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/bin/bash
2+
3+
# Configuration
4+
domains=(example.com www.example.com)
5+
email="your-email@example.com"
6+
staging=0 # Set to 1 for testing (avoid rate limits)
7+
8+
rsa_key_size=4096
9+
data_path="./certbot"
10+
11+
if [ -d "$data_path/conf/live/${domains[0]}" ]; then
12+
read -p "Existing data found. Continue and replace existing certificate? (y/N) " decision
13+
if [ "$decision" != "Y" ] && [ "$decision" != "y" ]; then
14+
exit
15+
fi
16+
fi
17+
18+
echo "### Creating dummy certificate for ${domains[0]} ..."
19+
mkdir -p "$data_path/conf/live/${domains[0]}"
20+
docker compose run --rm --entrypoint "\
21+
openssl req -x509 -nodes -newkey rsa:$rsa_key_size -days 1 \
22+
-keyout '/etc/letsencrypt/live/${domains[0]}/privkey.pem' \
23+
-out '/etc/letsencrypt/live/${domains[0]}/fullchain.pem' \
24+
-subj '/CN=localhost'" certbot
25+
echo
26+
27+
echo "### Starting nginx ..."
28+
docker compose up --force-recreate -d nginx
29+
echo
30+
31+
echo "### Deleting dummy certificate for ${domains[0]} ..."
32+
docker compose run --rm --entrypoint "\
33+
rm -Rf /etc/letsencrypt/live/${domains[0]} && \
34+
rm -Rf /etc/letsencrypt/archive/${domains[0]} && \
35+
rm -Rf /etc/letsencrypt/renewal/${domains[0]}.conf" certbot
36+
echo
37+
38+
echo "### Requesting Let's Encrypt certificate for ${domains[*]} ..."
39+
domain_args=""
40+
for domain in "${domains[@]}"; do
41+
domain_args="$domain_args -d $domain"
42+
done
43+
44+
# Select appropriate email arg
45+
case "$email" in
46+
"") email_arg="--register-unsafely-without-email" ;;
47+
*) email_arg="--email $email" ;;
48+
esac
49+
50+
# Enable staging mode if needed
51+
if [ $staging != "0" ]; then staging_arg="--staging"; fi
52+
53+
docker compose run --rm --entrypoint "\
54+
certbot certonly --webroot -w /var/www/certbot \
55+
$staging_arg \
56+
$email_arg \
57+
$domain_args \
58+
--rsa-key-size $rsa_key_size \
59+
--agree-tos \
60+
--force-renewal" certbot
61+
echo
62+
63+
echo "### Reloading nginx ..."
64+
docker compose exec nginx nginx -s reload
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
server {
2+
listen 80;
3+
server_name example.com www.example.com;
4+
5+
# Certbot challenge
6+
location /.well-known/acme-challenge/ {
7+
root /var/www/certbot;
8+
}
9+
10+
# Redirect HTTP to HTTPS
11+
location / {
12+
return 301 https://$host$request_uri;
13+
}
14+
}
15+
16+
server {
17+
listen 443 ssl;
18+
server_name example.com www.example.com;
19+
20+
# SSL certificates (will be created by certbot)
21+
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
22+
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
23+
24+
# SSL configuration
25+
ssl_protocols TLSv1.2 TLSv1.3;
26+
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
27+
ssl_prefer_server_ciphers off;
28+
ssl_session_cache shared:SSL:10m;
29+
ssl_session_timeout 1d;
30+
31+
# HSTS
32+
add_header Strict-Transport-Security "max-age=63072000" always;
33+
34+
location / {
35+
# Proxy to your application
36+
# proxy_pass http://app:8080;
37+
# proxy_set_header Host $host;
38+
# proxy_set_header X-Real-IP $remote_addr;
39+
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
40+
# proxy_set_header X-Forwarded-Proto $scheme;
41+
42+
# Default: serve static files
43+
root /var/www/html;
44+
index index.html;
45+
}
46+
}

0 commit comments

Comments
 (0)