Pierry Lim

Configurer un reverse proxy avec Nginx ou Traefik

· Mis à jour le 17 janvier 2026 · 12 min de lecture
Nginx
Traefik
Reverse Proxy
DevOps
HTTPS

Guide complet pour configurer un reverse proxy : Nginx vs Traefik, HTTPS avec Let's Encrypt, load balancing, exemples pratiques pour héberger plusieurs applications.

Configurer un reverse proxy avec Nginx ou Traefik

Sommaire

Introduction

Vous développez plusieurs applications et vous voulez les héberger sur le même serveur ? Vous en avez marre de retenir les ports 3000, 8080, 4000 ? Un reverse proxy est la solution !

Dans ce guide, nous allons voir comment configurer Nginx ou Traefik pour héberger plusieurs services derrière un seul domaine, avec HTTPS automatique et une configuration propre.

Qu’est-ce qu’un reverse proxy ?

Le principe de base

Un reverse proxy agit comme un intermédiaire entre vos utilisateurs et vos applications :

Utilisateur → Internet → Reverse Proxy → Applications

                          monsite.com

              App1:3000    App2:4000    API:8080

Différence avec un proxy classique

Proxy classique (forward proxy) :

Client → Proxy → Internet → Serveur
(cache, anonymat, filtrage)

Reverse proxy :

Client → Internet → Reverse Proxy → Serveurs internes
(load balancing, SSL termination, routing)

Cas d’usage courants

1. Hébergement multi-applications :

blog.monsite.com → App blog (port 3000)
api.monsite.com  → API REST (port 8080)
app.monsite.com  → SPA React (port 4000)

2. Load balancing :

monsite.com → [Serveur 1, Serveur 2, Serveur 3]

3. SSL Termination :

HTTPS → Reverse Proxy → HTTP (interne)

Nginx vs Traefik : lequel choisir ?

CritèreNginxTraefik
ComplexitéConfiguration manuelleAuto-découverte
PerformanceExcellentTrès bon
HTTPSCertbot requisLet’s Encrypt intégré
DockerConfig externeLabels sur conteneurs
MonitoringModules tiersDashboard intégré
FlexibilitéMaximumBonne
Courbe d’apprentissageRaideDouce

Choisir Nginx si :

  • Performance critique
  • Configuration très spécifique
  • équipe expérimentée
  • Infrastructure statique

Choisir Traefik si :

  • Environnement Docker
  • Configuration dynamique
  • HTTPS automatique important
  • équipe débutante

Configuration avec Nginx

Installation et setup de base

Sur Ubuntu/Debian :

# Installation
sudo apt update
sudo apt install nginx

# Démarrage et activation
sudo systemctl start nginx
sudo systemctl enable nginx

# Vérification
sudo nginx -t
curl http://localhost

Structure des fichiers :

/etc/nginx/
  nginx.conf                 # Configuration principale
  sites-available/           # Configurations de sites
    default
    monsite.com
  sites-enabled/             # Liens symboliques actifs
  conf.d/                    # Configurations modulaires

Configuration multi-services

Scénario : 3 applications sur le même serveur

  • Frontend React (port 3000)
  • API Node.js (port 8080)
  • Admin Panel (port 4000)

Configuration /etc/nginx/sites-available/monsite.com :

server {
    listen 80;
    server_name monsite.com www.monsite.com;
    
    # Logs
    access_log /var/log/nginx/monsite_access.log;
    error_log /var/log/nginx/monsite_error.log;
    
    # Frontend principal
    location / {
        proxy_pass http://localhost:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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_cache_bypass $http_upgrade;
    }
    
    # API
    location /api/ {
        proxy_pass http://localhost:8080/;
        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;
        
        # Headers CORS si nécessaire
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
        add_header Access-Control-Allow-Headers "Authorization, Content-Type";
        
        # Gestion preflight OPTIONS
        if ($request_method = OPTIONS) {
            return 204;
        }
    }
    
    # Panel admin
    location /admin/ {
        proxy_pass http://localhost:4000/;
        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;
        
        # Protection basique
        # auth_basic "Zone Restreinte";
        # auth_basic_user_file /etc/nginx/.htpasswd;
    }
    
    # Assets statiques avec cache
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        expires 1M;
        add_header Cache-Control "public, immutable";
    }
    
    # Gestion des erreurs
    error_page 502 503 504 /50x.html;
    location = /50x.html {
        root /var/www/html;
    }
}

Activation du site :

# Créer le lien symbolique
sudo ln -s /etc/nginx/sites-available/monsite.com /etc/nginx/sites-enabled/

