Ubuntu Linux · Épisode 11

🌐 Serveur Web Linux — Nginx, SSL Let's Encrypt & Reverse Proxy

Héberge ton propre site web, obtiens un certificat HTTPS gratuit et fais pointer plusieurs noms de domaine vers tes services Docker grâce au reverse proxy Nginx à la brique fondamentale du self-hosting.

📅 Avril 2026
👤 Par OWL
~40 min de lecture
Avancé
Illustration Nginx SSL Reverse Proxy Ubuntu

Héberger ses propres services web

💰
Nginx — Serveur Web
Installer et configurer Nginx pour héberger des sites statiques, des applications web et servir des fichiers efficacement.
💰
SSL/HTTPS Gratuit
Obtenir et renouveler automatiquement un certificat SSL avec Let's Encrypt et Certbot — HTTPS en quelques minutes, gratuitement.
💰
Reverse Proxy
Faire pointer plusieurs sous-domaines vers différents services Docker sur un seul serveur à la clé du self-hosting multi-services.
é
Optimisations
Gzip, cache, headers de sécurité HTTP, limitation de débit — toutes les bonnes pratiques pour un serveur web robuste et performant.

Nginx, SSL & Reverse Proxy sur Ubuntu

La métaphore d'OWL : Le Standard Téléphonique

Imagine un grand immeuble de bureaux. Ton serveur Linux, c'est l'immeuble. Chaque service (Nextcloud, Jellyfin, Portainer) est un bureau différent, à des étages différents. Nginx en reverse proxy, c'est la standardiste à l'accueil : elle reçoit tous les appels entrants (les requêtes HTTP/HTTPS sur le port 80/443) et les redirige vers le bon bureau selon le nom demandé.

Quelqu'un appelle pour nextcloud.mondomaine.fr → La standardiste redirige vers le bureau Nextcloud (port 8080). Pour jellyfin.mondomaine.fr → Bureau Jellyfin (port 8096). De l'extérieur, tout passe par le même numéro (port 443/HTTPS), mais chacun arrive dans le bon bureau.

Let's Encrypt, c'est l'organisme officiel qui offre gratuitement une carte d'identité vérifiée (le certificat SSL) à ton immeuble, prouvant que tu es bien le propriétaire du domaine.

Vue d'ensemble — Architecture Reverse Proxy

Internet
    é
    —  :443 (HTTPS)
    ?
