Tutoriel

Déploiement

Déployer vos applications avec Traefik sur un VPS

Traefik est un reverse proxy et load balancer cloud-native qui découvre vos conteneurs Docker automatiquement et leur attribue routes et certificats SSL sans rechargement manuel. Déployé sur votre VPS, il devient la porte d'entrée unique de toutes vos applications, avec une configuration déclarative par labels Docker. Ce guide installe la branche v3 (v3.7 au moment de l'écriture), avec HTTPS Let's Encrypt, dashboard protégé, HTTP/3, middlewares de production et les pièges à connaître si vous venez de Traefik v2.

11 min de lecture7 étapes
Sommaire· Pourquoi placer Traefik en frontal de votre VPS ?1/13
  1. 01Pourquoi placer Traefik en frontal de votre VPS ?
  2. 02Ce que Traefik apporte concrètement sur un VPS
  3. 03Prérequis
  4. 04Déployer Traefik avec Docker Compose
  5. 05Middlewares utiles en production
  6. 06Cinq middlewares à connaître
  7. 07Activer HTTP/3 (QUIC)
  8. 08Venir de Traefik v2 : ce qui casse
  9. 09Changements cassants de la v3
  10. 10Traefik v3, Nginx ou Caddy devant vos conteneurs
  11. 11Dépannage : les erreurs les plus fréquentes
  12. 12Symptômes et corrections
  13. 13Prochaine étape : durcir la stack

Pourquoi placer Traefik en frontal de votre VPS ?

Quand vous faites tourner plusieurs applications conteneurisées sur un même VPS, gérer manuellement les virtual hosts Nginx et renouveler chaque certificat devient vite ingérable. Traefik résout ce problème en lisant directement les labels de vos conteneurs Docker : vous déclarez une route au moment du docker run ou dans votre docker-compose.yml, et Traefik la configure à chaud, génère le certificat Let's Encrypt et l'expose en HTTPS. Aucun fichier de conf à éditer, aucun reload : tout est dynamique.

Nginx reste un excellent serveur HTTP, mais sa configuration est statique : chaque nouveau service demande un vhost, un nginx -s reload et un outil ACME à part (certbot et sa tâche de renouvellement). Traefik a été pensé pour une topologie qui change sans cesse, ce qui est exactement le cas d'un VPS où l'on ajoute, met à jour et retire des conteneurs chaque semaine. La branche v3, publiée en avril 2024, a stabilisé HTTP/3 et l'export de traces en OpenTelemetry, et durci la syntaxe des règles de routage.

Ce que Traefik apporte concrètement sur un VPS

  • Découverte automatique des conteneurs Docker via le provider Docker (les routes apparaissent sans redémarrage)
  • Certificats SSL Let's Encrypt générés et renouvelés automatiquement (challenges HTTP-01, TLS-ALPN-01 ou DNS-01), renouvelés par défaut 30 jours avant leur expiration
  • Routage par domaine, par chemin ou par en-tête, géré entièrement via les labels Docker
  • Dashboard web intégré pour visualiser routers, services et middlewares en temps réel
  • Middlewares prêts à l'emploi : redirection HTTPS, basic auth, rate limiting, headers de sécurité, compression
  • Load balancing automatique quand vous scalez un service à plusieurs réplicas
  • HTTP/3 (QUIC) activable sur un entrypoint en une option
  • D'autres providers que Docker (Swarm, Kubernetes, Nomad, fichiers) si votre infrastructure grandit

Prérequis

Traefik lui-même est très léger : 1 vCPU et 1 Go de RAM suffisent largement pour le proxy seul, le surcoût venant de vos applications derrière. Prévoyez un VPS sous Debian 12 ou Ubuntu 22.04/24.04 avec Docker Engine et le plugin Docker Compose v2 installés (la commande docker compose, sans tiret), un nom de domaine dont les enregistrements A/AAAA pointent vers l'IP du VPS avant le premier démarrage (sans quoi Let's Encrypt ne peut pas valider le domaine), et les ports 80 et 443 ouverts en entrée dans votre pare-feu (UFW), en TCP, plus 443 en UDP si vous activez HTTP/3. Gardez une adresse e-mail valide pour le compte ACME. Pour les certificats wildcard, il vous faudra aussi un accès API à votre fournisseur DNS.