# Tester la configuration
sudo nginx -t

# Recharger Nginx
sudo systemctl reload nginx

HTTPS avec Let’s Encrypt

Installation de Certbot :

sudo apt install certbot python3-certbot-nginx

Obtenir et configurer le certificat :

# Obtenir le certificat SSL
sudo certbot --nginx -d monsite.com -d www.monsite.com

# Renouvellement automatique
sudo crontab -e
# Ajouter :
0 12 * * * /usr/bin/certbot renew --quiet

Configuration HTTPS générée par Certbot :

server {
    listen 443 ssl http2;
    server_name monsite.com www.monsite.com;
    
    ssl_certificate /etc/letsencrypt/live/monsite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/monsite.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
    # Configuration proxy identique...
}

# Redirection HTTP → HTTPS
server {
    listen 80;
    server_name monsite.com www.monsite.com;
    return 301 https://$server_name$request_uri;
}

Load balancing

Configuration upstream :

# Définir le groupe de serveurs
upstream app_backend {
    # Stratégies de répartition
    # ip_hash;           # Session sticky
    # least_conn;        # Moins de connexions
    # random;            # Aléatoire
    
    server localhost:3000 weight=3 max_fails=3 fail_timeout=30s;
    server localhost:3001 weight=2 max_fails=3 fail_timeout=30s;
    server localhost:3002 weight=1 backup;  # Serveur de secours
}

server {
    listen 443 ssl http2;
    server_name monsite.com;
    
    location / {
        proxy_pass http://app_backend;
        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;
        
        # Health check
        proxy_next_upstream error timeout http_500 http_502 http_503;
        proxy_connect_timeout 5s;
        proxy_send_timeout 10s;
        proxy_read_timeout 10s;
    }
}

Configuration avec Traefik

Installation Docker

Structure des fichiers :

traefik/
  docker-compose.yml
  traefik.yml
  acme.json

docker-compose.yml :

services:
  traefik:
    image: traefik:v3.0
    container_name: traefik
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard (à sécuriser en prod)
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./traefik.yml:/traefik.yml:ro
      - ./acme.json:/acme.json
    networks:
      - proxy
    labels:
      # Dashboard
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.monsite.com`)"
      - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
      - "traefik.http.routers.dashboard.service=api@internal"
      # Protection dashboard
      - "traefik.http.middlewares.auth.basicauth.users=admin:$$2y$$10$$..."
      - "traefik.http.routers.dashboard.middlewares=auth"

  # Application exemple
  frontend:
    image: node:18-alpine
    container_name: frontend
    working_dir: /app
    volumes:
      - ./frontend:/app
    command: npm start
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.frontend.rule=Host(`monsite.com`, `www.monsite.com`)"
      - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
      - "traefik.http.services.frontend.loadbalancer.server.port=3000"

  api:
    image: node:18-alpine
    container_name: api
    working_dir: /app
    volumes:
      - ./api:/app
    command: npm start
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.monsite.com`)"
      - "traefik.http.routers.api.tls.certresolver=letsencrypt"
      - "traefik.http.services.api.loadbalancer.server.port=8080"

networks:
  proxy:
    external: true

Configuration automatique

traefik.yml :

# Points d'entrée
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ":443"

# Providers
providers:
  docker:
    watch: true
    exposedByDefault: false
    network: proxy

# Let's Encrypt automatique
certificatesResolvers:
  letsencrypt:
    acme:
      email: [email protected]
      storage: acme.json
      httpChallenge:
        entryPoint: web

# API et Dashboard
api:
  dashboard: true
  insecure: false  # HTTPS uniquement

# Logs
log:
  level: INFO
accessLog: {}

# Métriques (optionnel)
metrics:
  prometheus:
    addEntryPointsLabels: true
    addServicesLabels: true

HTTPS automatique

Préparation du fichier acme.json :

# Créer le fichier avec les bonnes permissions
touch acme.json
chmod 600 acme.json

Traefik s’occupe automatiquement :

  1. Demande des certificats Let’s Encrypt
  2. Renouvellement automatique
  3. Redirection HTTP → HTTPS
  4. HSTS headers

Dashboard et monitoring

Accès sécurisé au dashboard :

# Générer un hash pour le mot de passe
htpasswd -nb admin monmotdepasse
# admin:$2y$10$...

# Ou avec Python
python3 -c "import bcrypt; print(bcrypt.hashpw(b'motdepasse', bcrypt.gensalt()).decode())"

Middleware de sécurité :

