Pourquoi soigner son reverse proxy sur VPS
Sur un VPS, le serveur web frontal est la pièce qui orchestre tout : il termine le TLS, distribue le trafic vers vos conteneurs (app, forge, media-server, LLM), sert les fichiers statiques et applique les en-têtes de sécurité. Bien choisi, il simplifie radicalement la mise en HTTPS de tous vos sous-domaines. Caddy obtient et renouvelle les certificats Let's Encrypt automatiquement, sans configuration, avec un fichier Caddyfile lisible de quelques lignes. Nginx, référence du marché, offre un contrôle extrêmement fin (cache, règles de réécriture, équilibrage de charge, rate limiting) mais exige une gestion manuelle ou via Certbot des certificats. Le choix oppose l'automatisme moderne à la maîtrise totale éprouvée.
Ce qu'un bon frontal apporte à votre VPS
- Terminaison TLS centralisée pour tous vos sous-domaines
- Reverse proxy unique vers plusieurs conteneurs Docker
- Service de fichiers statiques rapide et compression (gzip/brotli)
- En-têtes de sécurité (HSTS, CSP, X-Content-Type-Options) appliqués au même endroit
- Avec Caddy : certificats Let's Encrypt obtenus et renouvelés automatiquement
- Avec Nginx : cache, rate limiting et load balancing finement réglés
- HTTP/3 et QUIC pour réduire la latence sur connexions dégradées
Prérequis : un frontal frugal
Un reverse proxy est très léger : Caddy comme Nginx tournent confortablement sur 1 vCPU et 512 Mo à 1 Go de RAM, même en frontal de plusieurs services. La ressource à surveiller est plutôt la bande passante et le nombre de connexions simultanées. Il vous faut un domaine et ses sous-domaines pointés vers l'IP du VPS (enregistrements A/AAAA), les ports 80 et 443 ouverts sur le pare-feu (le port 80 est requis pour la validation des certificats), et Docker si vous conteneurisez le proxy. Aucun GPU ni gros stockage : ici, c'est la configuration qui fait la différence, pas la puissance brute.
Mettre en place Caddy (ou Nginx) en reverse proxy
Pointer les DNS
Créez les enregistrements A (et AAAA si IPv6) pour chaque sous-domaine (app, git, media) vers l'IP du VPS. La validation Let's Encrypt échouera tant que la résolution DNS n'est pas effective, alors vérifiez-la avant tout avec
dig app.votredomaine.comou un outil en ligne.Ouvrir les ports 80 et 443
Autorisez uniquement 80 et 443 sur le pare-feu (
ufw allow 80/tcp && ufw allow 443/tcp). Le port 80 reste indispensable pour le challenge HTTP de Let's Encrypt et pour rediriger automatiquement le trafic vers HTTPS.Rédiger la configuration de base
Avec Caddy, un bloc suffit :
app.votredomaine.com { reverse_proxy 127.0.0.1:3000 }et le HTTPS est automatique. Avec Nginx, écrivez unserverpar sous-domaine avecproxy_passet les en-têtesX-Forwarded-*, puis obtenez le certificat via Certbot :certbot --nginx -d app.votredomaine.com.Configurer plusieurs sous-domaines
Avec Caddy, listez chaque bloc dans le même
Caddyfile:git.votredomaine.com { reverse_proxy 127.0.0.1:3001 }. Avec Nginx, créez un fichier par sous-domaine dans/etc/nginx/conf.d/ou/etc/nginx/sites-available/, puis activez-le avecln -s. Les deux approches permettent de gérer des dizaines de services sans se répéter.Activer la compression
Caddy active gzip par défaut ; pour ajouter brotli :
encode zstd br gzipdans le bloc du site. Sous Nginx, ajoutez dansnginx.conf:gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 256;. La compression réduit le poids des réponses texte de 60 à 80 % selon les cas.Lancer et recharger sans coupure
Démarrez le service (
docker compose up -dousystemctl start caddy). Après chaque modification, validez la config (nginx -toucaddy validate) puis rechargez à chaud (nginx -s reload/caddy reload) pour ne jamais interrompre le trafic.Vérifier les certificats
Avec Caddy, exécutez
caddy validate --config /etc/caddy/Caddyfilepour détecter les erreurs avant rechargement, et consultez les logs (journalctl -u caddy -f) pour confirmer l'émission du certificat. Avec Nginx + Certbot,certbot certificatesliste les dates d'expiration etcertbot renew --dry-runsimule le renouvellement.Durcir la sécurité et mettre en place les logs
Activez HSTS, masquez la version du serveur (
server_tokens offsous Nginx, automatique sous Caddy), forcez TLS 1.2+ et ajoutez un rate limiting basique. Activez les logs d'accès et d'erreur, et surveillez les codes 502/504 qui révèlent un conteneur en aval injoignable.
Une fois le proxy opérationnel et les certificats émis, deux étapes complémentaires renforcent la sécurité et les performances : la configuration avancée des en-têtes et du rate limiting, et la mise en place du monitoring. L'ordre importe : validez d'abord que le routage de base fonctionne (curl -I https://app.votredomaine.com) avant d'empiler les couches de configuration.
Configuration avancée : sécurité, compression et HTTP/3
Une fois la base en place, trois axes améliorent concrètement la posture de votre reverse proxy.
En-têtes de sécurité. Appliquez au niveau du proxy les en-têtes que chaque service en aval oubliera : Strict-Transport-Security: max-age=31536000; includeSubDomains (HSTS), X-Content-Type-Options: nosniff, X-Frame-Options: SAMEORIGIN et une Content-Security-Policy adaptée à votre application. Centraliser ces en-têtes au proxy garantit qu'ils couvrent tous vos sous-domaines d'un seul geste.
Rate limiting. Sous Caddy, le module rate_limit (disponible via xcaddy build) permet de borner le nombre de requêtes par IP. Sous Nginx, la directive limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m; dans http {} puis limit_req zone=api burst=10 nodelay; dans le location concerné suffisent à protéger une API contre les abus sans dépendance externe.
HTTP/3 et QUIC. Caddy active HTTP/3 par défaut dès que le port UDP 443 est ouvert. Nginx supporte QUIC depuis la branche mainline (paramètre quic dans le bloc listen) ; vérifiez la version installée avec nginx -v avant d'activer la directive. HTTP/3 réduit la latence perçue sur les connexions mobiles et les réseaux à forte perte de paquets, sans rien changer au comportement des clients qui ne le supportent pas.
Caddy vs Nginx — tableau comparatif
Faites défiler le tableau
| Critère | Caddy | Nginx |
|---|---|---|
| HTTPS / certificats | Automatique, zéro config | Manuel ou via Certbot |
| Syntaxe de configuration | Caddyfile, très concis | Plus verbeuse, très expressive |
| Courbe d'apprentissage | Faible | Modérée à élevée |
| Contrôle fin (cache, rewrite, LB) | Bon, parfois via plugins | Très complet et éprouvé |
| HTTP/3 / QUIC | Activé par défaut | Supporté (branche mainline) |
| Rate limiting natif | Via module xcaddy | Intégré (`limit_req`) |
| Modules dynamiques | Compilation via xcaddy | Modules dynamiques (.so) |
| Empreinte RAM au repos | ~30–50 Mo | ~20–40 Mo (workers) |
| Format des logs | JSON structuré par défaut | Texte, configurable |
| Idéal pour | Mise en HTTPS rapide, multi-sous-domaines | Réglages avancés, fort trafic |
Les étapes de déploiement couvrent la configuration idéale. En pratique, plusieurs types d'erreurs reviennent régulièrement : un certificat bloqué par un réseau intermédiaire, un service en aval qui ne répond pas encore, ou un conteneur Docker inaccessible depuis le proxy parce que les deux sont sur des réseaux distincts. Le tableau de bord le plus utile dans ces situations est le journal du proxy (journalctl -u caddy -f ou tail -f /var/log/nginx/error.log), combiné à curl en local pour isoler le problème.
Dépannage : les erreurs les plus fréquentes
Même un proxy bien configuré produit des erreurs au démarrage ou sous charge. Voici les cinq cas qui reviennent le plus souvent.
Caddy — « no certificate » derrière un load-balancer. Lorsque Caddy est placé derrière un load-balancer qui termine déjà le TLS, il ne peut pas recevoir le challenge HTTP-01 de Let's Encrypt et échoue à émettre le certificat. Solution : utiliser le challenge DNS-01 via le plugin de votre registrar (ex. tls { dns cloudflare {env.CF_API_TOKEN} }), ou déléguer entièrement la gestion TLS au load-balancer et forcer Caddy en http:// interne.
Nginx — 502 Bad Gateway (upstream timeout). Un 502 persistant après démarrage indique que le service en aval n'écoute pas encore ou est planté. Vérifiez avec curl -v http://127.0.0.1:<port> depuis le serveur. Si le service démarre lentement, augmentez proxy_read_timeout et proxy_connect_timeout. Un 502 intermittent sous charge pointe vers un manque de connexions keepalive : ajoutez keepalive 32; dans le bloc upstream.
Caddy avec Docker — conteneur non joignable. Quand Caddy et le service cible tournent dans des réseaux Docker distincts, reverse_proxy 127.0.0.1:3000 ne fonctionne pas : 127.0.0.1 est l'adresse de la boucle locale du conteneur Caddy, pas de l'hôte. Solution : branchez les deux conteneurs sur le même réseau Docker bridge nommé et utilisez le nom du service comme adresse cible : reverse_proxy nom-du-service:3000.
Nginx — « too many open files » sous charge. L'erreur worker_connections are not enough ou open() failed (24: Too many open files) apparaît quand le VPS reçoit un pic de trafic. Augmentez la limite système (ulimit -n 65535 ou DefaultLimitNOFILE=65535 dans la unit systemd) et alignez worker_connections 4096; dans nginx.conf. Le nombre de connexions simultanées max est worker_processes * worker_connections.
Caddy — renouvellement silencieusement bloqué. Caddy renouvelle en tâche de fond, mais si le port UDP 443 est fermé par le pare-feu, HTTP/3 échoue et les logs peuvent masquer la vraie cause. Surveillez journalctl -u caddy -f autour des dates de renouvellement (60 jours après émission) et testez le challenge avec caddy run --config /etc/caddy/Caddyfile --watch en avant-plan pour voir les erreurs en temps réel.
Caddy, Nginx ou Traefik : le troisième choix
Pour une infrastructure à nombreux microservices Docker avec découverte automatique des conteneurs, Traefik s'impose comme troisième option : il lit les labels Docker (traefik.http.routers.monapp.rule=Host("app.votredomaine.com")) et configure les routes à la volée sans recharger manuellement. L'inconvénient est sa configuration plus complexe et sa documentation plus dense. Caddy et Nginx restent les choix naturels pour un VPS de taille raisonnable (1 à 20 services) ; Traefik prend le relais au-delà, notamment dans un contexte Kubernetes ou Docker Swarm. Pour une comparaison complète des trois, consultez l'article choisir son reverse proxy VPS : Caddy, Traefik ou Nginx.
Combiner les deux plutôt que choisir
Si vous hésitez encore, sachez que Caddy et Nginx ne s'excluent pas. Un pattern courant place Caddy en tout premier frontal pour gérer automatiquement le TLS de tous vos sous-domaines, puis laisse Nginx en aval pour le cache fin et les règles de réécriture d'un service précis. Vous combinez ainsi l'automatisme des certificats et la maîtrise du tuning, sans choisir un camp définitif.