Déployer Traefik avec Docker Compose

  1. Créer le réseau et l'arborescence

    Créez un réseau Docker partagé que Traefik et vos applications utiliseront, puis un dossier dédié contenant le fichier acme.json (le stockage des certificats et de leurs clés privées) :

    docker network create proxy
    mkdir -p /opt/traefik && cd /opt/traefik
    touch acme.json && chmod 600 acme.json

    Créez le fichier avant le premier démarrage : si le chemin monté n'existe pas, Docker crée un dossier à sa place et Traefik ne peut plus y écrire. Les droits 600 sont exigés : Traefik refuse un fichier lisible par d'autres utilisateurs.

  2. Configurer les entrypoints et le résolveur ACME

    Placez ce fichier dans /opt/traefik/docker-compose.yml. Il déclare deux entrypoints (web sur :80, websecure sur :443), un certificateResolver Let's Encrypt validé par le challenge HTTP, la découverte des conteneurs par le socket Docker monté en lecture seule, et le dashboard :

    services:
      traefik:
        image: traefik:v3.7
        container_name: traefik
        restart: unless-stopped
        ports:
          - "80:80"
          - "443:443"
          - "443:443/udp"
        command:
          - "--providers.docker=true"
          - "--providers.docker.exposedbydefault=false"
          - "--providers.docker.network=proxy"
          - "--entrypoints.web.address=:80"
          - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
          - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
          - "--entrypoints.websecure.address=:443"
          - "--entrypoints.websecure.http3=true"
          - "[email protected]"
          - "--certificatesresolvers.letsencrypt.acme.storage=/acme.json"
          - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
          - "--api.dashboard=true"
        volumes:
          - "/var/run/docker.sock:/var/run/docker.sock:ro"
          - "./acme.json:/acme.json"
        networks:
          - proxy
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
          - "traefik.http.routers.dashboard.entrypoints=websecure"
          - "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
          - "traefik.http.routers.dashboard.service=api@internal"
          - "traefik.http.routers.dashboard.middlewares=dashboard-auth"
          - "traefik.http.middlewares.dashboard-auth.basicauth.users=admin:$$2y$$05$$REMPLACER_PAR_LE_HASH"
    
    networks:
      proxy:
        external: true

    L'option exposedbydefault=false est essentielle : sans elle, chaque conteneur du VPS serait publié, y compris votre base de données. Épinglez la branche (v3.7) plutôt que latest, et suivez les releases avant de changer de version mineure.

  3. Forcer la redirection HTTP vers HTTPS

    La redirection se déclare directement sur l'entrypoint web, avec les deux options --entrypoints.web.http.redirections.entrypoint.to=websecure et ...entrypoint.scheme=https déjà présentes dans le fichier ci-dessus. C'est plus simple et plus sûr qu'un router « catch-all » avec middleware : tout trafic en clair est basculé en HTTPS par une redirection permanente, sans label à répéter sur chaque service, et le challenge HTTP de Let's Encrypt continue de passer sur le port 80.

  4. Sécuriser le dashboard

    Le dashboard est exposé sur traefik.example.com, derrière le middleware basicauth nommé dashboard-auth. Générez un hash bcrypt (paquet apache2-utils sous Debian/Ubuntu) en doublant les $, comme l'exige une valeur de label dans un fichier Compose :

    apt install -y apache2-utils
    htpasswd -nB admin | sed -e 's/\$/\$\$/g'

    Collez le résultat à la place de admin:$$2y$$05$$REMPLACER_PAR_LE_HASH. Un hash collé avec des $ simples est interprété par Compose comme des variables et casse l'authentification. Ne laissez jamais le flag --api.insecure=true en production : il publie le dashboard sans authentification.

  5. Lancer Traefik

    Démarrez la stack et suivez les logs :

    cd /opt/traefik
    docker compose up -d
    docker compose logs -f traefik

    Vous devez voir le provider Docker démarrer, puis le router dashboard s'attacher, sans erreur ACME. Pendant vos essais, ajoutez temporairement --certificatesresolvers.letsencrypt.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory : le serveur staging de Let's Encrypt délivre des certificats non reconnus par les navigateurs, mais vous protège du rate limit de production si une configuration échoue en boucle. Retirez l'option et videz acme.json avant le passage en production.

  6. Connecter une application

    Chaque application vit dans son propre docker-compose.yml, rattachée au réseau proxy et décrite par ses labels :

    services:
      app:
        image: ghcr.io/example/app:1.0.0
        restart: unless-stopped
        networks:
          - proxy
        labels:
          - "traefik.enable=true"
          - "traefik.http.routers.app.rule=Host(`app.example.com`)"
          - "traefik.http.routers.app.entrypoints=websecure"
          - "traefik.http.routers.app.tls.certresolver=letsencrypt"
          - "traefik.http.services.app.loadbalancer.server.port=3000"
    
    networks:
      proxy:
        external: true

    Au docker compose up -d, Traefik détecte le conteneur, obtient le certificat et active la route en quelques secondes, sans toucher à sa propre configuration. Le label loadbalancer.server.port indique le port interne de l'application ; il devient indispensable dès que l'image en expose plusieurs. Le nom du router (app ici) doit être unique sur tout le VPS.

  7. Vérifier le certificat et la redirection

    Contrôlez depuis une machine extérieure au VPS :

    curl -I http://app.example.com
    curl -I https://app.example.com
    dig +short app.example.com

    La première requête doit renvoyer une redirection permanente vers https://, la deuxième un 200 (ou le code de votre application) servi avec un certificat Let's Encrypt valide, et dig doit afficher l'IP du VPS. Le dashboard liste aussi chaque router avec son résolveur de certificat. Un port 80 qui refuse la connexion pointe presque toujours vers le pare-feu.

