Pourquoi un reverse proxy sur votre VPS
Un VPS expose une seule adresse IP publique. Derrière cette IP, vous pouvez faire tourner cinq, dix ou vingt services sur des ports internes différents. Sans reverse proxy, exposer chaque service sur un port public implique d'ouvrir ces ports dans le pare-feu, de gérer manuellement les certificats TLS pour chacun, et d'en informer chaque utilisateur. Un reverse proxy résout ces trois problèmes d'un coup : il reçoit tout le trafic sur les ports 80 et 443, identifie le domaine demandé, et redirige la requête vers le bon conteneur interne. Nginx Proxy Manager ajoute une couche d'interface graphique à cette mécanique : pas de fichier de conf à écrire, pas de reload manuel, et les certificats Let's Encrypt se gèrent en quelques clics. C'est particulièrement adapté aux agences qui hébergent plusieurs applications clientes sur le même serveur, ou aux développeurs indépendants qui font tourner plusieurs projets en parallèle.
NPM face à la configuration Nginx manuelle : 7 avantages concrets
- Pas de fichier de configuration : chaque proxy host se crée depuis l'interface web, sans syntaxe Nginx à mémoriser.
- Certificats Let's Encrypt automatiques : NPM demande, installe et renouvelle les certificats sans intervention. Wildcard possible via DNS challenge.
- Gestion centralisée : tous vos domaines, sous-domaines et redirections dans un seul écran, au lieu d'une dizaine de fichiers dans
/etc/nginx/sites-enabled/. - Listes d'accès (Access Lists) intégrées : protéger un service par IP ou par mot de passe sans toucher aux config de chaque app.
- Logs par hôte consultables dans l'interface : identifier une erreur 502 ou un abus sans ssh dans le conteneur.
- Redirections HTTP→HTTPS et 404 personnalisés configurables visuellement.
- Découverte par nom de conteneur Docker : cibler
portainer:9000plutôt qu'une IP interne instable qui change au redémarrage.
Prérequis chiffrés avant d'installer NPM
NPM ne fait que router du trafic, il est donc léger. Un VPS avec 1 Go de RAM et 1 vCPU suffit si NPM est le seul service notable. Si vous hébergez également les applications derrière lui, dimensionnez selon la somme de leurs besoins. Prévoyez 15 Go de disque SSD (certificats, base SQLite, logs). Logiciel requis : Docker 24+ et le plugin Compose v2 (docker compose, pas l'ancienne commande docker-compose). Réseau : les ports 80 et 443 doivent être libres sur le VPS — NPM en est l'unique occupant. Le port 81 est réservé à l'interface d'administration ; il ne doit jamais être exposé directement sur Internet. DNS : faites pointer vos enregistrements A vers l'IP du VPS avant de demander les certificats. Pour un wildcard *.votre-domaine.com, il faut une clé API auprès de votre fournisseur DNS (Cloudflare, OVH, etc.).
Installation et première configuration de Nginx Proxy Manager
Installer Docker sur le VPS
Sur un serveur Debian/Ubuntu : curl -fsSL https://get.docker.com | sh. Vérifiez ensuite : docker --version et docker compose version. Si le plugin Compose n'est pas présent, installez le paquet docker-compose-plugin via apt.
Créer le dossier de travail et le fichier Compose
Créez /opt/npm sur le VPS. Dans ce dossier, créez un fichier docker-compose.yml. Déclarez-y le service NPM avec l'image jc21/nginx-proxy-manager:latest, mappez les ports 80:80, 443:443 et 81:81, et définissez deux volumes : ./data:/data et ./letsencrypt:/etc/letsencrypt.
Démarrer le conteneur
Depuis /opt/npm, lancez docker compose up -d. Vérifiez que le conteneur tourne : docker compose ps. L'interface d'administration est accessible sur http://IP_DU_VPS:81 dans les trente secondes qui suivent.
Première connexion et sécurisation du compte admin
Connectez-vous avec les identifiants par défaut : email [email protected], mot de passe changeme. NPM vous invite immédiatement à changer ces deux valeurs. Faites-le avant toute autre action : ce compte donne un accès total à votre infrastructure de routage.
Créer un réseau Docker partagé
Pour que NPM puisse joindre vos conteneurs applicatifs par leur nom, ils doivent partager le même réseau Docker. Créez un réseau externe : docker network create proxy. Dans votre docker-compose.yml NPM, déclarez ce réseau comme externe. Faites de même dans le Compose de chaque application à proxifier.
Ajouter un premier Proxy Host
Dans l'interface : Proxy Hosts → Add Proxy Host. Renseignez le domaine (ex. app.votre-domaine.com), le Forward Hostname (nom du conteneur ou IP interne) et le port de l'application. Cochez « Block Common Exploits ». Si l'application utilise des WebSockets, activez « Websockets Support ».
Activer le SSL Let's Encrypt
Dans l'onglet SSL du Proxy Host, choisissez « Request a new SSL Certificate », acceptez les conditions Let's Encrypt et cochez « Force SSL ». NPM contacte les serveurs ACME, valide le domaine via HTTP-01 et installe le certificat. Votre service est en HTTPS en quelques secondes. Le renouvellement est automatique.
Sécuriser l'interface d'administration (port 81)
Fermez le port 81 dans votre pare-feu (ufw deny 81). Créez ensuite un Proxy Host dédié — ex. npm.votre-domaine.com → localhost:81 — avec SSL et une Access List restreinte à votre IP de gestion. Vous accédez ainsi à l'interface via HTTPS sans exposer le port 81 au reste du monde.
Certificat wildcard via DNS challenge
Pour couvrir tous vos sous-domaines d'un seul certificat, utilisez le DNS challenge. Dans l'onglet SSL, sélectionnez « Use a DNS Challenge », choisissez votre fournisseur (Cloudflare, OVH…) et renseignez la clé API. NPM crée un enregistrement TXT dans votre zone DNS, valide la propriété du domaine et obtient le certificat *.votre-domaine.com.
Tester la chaîne complète
Depuis un terminal : curl -I https://app.votre-domaine.com. Attendez un code 200 ou le code de votre application. Vérifiez également la redirection HTTP : curl -I http://app.votre-domaine.com doit retourner un 301 vers la version HTTPS.
Configuration avancée
NPM expose dans son interface plusieurs fonctionnalités qui vont au-delà du simple reverse proxy. Les Access Lists permettent de restreindre l'accès à un hôte par plage d'IP, par identifiant HTTP Basic Auth, ou par une combinaison des deux — utile pour protéger un backoffice sans ajouter d'authentification dans l'application elle-même. Les Streams gèrent le proxying TCP/UDP pour les protocoles non-HTTP (MySQL distant, serveur de jeux, MQTT…). La section Redirections crée des règles permanentes (301) ou temporaires (302) d'un domaine ou d'un chemin vers une autre URL, sans qu'un service soit nécessaire derrière. Les onglets Avancé de chaque proxy host permettent d'injecter de la configuration Nginx brute lorsque l'interface ne couvre pas un cas particulier (en-têtes de sécurité personnalisés, proxy_read_timeout étendu pour les longues requêtes d'upload, etc.).
Durcissement : rate limiting dans l'onglet Avancé
NPM n'expose pas de curseur de rate limiting dans son interface de base, mais vous pouvez injecter la directive Nginx dans l'onglet « Advanced » du proxy host concerné. Déclarez une zone partagée dans la configuration custom : limit_req_zone $binary_remote_addr zone=api:10m rate=30r/m; puis appliquez-la : limit_req zone=api burst=10 nodelay;. Cela limite chaque IP à 30 requêtes par minute avec un burst de 10, ce qui suffit à écrêter le scraping ou les tentatives de brute-force sur un formulaire de connexion sans bloquer les utilisateurs légitimes.
Dépannage des erreurs courantes
Voici les cinq problèmes les plus fréquents rencontrés après une installation de NPM, avec leur diagnostic direct.
Erreurs courantes et leurs causes
- 502 Bad Gateway : NPM ne joint pas votre conteneur. Vérifiez en premier que le conteneur applicatif tourne (
docker ps) et qu'il est bien sur le même réseau Docker que NPM (docker network inspect proxy). Vérifiez ensuite que leForward Hostnamecorrespond exactement au nom du service déclaré dans le Compose de l'application. - Certificat SSL en attente ou erreur ACME : Let's Encrypt doit pouvoir joindre votre serveur sur le port 80 via le domaine déclaré. Vérifiez que le DNS A pointe vers la bonne IP, que le port 80 n'est pas bloqué par le pare-feu du VPS ou par un filtre réseau amont, et que le domaine se résout depuis l'extérieur (
dig app.votre-domaine.com). - Conteneur inaccessible via le nom DNS Docker : si vous ciblez
monapp:3000et obtenez une erreur de résolution, la conteneurmonappn'est pas sur le même réseau que NPM. Ajoutez le réseauproxydans le Compose de l'application et recréez les conteneurs (docker compose up -d --force-recreate). - Redirection infinie HTTP→HTTPS : cela arrive quand l'application elle-même effectue sa propre redirection HTTPS en plus de celle de NPM. Ajoutez dans l'onglet Avancé :
proxy_set_header X-Forwarded-Proto $scheme;pour que l'application connaisse le protocole réel. - Interface d'administration inaccessible après redémarrage : assurez-vous que le service NPM a la directive
restart: unless-stoppeddans votre Compose. Sans elle, Docker ne relancera pas le conteneur après un reboot du VPS.
Nginx Proxy Manager face à Traefik
| Critère | Nginx Proxy Manager | Traefik |
|---|---|---|
| Configuration | Interface web visuelle, aucun fichier à éditer | Fichiers YAML et labels Docker |
| Courbe d'apprentissage | Faible, accessible sans expérience Nginx | Plus raide, orientée DevOps |
| SSL Let's Encrypt | Automatique via l'interface, wildcard possible | Automatique via configuration |
| Découverte de services | Manuelle (nom de conteneur ou IP:port) | Automatique via labels Docker |
| Idéal pour | Quelques services gérés manuellement, setup clair | Environnements dynamiques et nombreux conteneurs |
| Consommation RAM | Très faible | Faible |
| Logs par hôte | Consultables dans l'interface | Via stack de logs externe |
| Gestion des accès | Access Lists intégrées (IP, mot de passe) | Middlewares à configurer |
Quand envisager Traefik ou Caddy
NPM convient parfaitement pour un parc de services stable dont le nombre reste maîtrisé. Dès que vous gérez des déploiements dynamiques — conteneurs qui apparaissent et disparaissent automatiquement, comme en environnement Kubernetes ou avec des pipelines CI/CD qui créent des previews à la volée — Traefik devient plus adapté : sa découverte de services via les labels Docker évite de retourner dans l'interface pour chaque nouveau conteneur. Caddy est une bonne alternative si vous cherchez la simplicité de configuration par fichier avec des certificats automatiques, sans interface web. Dans tous les cas, NPM peut coexister avec Traefik ou Caddy sur le même VPS, chacun gérant une partie du trafic — à condition de ne pas mettre deux proxies sur les mêmes ports 80 et 443. Si votre infrastructure grossit au point où vous gérez plusieurs dizaines de services avec des équipes différentes, un maillage de services (Consul Connect, Linkerd) remplace avantageusement l'empilement de proxies.