+----------------------------------------------------+
é  NGINX Reverse Proxy  (Let's Encrypt SSL)          é
é                                                    é
é  nextcloud.mondomaine.fr  ------é  :8080 Nextcloud é
é  jellyfin.mondomaine.fr   ------é  :8096 Jellyfin  é
é  portainer.mondomaine.fr  ------é  :9000 Portainer é
é  monsite.fr               ------é  /var/www/html   é
+----------------------------------------------------+
    —           —           —           é
 Docker      Docker      Docker     Fichiers
 Nextcloud  Jellyfin   Portainer    statiques

1. Installer et Configurer Nginx

Terminal — Installation Nginx
# Installer Nginx
sudo apt update && sudo apt install -y nginx

# Démarrer et activer au boot
sudo systemctl enable --now nginx

# Vérifier le statut
sudo systemctl status nginx
é nginx.service - A high performance web server
Active: active (running)


# Autoriser dans UFW
sudo ufw allow 'Nginx Full' # ports 80 + 443
sudo ufw status

# Structure des fichiers Nginx
ls /etc/nginx/
nginx.conf — config principale
sites-available/ — configs disponibles
sites-enabled/ — configs actives (liens symboliques)
conf.d/ — configs additionnelles
snippets/ — fragments réutilisables


# Tester la configuration avant reload
sudo nginx -t
nginx: configuration file /etc/nginx/nginx.conf test is OK

# Recharger après chaque modification
sudo systemctl reload nginx

2. Héberger un Site Web Statique

Terminal + config Nginx
# Créer le dossier du site
sudo mkdir -p /var/www/monsite.fr/html
sudo chown -R $USER:$USER /var/www/monsite.fr

# Créer une page de test
echo "<h1>Bienvenue sur MonSite ! ??</h1>" > /var/www/monsite.fr/html/index.html

# Créer la config Nginx pour ce site
sudo nano /etc/nginx/sites-available/monsite.fr

Contenu de /etc/nginx/sites-available/monsite.fr :

/etc/nginx/sites-available/monsite.fr
server {
listen 80;
listen [::]:80;

server_name monsite.fr www.monsite.fr;

root /var/www/monsite.fr/html;
index index.html index.htm;

location / {
try_files $uri $uri/ =404;
}

# Logs
access_log /var/log/nginx/monsite.fr.access.log;
error_log /var/log/nginx/monsite.fr.error.log;
}


# Activer le site (lien symbolique)
sudo ln -s /etc/nginx/sites-available/monsite.fr /etc/nginx/sites-enabled/

# Désactiver le site par défaut
sudo rm /etc/nginx/sites-enabled/default

# Tester et recharger
sudo nginx -t && sudo systemctl reload nginx

3. HTTPS Gratuit avec Let's Encrypt & Certbot

Certbot est le client officiel Let's Encrypt. Il génére ton certificat SSL, modifie automatiquement ta config Nginx pour activer HTTPS, et met en place le renouvellement automatique.

⚠️

Prérequis : ton domaine doit pointer vers l'IP de ton serveur via un enregistrement DNS A. Let's Encrypt va vérifier que tu contrôles bien le domaine en accédant à ton serveur via HTTP.

Terminal — Installation et obtention du certificat SSL
# Installer Certbot et le plugin Nginx
sudo apt install -y certbot python3-certbot-nginx

# Obtenir le certificat (remplace par ton domaine et email)
sudo certbot --nginx -d monsite.fr -d www.monsite.fr \
--email ton@email.fr \
--agree-tos \
--no-eff-email

Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for monsite.fr...
Successfully deployed certificate for monsite.fr
Congratulations! You have successfully enabled HTTPS

IMPORTANT NOTES:
- Certificate is saved at: /etc/letsencrypt/live/monsite.fr/fullchain.pem
- Key is saved at: /etc/letsencrypt/live/monsite.fr/privkey.pem
- This certificate expires on 2026-07-11.
- These files will be updated when the certificate renews.


# Certbot met à jour automatiquement la config Nginx !
# Il ajoute les lignes SSL et une redirection HTTP?HTTPS

# Tester le renouvellement automatique

sudo certbot renew --dry-run
Simulating renewal of an existing certificate for monsite.fr
Congratulations, all simulated renewals succeeded!


# Le service systemd de renouvellement est actif automatiquement
sudo systemctl status certbot.timer
é certbot.timer - Run certbot twice daily
Active: active (waiting)

4. Config Nginx HTTPS Complète & Sécurisée

Config Nginx optimisée après obtention du certificat SSL, avec les headers de sécurité recommandés :

/etc/nginx/sites-available/monsite.fr — Version HTTPS complète
# Redirection HTTP — HTTPS
server {
listen 80;
listen [::]:80;
server_name monsite.fr www.monsite.fr;
return 301 https://$host$request_uri;
}

# Serveur HTTPS principal
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name monsite.fr www.monsite.fr;

# Certificat Let's Encrypt
ssl_certificate /etc/letsencrypt/live/monsite.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/monsite.fr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

# Headers de sécurité
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript;

root /var/www/monsite.fr/html;
index index.html;

location / {
try_files $uri $uri/ =404;
}

access_log /var/log/nginx/monsite.fr.access.log;
error_log /var/log/nginx/monsite.fr.error.log;
}

5. Reverse Proxy — Un Domaine, Plusieurs Services

Le reverse proxy te permet de diriger plusieurs sous-domaines vers différents services qui tournent en local (ou dans Docker). Un seul port 443 ouvert, des dizaines de services accessibles.

Snippet proxy réutilisable (é créer une seule fois)

/etc/nginx/snippets/proxy-params.conf
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_buffering off;


sudo nano /etc/nginx/snippets/proxy-params.conf
# Copie le contenu ci-dessus, puis tu l'incluras dans chaque vhost

Exemple : portainer.mondomaine.fr — localhost:9000

/etc/nginx/sites-available/portainer.mondomaine.fr
server {
listen 80;
server_name portainer.mondomaine.fr;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
server_name portainer.mondomaine.fr;

ssl_certificate /etc/letsencrypt/live/mondomaine.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mondomaine.fr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;

location / {
proxy_pass http://localhost:9000;
include /etc/nginx/snippets/proxy-params.conf;
}
}

Exemple : jellyfin.mondomaine.fr — localhost:8096

/etc/nginx/sites-available/jellyfin.mondomaine.fr
server {
listen 80;
server_name jellyfin.mondomaine.fr;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl http2;
server_name jellyfin.mondomaine.fr;

ssl_certificate /etc/letsencrypt/live/mondomaine.fr/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mondomaine.fr/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;

# Taille max upload (utile pour Nextcloud aussi)
client_max_body_size 0;

location / {
proxy_pass http://localhost:8096;
include /etc/nginx/snippets/proxy-params.conf;
}
}


# Activer les deux vhosts et recharger Nginx
sudo ln -s /etc/nginx/sites-available/portainer.mondomaine.fr /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/jellyfin.mondomaine.fr /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
💡

Certificat Wildcard — Un SSL pour tous vos sous-domaines

Plutôt que d'obtenir un certificat par sous-domaine, tu peux obtenir un certificat wildcard (*.mondomaine.fr) qui couvre tous vos sous-domaines. Cela nécessite une validation DNS (pas HTTP) et est compatible avec Cloudflare DNS.

sudo certbot certonly --manual --preferred-challenges dns -d "*.mondomaine.fr" -d "mondomaine.fr"