Middlewares utiles en production

Un middleware Traefik se déclare par label, une seule fois, puis s'attache à un ou plusieurs routers par traefik.http.routers.<router>.middlewares=<nom1>,<nom2>. Vous les définissez donc sur le service concerné, sans toucher à la configuration centrale de Traefik. Voici ceux qui servent sur presque tous les VPS.

Cinq middlewares à connaître

  • BasicAuth sur un outil d'administration (Adminer, Flower…) : traefik.http.middlewares.adminauth.basicauth.users=admin:$$2y$$05$$..., puis traefik.http.routers.monadmin.middlewares=adminauth. Même règle de $ doublés que pour le dashboard.
  • Rate limit devant une API ou un formulaire : traefik.http.middlewares.ratelimit.ratelimit.average=100, ...ratelimit.period=1s et ...ratelimit.burst=200 autorisent 100 requêtes par seconde en moyenne, avec des rafales jusqu'à 200. Sans average, la limite est désactivée.
  • Headers de sécurité : le middleware headers pose HSTS (stsSeconds=31536000, stsIncludeSubdomains=true), X-Frame-Options: DENY (frameDeny=true) et X-Content-Type-Options: nosniff (contentTypeNosniff=true), sans fichier de configuration séparé.
  • Redirection www vers le domaine nu : redirectregex avec regex=^https://www\.(.+), replacement=https://$${1} et permanent=true. Pensez à déclarer les deux hôtes dans la règle du router pour que le certificat couvre www.
  • Compression : traefik.http.middlewares.compress.compress=true active gzip, Brotli et Zstandard selon ce qu'accepte le navigateur, sans réglage côté application.

Pour obtenir un certificat wildcard (*.example.com) et éviter d'exposer chaque sous-domaine, passez du httpChallenge au dnsChallenge : c'est le seul challenge qui délivre un wildcard. Avec Cloudflare, déclarez --certificatesresolvers.letsencrypt.acme.dnschallenge.provider=cloudflare et passez à Traefik la variable CF_DNS_API_TOKEN, un jeton API limité aux permissions Zone / DNS / Edit et Zone / Zone / Read. L'ancien couple CF_API_EMAIL + CF_API_KEY fonctionne aussi, mais il exige la clé API globale, qui ouvre tout le compte : préférez le jeton. Traefik prouve alors la propriété du domaine par un enregistrement TXT, ce qui fonctionne même pour des services non exposés publiquement.

Activer HTTP/3 (QUIC)

Le fichier Compose ci-dessus l'active déjà : --entrypoints.websecure.http3=true sur l'entrypoint TLS, et la publication du port 443:443/udp. Traefik écoute alors en UDP sur le même port que l'entrypoint TCP ; une connexion commence toujours en TCP, puis le navigateur bascule en QUIC au voyage suivant. Deux conditions : seuls les routers en TLS sont servis en HTTP/3, et le pare-feu doit laisser passer le port 443 en UDP (ufw allow 443/udp). Si vous publiez un autre port UDP que celui de l'entrypoint, l'option http3.advertisedPort annonce le bon. Pour vérifier, utilisez un curl compilé avec HTTP/3 : curl --http3 -I https://app.example.com.

Venir de Traefik v2 : ce qui casse

La v3 garde la configuration de routage v2 compatible, mais elle change la syntaxe par défaut des règles et refuse de démarrer sur plusieurs options retirées. Pour migrer sans tout réécrire d'un coup, ajoutez --core.defaultRuleSyntax=v2 dans la configuration d'installation : vos anciennes règles continuent de fonctionner, vous passez les routers un par un à la syntaxe v3, puis vous retirez l'option. Les logs de Traefik signalent chaque option dépréciée encore utilisée : lisez-les après le premier démarrage. Les changements qui piègent le plus souvent :

