Devclic
 

De Nginx à Caddy : pourquoi nous avons changé de serveur web

Nginx fait partie des outils que nous utilisons depuis très longtemps. Il est rapide, éprouvé, et il a tenu sans broncher derrière une bonne partie de nos services. Pourtant, nous avons décidé de migrer nos frontaux vers Caddy.

Ce n’est pas un problème de performance qui nous a poussés à changer, mais plutôt tout ce qu’il y a autour : la gestion des certificats, la configuration de nos services gRPC et la verbosité des fichiers de configuration. Voici ce qui a fait pencher la balance.

Des certificats Let’s Encrypt qui se gèrent tout seuls

Avec Nginx, le HTTPS reposait chez nous sur le duo classique : Nginx d’un côté, certbot de l’autre, une tâche planifiée pour renouveler les certificats et un rechargement de Nginx derrière. Ça fonctionne, mais ce sont autant de pièces qui peuvent casser sans prévenir : un cron qui ne tourne plus, un hook de rechargement oublié, un nouveau vhost ajouté sans demander son certificat…

Caddy prend le problème à l’envers : le HTTPS est activé par défaut. Dès qu’un nom de domaine apparaît dans la configuration, Caddy :

  • demande lui-même le certificat auprès de Let’s Encrypt via le protocole ACME ;
  • le renouvelle automatiquement bien avant son expiration, sans aucune intervention ;
  • redirige tout seul le HTTP vers le HTTPS ;
  • recharge le certificat à chaud, sans coupure pour les visiteurs.

Plus de certbot, plus de cron, plus de « le certificat a expiré ce week-end ». Et c’est d’autant plus important que la durée de vie des certificats publics va continuer de baisser dans les années à venir : un renouvellement 100 % automatique n’est plus un confort, c’est une nécessité.

Une syntaxe beaucoup plus concise

Pour exposer un service en HTTPS derrière Nginx, il nous fallait un bloc pour le port 80 (la redirection), un bloc pour le port 443, les chemins des certificats, les protocoles TLS, les en-têtes à transmettre… Voici un exemple simplifié de ce que nous avions :

server {
    listen 80;
    server_name www.exemple.fr;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.exemple.fr;

    ssl_certificate     /etc/letsencrypt/live/www.exemple.fr/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.exemple.fr/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    location / {
        proxy_pass http://app: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;
    }
}

Et voici l’équivalent avec Caddy :

www.exemple.fr {
    reverse_proxy app:8080
}

C’est tout. La redirection HTTP vers HTTPS, le certificat, des paramètres TLS modernes et les en-têtes X-Forwarded-* sont gérés par défaut. Sur l’ensemble de nos vhosts, la configuration a fondu et surtout, elle se relit d’un coup d’œil. Pour ce qui se répète d’un site à l’autre (en-têtes de sécurité, logs, compression), les snippets de Caddy permettent de tout factoriser :

(commun) {
    encode zstd gzip
    header Strict-Transport-Security "max-age=31536000"
    log
}

www.exemple.fr {
    import commun
    reverse_proxy app:8080
}

gRPC : enfin sans prise de tête

Une partie de nos services internes communiquent en gRPC. gRPC repose sur HTTP/2, et il faut que le proxy sache parler HTTP/2 jusqu’au backend, y compris en clair (h2c) lorsque le service tourne sans TLS sur notre réseau interne.

Avec Nginx, gRPC impose ses propres directives (grpc_pass, grpc_set_header, réglages de timeouts spécifiques pour les flux longs…), différentes de celles du reverse proxy HTTP classique. Avec Caddy, c’est le même reverse_proxy que pour n’importe quel site, il suffit d’indiquer le schéma h2c:// :

api.exemple.fr {
    reverse_proxy h2c://grpc-svc:50051
}

Le client parle gRPC en HTTPS avec un certificat Let’s Encrypt valide, Caddy termine le TLS et transmet en HTTP/2 au service. Les appels en streaming fonctionnent sans configuration supplémentaire. Si le backend est lui-même en TLS, on remplace simplement h2c:// par https://.

HTTP/3 activé par défaut

HTTP/3, qui repose sur QUIC (et donc UDP), améliore nettement l’expérience sur les réseaux instables, notamment en mobilité : établissement de connexion plus rapide et pas de blocage de toute la connexion quand un paquet se perd.

Nginx sait aujourd’hui faire de l’HTTP/3, mais il faut un binaire compilé avec le support QUIC, une directive listen 443 quic par vhost et l’en-tête Alt-Svc à ajouter soi-même. Avec Caddy, HTTP/3 est actif par défaut, sans une ligne de configuration. Seul point à ne pas oublier : ouvrir le port 443 en UDP sur les pare-feux, en plus du 443 en TCP.

Nos conseils pour la migration

La migration s’est faite service par service, sans big bang. Quelques points qui nous ont été utiles :

  • Testez avec l’environnement de staging de Let’s Encrypt (directive acme_ca) le temps de valider la configuration, pour ne pas atteindre les limites de requêtes de l’environnement de production.
  • Persistez le répertoire de données de Caddy (le volume /data en conteneur) : c’est là que sont stockés les certificats et les comptes ACME. Le perdre, c’est redemander tous les certificats au redémarrage.
  • Validez avant de recharger avec caddy validate, puis caddy reload qui applique la nouvelle configuration sans couper les connexions en cours. caddy fmt garde des fichiers propres et homogènes.
  • Pour les certificats wildcard, le challenge DNS est nécessaire : il faut alors une version de Caddy compilée avec le module de votre fournisseur DNS (via xcaddy).

En résumé

Nginx reste un excellent serveur web, mais pour notre usage — beaucoup de vhosts en HTTPS, des services gRPC et l’envie de proposer HTTP/3 partout — Caddy nous fait gagner un temps précieux. Moins de configuration à écrire, moins de pièces à surveiller, et surtout des certificats Let’s Encrypt dont nous n’avons plus à nous soucier.

Vous avez un projet d’hébergement ou de migration de votre infrastructure web ? Parlons-en, notre équipe se fera un plaisir de vous accompagner.