# Dans docker-compose.yml ou fichier de config
labels:
  - "traefik.http.middlewares.secure-headers.headers.SSLRedirect=true"
  - "traefik.http.middlewares.secure-headers.headers.STSSeconds=31536000"
  - "traefik.http.middlewares.secure-headers.headers.contentTypeNosniff=true"
  - "traefik.http.middlewares.secure-headers.headers.browserXSSFilter=true"

Sécurité et optimisations

Sécurité Nginx

Configuration SSL durcie :

# /etc/nginx/conf.d/ssl.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/monsite.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;

# Headers de sécurité
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;

Rate limiting :

# Dans http {}
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;

# Dans server {}
location /api/ {
    limit_req zone=api burst=20 nodelay;
    proxy_pass http://localhost:8080/;
}

location /login {
    limit_req zone=login burst=3;
    proxy_pass http://localhost:3000/login;
}

Optimisations performances

Compression Nginx :

# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/x-javascript
    application/xml+rss
    application/javascript
    application/json;

Cache Nginx :

# Définir zone de cache
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;

# Utiliser le cache
location /api/public/ {
    proxy_cache my_cache;
    proxy_cache_valid 200 302 10m;
    proxy_cache_valid 404 1m;
    proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
    proxy_pass http://localhost:8080/;
}

Troubleshooting

Problèmes courants Nginx

1. Erreur 502 Bad Gateway

# Vérifier que l'application tourne
curl http://localhost:3000

# Vérifier les logs Nginx
sudo tail -f /var/log/nginx/error.log

# Vérifier la config
sudo nginx -t

2. Certificat SSL invalide

# Vérifier le certificat
sudo certbot certificates

# Renouveler si expiré
sudo certbot renew

# Vérifier la config SSL
openssl s_client -connect monsite.com:443 -servername monsite.com

3. Configuration non prise en compte

# Recharger la config
sudo nginx -s reload

# Ou redémarrer complètement
sudo systemctl restart nginx

Problèmes courants Traefik

1. Service non accessible

# Vérifier les logs Traefik
docker logs traefik

# Vérifier le dashboard
http://traefik.monsite.com

# Vérifier le réseau Docker
docker network ls
docker network inspect proxy

2. Certificat Let’s Encrypt non obtenu

# Vérifier les permissions acme.json
ls -la acme.json  # Doit être 600

# Vérifier les logs
docker logs traefik | grep -i certificate

# Vérifier la config ACME
cat traefik.yml | grep -A 10 certificatesResolvers

FAQ

Peut-on utiliser Nginx ET Traefik ensemble ?

Oui, mais c’est généralement inutile. Cas d’usage possible :

  • Nginx pour les sites statiques/PHP
  • Traefik pour les applications Docker
  • Nginx en upstream de Traefik pour la performance

Comment migrer de Nginx vers Traefik ?

Plan de migration :

  1. Installer Traefik en parallèle (port 8080)
  2. Migrer service par service
  3. Basculer le DNS
  4. Désactiver Nginx

Traefik avec labels équivalents :

# Nginx: location /api/ { proxy_pass http://localhost:8080/; }
labels:
  - "traefik.http.routers.api.rule=Host(`monsite.com`) && PathPrefix(`/api/`)"
  - "traefik.http.middlewares.api-strip.stripprefix.prefixes=/api"
  - "traefik.http.routers.api.middlewares=api-strip"

Comment gérer plusieurs domaines avec Traefik ?

labels:
  - "traefik.http.routers.frontend.rule=Host(`monsite.com`, `www.monsite.com`, `monsite.fr`)"
  - "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
  # Certificat SAN automatique pour tous les domaines

Performance : Nginx vs Traefik ?

Benchmarks typiques :

  • Nginx : ~50,000 req/s (statique), ~10,000 req/s (proxy)
  • Traefik : ~30,000 req/s (statique), ~8,000 req/s (proxy)

Mais Traefik compense par :

  • Configuration zéro
  • Auto-discovery
  • Métriques intégrées

Comment gérer les WebSockets ?

Nginx :

location /socket.io/ {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

Traefik :

# Traefik gère automatiquement les WebSockets
labels:
  - "traefik.enable=true"
  - "traefik.http.routers.socketio.rule=Host(`monsite.com`)"
  # Aucune config spéciale nécessaire !

Le reverse proxy transforme complètement la façon dont vous hébergez vos applications. Nginx pour la performance maximale, Traefik pour la simplicité : les deux sont excellents selon vos besoins !

Travaillons ensemble

Vous cherchez un développeur freelance pour créer un site web ou une application sur mesure ? Contactez-moi pour discuter de votre projet et obtenir un devis personnalisé.