Changements cassants de la v3

  • Swarm : l'option swarmMode du provider Docker n'existe plus et bloque le démarrage. Docker Swarm a désormais son propre provider (--providers.swarm).
  • Règles de routage : Headers et HeadersRegexp deviennent Header et HeaderRegexp, HostHeader disparaît au profit de Host, et la plupart des matchers n'acceptent plus qu'une valeur.
  • Chemins : Path et PathPrefix ne lisent plus d'expression régulière ni de placeholder comme {id} ; une telle route ne correspond plus à rien. Passez à PathRegexp, qui suit la syntaxe regexp de Go, comme HostRegexp.
  • Middlewares renommés ou allégés : IPWhiteList devient IPAllowList (mêmes options) ; le middleware headers perd sslRedirect, sslTemporaryRedirect, sslHost, sslForceHost et featurePolicy.
  • Content-Type : Traefik ne devine plus le type d'une réponse que le backend n'a pas typée ; ajoutez le middleware ContentType si une application en dépend.
  • Providers et observabilité retirés : Marathon, Rancher v1, Traefik Pilot et les métriques InfluxDB v1 empêchent le démarrage ; le tracing passe uniquement par OpenTelemetry (plus d'export direct vers Jaeger, Zipkin ou Datadog).

Traefik v3, Nginx ou Caddy devant vos conteneurs

Faites défiler le tableau

CritèreTraefik v3NginxCaddy 2
ConfigurationLabels Docker, YAML ou TOML, prise en compte à chaudFichiers vhost statiques, `nginx -s reload` à chaque changementCaddyfile ou API JSON, rechargement sans coupure
HTTPS automatiqueIntégré (ACME : HTTP-01, TLS-ALPN-01, DNS-01)Outil externe (certbot) et tâche de renouvellementIntégré et actif par défaut
Découverte des conteneursNative, par le socket DockerAbsente : outil tiers ou édition manuelleVia le module communautaire caddy-docker-proxy
HTTP/3Stable depuis la v3.0 (avril 2024), une option par entrypointExpérimental depuis nginx 1.25.0 (mai 2023), configuration dédiéeActif par défaut depuis Caddy 2.6 (septembre 2022)
Prise en mainMoyenne : routers, services et middlewares à assimilerConnue de tous, mais HTTPS + Docker demandent de l'outillageLa plus rapide pour quelques sites

Dépannage : les erreurs les plus fréquentes

La plupart des incidents Traefik viennent de quatre sources : le DNS ou le pare-feu qui empêchent la validation Let's Encrypt, le fichier acme.json, un réseau Docker manquant et des labels mal écrits. Les symptômes et leurs corrections :

Symptômes et corrections

  • Certificat non obtenu, erreur ACME unauthorized ou 403 dans les logs : Let's Encrypt n'atteint pas votre domaine. Vérifiez depuis l'extérieur que le port 80 répond (curl -I http://app.example.com) et que le DNS pointe sur le VPS (dig +short app.example.com). Derrière un CDN en mode proxy, préférez le dnsChallenge.
  • permissions 644 for /acme.json are too open, please use 600 : le résolveur refuse le fichier. Corrigez avec chmod 600 /opt/traefik/acme.json puis redémarrez Traefik ; ce contrôle protège les clés privées qui y sont stockées.
  • Route visible dans le dashboard mais 502 Bad Gateway : le conteneur n'est pas sur le réseau proxy, ou le port interne est faux. Vérifiez avec docker inspect <conteneur> (section Networks), ajoutez le réseau ou le label loadbalancer.server.port, puis recréez le conteneur. Sur un conteneur relié à plusieurs réseaux, le label traefik.docker.network=proxy lève l'ambiguïté.
  • Labels ignorés, route absente du dashboard : il manque traefik.enable=true (obligatoire avec exposedbydefault=false), ou deux services déclarent le même nom de router. Les logs de Traefik signalent alors le conflit.
  • BasicAuth qui refuse un bon mot de passe : les $ du hash ne sont pas doublés dans le docker-compose.yml. Dans un fichier Compose, chaque $ devient $$ ; dans un fichier de configuration dynamique YAML ou TOML, le hash se colle tel quel.

Prochaine étape : durcir la stack

Traefik règle le routage et le TLS, mais une stack prête pour la production demande davantage : healthchecks, politique de redémarrage, rotation des logs, secrets hors du fichier Compose, sauvegarde des volumes (dont acme.json). Notre check-list Docker Compose en production reprend ces points un par un. Et si vous hésitez encore sur l'outil, le comparatif Caddy, Traefik et Nginx Proxy Manager aide à trancher selon le nombre de services et le besoin de découverte automatique.

Lancez Traefik en quelques minutes sur un VPS Cloud ServOrbit

Commandez un VPS Cloud avec Docker préinstallé et déployez votre stack Traefik à partir du template Déploiement. Vos applications sont routées en HTTPS automatiquement.