Aller au contenu
medium

Caddy : HTTPS automatique et configuration simple

33 min de lecture

Logo Caddy

Caddy est un serveur web moderne avec HTTPS automatique par défaut. Contrairement à Nginx ou Apache, Caddy obtient et renouvelle vos certificats TLS sans configuration. En 5 minutes, vous pouvez servir un site statique sécurisé ou proxyfier une API.

Niveau : Débutant → Intermédiaire · Durée : 25-35 min

À la fin de ce guide, vous saurez :

  • Servir un site statique avec HTTPS automatique
  • Configurer un reverse proxy vers une application
  • Comprendre le modèle mental du Caddyfile
  • Déboguer les erreurs courantes (ACME, 502)
  • Utiliser tls internal pour les environnements LAN

Caddy s'impose dès que vous avez besoin d'un serveur web simple et sécurisé sans passer des heures sur la configuration TLS. Voici les situations où il fait la différence :

  • Exposer une API ou un dashboard derrière HTTPS sans toucher à certbot ni cron de renouvellement.
  • Servir un site statique (documentation, landing page, blog Hugo/Astro) avec un Caddyfile de 3 lignes.
  • Proxyfier plusieurs applications sur un même serveur (Node, Python, Go) avec routage par domaine ou chemin.
  • Prototyper rapidement un environnement de dev avec tls internal et des certificats auto-signés.
  • Remplacer Nginx sur un petit serveur ou un homelab sans sacrifier les performances.
  • Ajouter des headers de sécurité (HSTS, CSP, X-Frame-Options) en quelques lignes.

Le guide couvre quatre besoins distincts, et chaque lien ci-dessous ouvre directement la section correspondante. Si vous découvrez l'outil, gardez l'ordre : le site statique valide que Caddy lit bien votre configuration, le reverse proxy enchaîne sur un backend réel. Les lecteurs qui butent déjà sur un certificat ACME ou sur un 502 peuvent aller droit au dépannage.

Les deux serveurs traitent le même trafic HTTP ; la différence porte sur ce que vous devez écrire pour y arriver. Caddy embarque un client ACME dans son binaire, là où Nginx délègue l'obtention et le renouvellement des certificats à certbot et à une tâche planifiée. Le tableau compare les points où ce choix d'architecture se voit concrètement, du volume de configuration au support HTTP/3.