6. Alternative : Nginx Proxy Manager

Si tu préféres une interface graphique pour gérer tes reverse proxies, Nginx Proxy Manager (NPM) est la solution idéale — gestion des vhosts, SSL automatique, redirections, tout depuis une UI web.

/opt/nginx-proxy-manager/compose.yml
services:
npm:
image: jc21/nginx-proxy-manager:latest
container_name: nginx-proxy-manager
restart: unless-stopped
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
- "81:81" # Interface d'administration NPM
volumes:
- npm_data:/data
- letsencrypt:/etc/letsencrypt

volumes:
npm_data:
letsencrypt:


# Déployer
mkdir -p /opt/nginx-proxy-manager && cd /opt/nginx-proxy-manager
docker compose up -d

# Accès admin — http://IP:81
# Login par défaut :
# Email : admin@example.com
# Password : changeme


💡 IMPORTANT : Si Nginx est déjé installé sur le serveur,
# arrête-le avant de démarrer NPM (conflit sur les ports 80/443)

sudo systemctl stop nginx
sudo systemctl disable nginx
é

Nginx manuel vs Nginx Proxy Manager — Quand choisir

⚙️ Nginx Manuel

Plus de contrôle, configuré en fichiers texte, idéal si tu veux comprendre comment ça fonctionne. Recommandé pour apprendre.

✅ Nginx Proxy Manager

Interface graphique, SSL automatique en 1 clic, gestion rapide. Idéal pour un homelab avec beaucoup de services.

7. Commandes Nginx Essentielles — Antiséche

Terminal — Nginx cheat sheet
## SERVICE ##
sudo systemctl start nginx # démarrer
sudo systemctl stop nginx # arrêter
sudo systemctl reload nginx # recharger la config (sans interruption)
sudo systemctl restart nginx # redémarrer complètement

## CONFIGURATION ##
sudo nginx -t # tester la config (TOUJOURS avant reload !)
sudo nginx -T # afficher la config complète dépliée

## SITES ##
sudo ln -s /etc/nginx/sites-available/monsite /etc/nginx/sites-enabled/
# activer un site
sudo rm /etc/nginx/sites-enabled/monsite
# désactiver un site (ne supprime pas l'original)

## LOGS ##
sudo tail -f /var/log/nginx/access.log # accès en temps réel
sudo tail -f /var/log/nginx/error.log # erreurs en temps réel
sudo tail -f /var/log/nginx/monsite.fr.error.log # log d'un site

## SSL (CERTBOT) ##
sudo certbot certificates # lister les certificats
sudo certbot renew --dry-run # tester le renouvellement
sudo certbot renew # renouveler maintenant
sudo certbot delete --cert-name monsite.fr # supprimer un certificat

✅ Comment savoir si ton serveur web est bien configuré

  • Nginx est actif et sudo nginx -t retourne "configuration file test is OK"
  • Ton site est accessible en HTTPS avec le cadenas vert dans le navigateur (certificat Let's Encrypt valide)
  • La redirection HTTP — HTTPS fonctionne automatiquement (accèder en http:// redirige vers https://)
  • Un reverse proxy pointe vers au moins un service Docker (ex: portainer.tondomaine.fr accessible en HTTPS)
  • sudo certbot renew --dry-run réussit sans erreur, confirmant le renouvellement automatique SSL

⚠️ Problèmes Courants & Solutions

é Certbot échoue avec "Could not bind to IPv4 or IPv6"

💡 Le port 80 est déjé utilisé par Nginx ou un autre service. Certbot a besoin du port 80 libre pour sa validation HTTP. Arrête temporairement Nginx : sudo systemctl stop nginx, obtiens le certificat, puis redémarre. Avec le plugin --nginx, Certbot gére ça automatiquement.

"502 Bad Gateway" en reverse proxy

💡 Le service vers lequel tu proxies ne répond pas. Vérifie : 1) le conteneur Docker est-il démarré — (docker ps) 2) le port dans proxy_pass est-il correct — 3) si Docker, utilise l'IP du conteneur ou le nom du service rôleau plutôt que localhost qui peut ne pas fonctionner depuis Nginx système.

Mon domaine pointe bien vers le serveur mais Certbot dit que le challenge échoue

💡 Le pare-feu UFW bloque le port 80 entrant. Vérifie : sudo ufw status. Ajoute la règle si nécessaire : sudo ufw allow 'Nginx Full'. Aussi, certains FAI bloquent les ports 80/443 en entrée — dans ce cas, utilise la validation DNS.

"413 Request Entity Too Large" lors d'upload vers Nextcloud ou Jellyfin

💡 Nginx limite la taille des fichiers uploadés. Ajoute dans le bloc server ou location : client_max_body_size 0; (illimité) ou une valeur spécifique comme client_max_body_size 10G;. Puis recharge Nginx : sudo systemctl reload nginx.

💬 Commentaires & Discussion