CritèreCaddyNginx
HTTPSAutomatique (Let's Encrypt intégré)Manuel (certbot séparé)
ConfigurationLisible (Caddyfile)Verbeux (nginx.conf)
Rechargementcaddy reload sans pertenginx -s reload
HTTP/3NatifModule externe
Courbe d'apprentissage30 min2-3 heures

En résumé : Caddy pour la simplicité, Nginx pour le contrôle fin et l'écosystème mature.

Pour la culture : historique de Caddy

Caddy a été créé par Matt Holt en 2015 avec une vision claire : simplifier la configuration des serveurs web et rendre HTTPS accessible à tous. À l'époque, obtenir un certificat SSL était complexe et coûteux. L'intégration native de Let's Encrypt dans Caddy a démocratisé HTTPS.

Aujourd'hui, Caddy est utilisé en production par de nombreuses entreprises pour sa simplicité et sa robustesse. Il est écrit en Go, ce qui lui confère d'excellentes performances et une facilité de déploiement (un seul binaire).

Avant de plonger dans la configuration, prenons 2 minutes pour comprendre comment Caddy pense. Cette compréhension vous évitera 90% des erreurs.

Le schéma reprend le trajet d'une requête entrante. Le nom de domaine sélectionne le site block, les matchers filtrent ensuite selon le chemin ou la méthode, et un handler produit enfin la réponse. La couche TLS intervient en amont de tout cela et ne se déclare nulle part dans le Caddyfile.

Modèle mental du Caddyfile : site block, handlers et HTTPS automatique

Pourquoi 4 couches ? Chaque requête traverse ces étapes dans l'ordre. Si vous comprenez ce flux, vous comprenez 90% de Caddy.

CoucheRôleExemples
Site blockDéfinit le domaine ou l'adresseexample.com { }, :8080 { }, localhost { }
MatchersFiltrent les requêtes (chemin, méthode, headers)/api/*, @websocket, path /static/*
HandlersTraitent la requêtefile_server, reverse_proxy, respond, redir
RéponseHTTPS activé par défaut si domaine publicTLS auto via Let's Encrypt

Caddy se distribue sous forme d'un binaire Go unique, sans dépendance système à résoudre. Le dépôt officiel ajoute par-dessus l'unit systemd, l'utilisateur de service caddy et les répertoires de données : c'est la méthode à privilégier sur un serveur. L'image Docker convient pour un essai jetable, à condition de monter un volume sur /data, sinon les certificats obtenus sont perdus à chaque recréation du conteneur.

Fenêtre de terminal
# Ajouter le dépôt officiel
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| sudo tee /etc/apt/sources.list.d/caddy-stable.list
# Installer
sudo apt update && sudo apt install caddy
# Le service systemd est configuré automatiquement
sudo systemctl status caddy

Vérification :

Fenêtre de terminal
caddy version
# v2.11.4
# Le Caddyfile par défaut est dans /etc/caddy/Caddyfile
cat /etc/caddy/Caddyfile

Le premier essai se fait volontairement sur le port 8080 en HTTP, sans nom de domaine : c'est le seul moyen de vérifier que Caddy lit bien votre Caddyfile avant d'ajouter la variable TLS à l'équation. Les fichiers doivent être lisibles par l'utilisateur caddy, faute de quoi le serveur répond 403 alors que la configuration est correcte.

  1. Créer le répertoire et le fichier

    Fenêtre de terminal
    sudo mkdir -p /var/www/monsite
    echo '<h1>Hello Caddy!</h1>' | sudo tee /var/www/monsite/index.html
    sudo chown -R caddy:caddy /var/www/monsite
  2. Configurer le Caddyfile

    Fenêtre de terminal
    sudo tee /etc/caddy/Caddyfile << 'EOF'
    # Pour un test local (pas de TLS)
    :8080 {
    root * /var/www/monsite
    file_server
    }
    EOF
  3. Recharger Caddy

    Fenêtre de terminal
    sudo systemctl reload caddy
  4. Tester

    Fenêtre de terminal
    curl http://localhost:8080
    # <h1>Hello Caddy!</h1>

Remplacer :8080 par un nom de domaine change le comportement du bloc entier. Caddy reconnaît un domaine public, déclenche la validation ACME auprès de Let's Encrypt et bascule son écoute sur les ports 80 et 443.

Si votre domaine pointe vers votre serveur :

monsite.com {
root * /var/www/monsite
file_server
}

C'est tout. Caddy :

  • Obtient automatiquement un certificat Let's Encrypt
  • Redirige HTTP → HTTPS
  • Renouvelle le certificat avant expiration

Une application React, Vue ou Angular gère son routage dans le navigateur : le serveur reçoit une requête sur /dashboard alors qu'aucun fichier de ce nom n'existe sur le disque. La directive try_files teste d'abord le chemin réel, puis retombe sur index.html, ce qui laisse le routeur JavaScript afficher la bonne vue au lieu d'un 404.

Pour React, Vue, Angular, etc., fallback vers index.html :

monsite.com {
root * /var/www/spa
try_files {path} /index.html
file_server
}

Cette partie fait passer Caddy du service de fichiers au relais HTTP devant une application qui écoute en local. Le montage est toujours le même : le backend reste sur un port non privilégié comme 3000, Caddy occupe les ports 80 et 443, termine le TLS et transmet la requête en ajoutant les en-têtes qui décrivent le client d'origine.

Un reverse proxy se place devant vos applications et reçoit toutes les requêtes à leur place. Le client ne connaît que lui : il ignore combien de services tournent derrière, sur quels ports et sur quelles machines.

  • Le backend n'est jamais joignable directement, il n'écoute que sur une interface locale
  • Caddy choisit le service de destination d'après le nom de domaine ou le chemin demandé
  • Il enrichit la requête d'en-têtes que le backend ne pourrait pas déduire seul, dont X-Forwarded-For qui porte l'adresse réelle du client

Pourquoi utiliser un reverse proxy ?

Sans reverse proxyAvec reverse proxy (Caddy)
Votre app Node/Python écoute sur le port 80Caddy écoute sur 80/443, votre app sur 3000
Pas de HTTPS (ou config manuelle)HTTPS automatique
Une seule app par serveurPlusieurs apps sur le même serveur
Votre app gère les logs HTTPCaddy centralise les logs

Une seule directive suffit quand il n'y a qu'un backend à desservir. Caddy ouvre une connexion vers localhost:3000 pour chaque requête entrante et relaie la réponse telle quelle, y compris les codes d'erreur produits par l'application.

api.example.com {
reverse_proxy localhost:3000
}

C'est tout. En une ligne, Caddy :

  • Écoute sur api.example.com ports 80 et 443
  • Obtient un certificat HTTPS
  • Transmet les requêtes à votre app sur localhost:3000
  • Ajoute automatiquement les headers Host, X-Forwarded-For, X-Forwarded-Proto

Un même bloc mélange sans problème proxy et fichiers statiques. Caddy classe les directives par spécificité : le matcher /api/* l'emporte sur le file_server qui sert de filet pour tout le reste. C'est le montage typique d'un frontend compilé servi à côté de son API.

example.com {
# L'API sur /api/*
reverse_proxy /api/* localhost:3000
# Le reste en statique
root * /var/www/frontend
file_server
}

Une connexion WebSocket démarre par une requête HTTP ordinaire portant l'en-tête Upgrade. Caddy détecte cet en-tête et bascule la connexion en tunnel bidirectionnel sans directive supplémentaire, là où Nginx exige de propager explicitement Upgrade et Connection dans le bloc location.

example.com {
reverse_proxy /ws/* localhost:3000
}

Caddy gère automatiquement l'upgrade WebSocket. Aucune configuration spéciale n'est nécessaire.

Plusieurs directives to transforment le proxy en répartiteur de charge. La politique round_robin distribue les requêtes à tour de rôle entre les backends déclarés, tandis que le health check interroge /health toutes les 10 secondes et retire du pool celui qui ne répond plus, sans intervention manuelle.

example.com {
reverse_proxy {
to backend1:3000
to backend2:3000
to backend3:3000
lb_policy round_robin
health_uri /health
health_interval 10s
}
}

L'automatisme TLS est l'argument principal de Caddy, et c'est aussi la première source de blocage au démarrage. Cette partie détaille ce que le serveur fait réellement à la première requête sur un domaine, les prérequis DNS et réseau qu'il ne peut pas contourner, puis les deux échappatoires quand ces prérequis ne sont pas réunis : tls internal et le challenge DNS.

Quand vous écrivez example.com { } dans votre Caddyfile, Caddy :

  1. Détecte que c'est un domaine public (pas localhost, pas une IP)
  2. Contacte Let's Encrypt pour prouver que vous contrôlez le domaine
  3. Obtient un certificat valide 90 jours
  4. Configure TLS avec les bonnes options de sécurité
  5. Crée une redirection HTTP → HTTPS automatique
  6. Renouvelle le certificat avant expiration (environ 30 jours avant)

Tout cela sans une seule ligne de configuration TLS.

Caddy retient le mode automatique dès qu'un nom de domaine public apparaît en tête de bloc, sans que rien ne soit écrit. Les deux autres modes se déclarent explicitement avec la directive tls et désactivent toute demande de certificat auprès de Let's Encrypt.

ModeQuand l'utiliserConfiguration
Auto (défaut)Domaine public accessibleexample.com { ... }
InternalRéseau local / développementtls internal
ManuelCertificats existantstls /path/cert.pem /path/key.pem

Un domaine en .local ou .lan n'est validable par aucune autorité publique : aucun serveur ACME ne peut prouver que vous le contrôlez. La directive tls internal fait signer le certificat par la CA interne de Caddy, stockée dans son répertoire de données, ce qui reste utilisable indéfiniment sur un réseau fermé.

Pour un serveur interne sans accès Internet :

intranet.local {
tls internal
reverse_proxy localhost:3000
}

Caddy génère un certificat auto-signé. Important : vous devez installer la CA Caddy dans les navigateurs/clients pour éviter les avertissements de sécurité.

Fenêtre de terminal
# Afficher le chemin de la CA
caddy trust
# Installe la CA dans le trust store système (Linux/macOS)

Le challenge HTTP-01 suppose que Let's Encrypt joigne votre serveur sur le port 80, ce qui devient impossible derrière un NAT et n'a jamais été prévu pour un certificat wildcard. Le challenge DNS-01 contourne le problème en déposant un enregistrement TXT dans votre zone : il faut alors recompiler le binaire avec le module de votre hébergeur DNS à l'aide de xcaddy, le paquet officiel ne l'embarquant pas.

Si les ports 80/443 ne sont pas accessibles (firewall, NAT), utilisez le DNS Challenge :

Fenêtre de terminal
# Compiler Caddy avec le plugin DNS (ex: Cloudflare)
xcaddy build --with github.com/caddy-dns/cloudflare
*.example.com {
tls {
dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}
reverse_proxy localhost:3000
}

Par défaut, Caddy renvoie le code d'erreur sans corps HTML : le navigateur affiche une page vide. Le bloc handle_errors intercepte ces réponses et rejoue le traitement de votre choix. La variable {err.status_code} sépare les erreurs client des erreurs serveur, ici une page 404 servie depuis le disque d'un côté, un message 503 généré à la volée de l'autre.

example.com {
root * /var/www/html
file_server
handle_errors {
@404 expression {err.status_code} == 404
handle @404 {
root * /var/www/errors
rewrite * /404.html
file_server
}
@5xx expression {err.status_code} >= 500
handle @5xx {
respond "Service temporairement indisponible" 503
}
}
}

Chaque configuration ci-dessous est autonome : elle constitue un Caddyfile complet, à copier puis à adapter au domaine et aux chemins réels. Elles couvrent les montages qui reviennent le plus souvent, du file_server seul au strip de préfixe, en passant par les en-têtes de sécurité.

root ne sert rien par lui-même : c'est file_server qui lit et renvoie le fichier correspondant au chemin demandé.

example.com {
root * /var/www/html
file_server
}

Même base, avec try_files intercalé avant file_server pour renvoyer index.html sur toute route absente du disque. Sans cette ligne, un simple rafraîchissement du navigateur sur une route interne se solde par un 404.

example.com {
root * /var/www/app
try_files {path} /index.html
file_server
}

Caddy termine le TLS et transmet en clair vers le port local : l'application n'a aucun certificat à gérer de son côté.

api.example.com {
reverse_proxy localhost:3000
}

Les blocs handle s'excluent mutuellement : la première correspondance gagne, les suivantes sont ignorées pour cette requête. Le handle sans matcher joue le rôle de cas par défaut, il doit donc rester en dernière position.

example.com {
handle /api/* {
reverse_proxy localhost:3000
}
handle {
root * /var/www/frontend
file_server
}
}

handle_path se comporte comme handle mais retire le préfixe de l'URL avant de transmettre la requête. C'est la forme à retenir quand le backend expose ses routes à la racine et ne connaît pas le préfixe /api ajouté côté public.

example.com {
handle_path /api/* {
reverse_proxy localhost:3000
}
}

Pour un service qui n'est jamais joignable depuis Internet. Caddy signe le certificat avec sa CA locale ; tant que caddy trust n'a pas été exécuté sur les postes clients, les navigateurs affichent un avertissement de sécurité parfaitement normal.

intranet.local {
tls internal
reverse_proxy localhost:3000
}

Le cas d'un certificat fourni par l'entreprise ou par une PKI interne. Caddy ne tente alors aucune demande ACME et charge simplement la paire indiquée ; l'utilisateur de service doit pouvoir lire la clé privée, qui reste en mode 0600.

example.com {
tls /etc/ssl/cert.pem /etc/ssl/key.pem
file_server
}

Après un changement de nom de domaine, le placeholder {uri} reporte le chemin et la chaîne de requête sur la nouvelle adresse, au lieu de tout renvoyer vers la page d'accueil. Le mot-clé permanent produit un 301, code que les moteurs de recherche exploitent pour transférer le référencement acquis.

old.example.com {
redir https://new.example.com{uri} permanent
}

La directive header ajoute ces en-têtes à toutes les réponses du bloc. HSTS interdit au navigateur de retenter le HTTP sur ce domaine pendant un an, nosniff l'empêche de deviner le type d'un fichier à partir de son contenu, et DENY bloque l'inclusion du site dans une iframe tierce.

example.com {
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
X-Frame-Options "DENY"
}
file_server
}

L'authentification ne s'applique qu'au matcher indiqué, ici tout ce qui commence par /admin/. Caddy ne stocke jamais le mot de passe en clair dans le Caddyfile : la valeur attendue est un hash bcrypt.

example.com {
basic_auth /admin/* {
admin $2a$14$hash...
}
file_server
}

La directive s'appelle basic_auth depuis Caddy v2.8 (l'ancien basicauth fonctionne encore mais émet un avertissement). Pour générer un hash bcrypt :

Fenêtre de terminal
caddy hash-password
# Entrez le mot de passe, Caddy retourne le hash bcrypt

L'option metrics se déclare dans le bloc global, celui qui n'a pas de nom de domaine et qui s'ouvre avant tous les sites. Aucun réglage n'est ensuite nécessaire dans les blocs de site : la collecte couvre l'ensemble des serveurs déclarés.

{
servers {
metrics
}
}
example.com {
file_server
}

La grande majorité des incidents Caddy vient d'une hypothèse implicite jamais vérifiée : un enregistrement DNS qui ne pointe pas là où on croit, un port filtré en amont du serveur, ou un ordre de directives qui fait capturer la requête par le mauvais handler. Le tableau associe à chaque cause le symptôme observé et la commande qui tranche en une ligne.

ErreurConséquenceSolution
DNS ne pointe pas vers le serveurHTTPS auto échoue (erreur ACME)dig example.com pour vérifier
Ports 80/443 fermésLet's Encrypt ne peut pas validerOuvrir les ports ou utiliser DNS Challenge
Domaine local sans tls internalCaddy tente d'obtenir un certificatAjouter tls internal pour .local, .lan
Oublier handle_path pour stripBackend reçoit /api/users au lieu de /usersUtiliser handle_path /api/* { ... }
Ordre des handlers incorrectUn handler large capture toutPlacer /api/* avant file_server catch-all
Backend downCaddy renvoie 502curl localhost:3000 pour confirmer
https:// dans reverse_proxyErreurs de connexionNe pas mettre https:// sauf si backend l'exige

Caddy journalise dans journald et refuse d'appliquer une configuration invalide : ces deux comportements donnent des points d'entrée fiables pour diagnostiquer. Les échecs ACME et les 502 représentent la quasi-totalité des cas réels, et chacun se confirme en une commande avant toute modification du Caddyfile.

caddy validate analyse la syntaxe sans toucher au service en cours d'exécution : à lancer systématiquement avant un rechargement. Le reload applique ensuite la nouvelle configuration sans couper les connexions établies, contrairement à un restart qui ferme tout.

Fenêtre de terminal
# Valider la configuration
caddy validate --config /etc/caddy/Caddyfile
# Recharger sans downtime
sudo systemctl reload caddy
# Voir les logs
sudo journalctl -u caddy -f
# Formater le Caddyfile (indentation)
caddy fmt --overwrite /etc/caddy/Caddyfile

Chaque ligne part du message effectivement affiché par le serveur, pas d'une hypothèse sur la configuration. La colonne solution indique la vérification à mener avant de modifier le Caddyfile : dans la plupart des cas, le problème est ailleurs que dans la configuration.

ErreurCause probableSolution
ACME challenge failedDNS incorrect ou ports fermésVérifier DNS + ouvrir 80/443
502 Bad GatewayBackend ne répond pascurl localhost:3000 pour tester
too many redirectsBoucle HTTP ↔ HTTPSVérifier la config proxy/CDN
permission deniedCaddy ne peut pas lire les fichierschown -R caddy:caddy /var/www
address already in useAutre service sur le portss -tlnp | grep :80

Un échec d'obtention de certificat laisse toujours une trace explicite dans le journal, à condition de filtrer sur acme. Trois causes reviennent : l'enregistrement DNS absent ou pointant ailleurs, le port 80 fermé côté pare-feu, et le dépassement du rate limit Let's Encrypt, ce dernier imposant d'attendre plutôt que de relancer le service.

Fenêtre de terminal
# Voir les détails de l'erreur
sudo journalctl -u caddy | grep -i acme
# Erreurs typiques :
# - "no valid IP addresses" → DNS pas configuré
# - "connection refused" → port 80 fermé
# - "rate limit" → trop de tentatives (attendre 1h)

Un 502 signifie que Caddy n'a obtenu aucune réponse exploitable du backend, jamais que sa propre configuration est fautive. La séquence ci-dessous isole la responsabilité en trois temps : l'application répond-elle, répond-elle aussi à l'utilisateur caddy (droits, SELinux, socket), et que dit le journal au moment exact de la requête.

Fenêtre de terminal
# 1. Le backend tourne-t-il ?
curl -I http://localhost:3000
# 2. Caddy peut-il joindre le backend ?
sudo -u caddy curl http://localhost:3000
# 3. Regarder les logs
sudo journalctl -u caddy -f

Deux sorties suffisent à suivre un Caddy en production : les logs d'accès au format JSON, exploitables tels quels par Loki ou Elasticsearch sans écrire de parseur, et les métriques Prometheus exposées par l'endpoint d'administration.

Le bloc log se déclare par site, ce qui autorise un fichier distinct par domaine. roll_size et roll_keep activent la rotation interne : Caddy la gère lui-même, il n'y a ni logrotate à configurer, ni signal à envoyer au processus après rotation.

example.com {
log {
output file /var/log/caddy/access.log {
roll_size 100mb
roll_keep 5
}
format json
}
file_server
}

Les compteurs exposés couvrent le nombre de requêtes, leur durée et la répartition des codes de réponse, ventilés par serveur et par handler. Ils suffisent à construire un tableau de bord de latence sans instrumenter l'application elle-même.

Ajoutez dans le bloc global :

{
servers {
metrics
}
}
example.com {
file_server
}

Les métriques Prometheus sont exposées sur le port :2019/metrics par défaut, prêtes à être collectées.

Fenêtre de terminal
curl localhost:2019/metrics

Les tableaux ci-dessous regroupent les directives par usage. Ils servent de rappel une fois le modèle du Caddyfile acquis, pas de documentation exhaustive : chaque directive accepte des options supplémentaires détaillées dans la référence officielle.

Ces directives concernent le service de contenu depuis le disque. root ne sert rien à lui seul, il fixe uniquement le répertoire de base que file_server et try_files utilisent ensuite pour résoudre les chemins.

DirectiveDescription
root * /pathDéfinir la racine des fichiers
file_serverServir les fichiers statiques
file_server browseAvec listing des répertoires
try_files {path} /index.htmlFallback SPA

Les trois formes de reverse_proxy diffèrent par le chemin finalement transmis au backend. Le choix entre le matcher écrit sur la même ligne et le bloc handle_path décide si le préfixe est conservé ou retiré, ce qui explique la plupart des 404 vus côté application.

DirectiveDescription
reverse_proxy localhost:3000Proxy simple
reverse_proxy /api/* localhost:3000Proxy sur un chemin
handle_path /api/* { reverse_proxy ... }Strip le préfixe

La directive tls ne s'écrit que pour sortir du comportement par défaut. L'adresse indiquée sert aux notifications Let's Encrypt, notamment en cas d'échec de renouvellement : c'est le seul canal d'alerte automatique si vous n'en supervisez pas l'expiration.

DirectiveDescription
tls email@example.comHTTPS auto avec email
tls internalCertificat auto-signé (LAN)
tls /cert.pem /key.pemCertificats manuels

header ajoute un en-tête aux réponses, et le préfixe - en supprime un, ce qui permet de retirer la bannière Server. encode négocie la compression avec le client selon ce qu'il annonce accepter, gzip ou zstd, et laisse les contenus déjà compressés intacts.

DirectiveDescription
header X-Custom "value"Ajouter un header
header -ServerSupprimer un header
basic_auth /admin/* { user hash }Auth basique
encode gzip zstdCompression

redir renvoie une réponse de redirection au navigateur : l'URL change dans la barre d'adresse et une seconde requête part. rewrite modifie le chemin en interne, le client n'en voit rien. Confondre les deux est la cause classique de la boucle too many redirects.

DirectiveDescription
redir /old /new permanentRedirection 301
rewrite /old /newRéécriture interne
respond "OK" 200Réponse directe
handle_errors { ... }Pages d'erreur custom

Ces sous-commandes s'exécutent indépendamment de systemd. caddy reload applique la nouvelle configuration sans fermer les connexions en cours, et conserve l'ancienne si le fichier est invalide.

CommandeDescription
caddy validate --config /etc/caddy/CaddyfileValider la config
caddy fmt --overwrite CaddyfileFormater
caddy reloadRecharger la config
caddy hash-passwordGénérer un hash bcrypt
caddy trustInstaller la CA interne

Les points ci-dessous concentrent ce qui sépare une configuration Caddy stable d'une configuration qui casse au premier renouvellement de certificat ou au premier déploiement du backend.

  1. HTTPS automatique : fonctionne si DNS + ports 80/443 accessibles
  2. tls internal : pour les environnements LAN sans accès Internet
  3. caddy validate : toujours valider avant de recharger
  4. handle_path : pour strip le préfixe URL avant le backend
  5. Ordre des handlers : spécifique → générique
  6. Logs : journalctl -u caddy -f pour déboguer

Caddy couvre les besoins courants d'un serveur unique. Passer à Nginx apporte un contrôle plus fin sur le cache et les modules, tandis que Traefik prend le relais dès que la configuration doit être découverte depuis Docker ou Kubernetes plutôt qu'écrite dans un fichier.

La référence des directives liste les options que cet aide-mémoire laisse de côté, et la page HTTPS automatique détaille les cas de figure ACME peu courants. Le dépôt caddy-dns recense les modules disponibles pour le challenge DNS, à compiler avec xcaddy.

Ces réponses reprennent en format court les points traités plus haut : structure du Caddyfile, fonctionnement du HTTPS automatique, mise en place d'un reverse proxy, et diagnostic des erreurs ACME ou 502. Elles servent de vérification rapide après lecture.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn