SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor

Installer Certbot Apache sur Ubuntu 24.04

Installez Certbot 2.9.0 avec apt sur Ubuntu 24.04, sans snap, puis activez HTTPS en une commande. Évitez l’erreur ServerName et le port 80 fermé.

Ce que vous allez mettre en place

Un site Apache sur Ubuntu 24.04, accessible en HTTPS avec un certificat Let’s Encrypt gratuit et approuvé par les navigateurs. Certbot délivre le certificat. Un timer systemd le renouvelle automatiquement, sans intervention ultérieure. La commande qui effectue le travail tient sur une ligne. Les problèmes surviennent avant cette ligne : vhost sans ServerName, port 80 fermé par le pare-feu du fournisseur, DNS qui pointe encore vers l’ancien serveur. Ce guide consacre donc l’essentiel de son contenu aux prérequis et indique le message d’erreur exact affiché par chaque erreur de configuration.

Deux précisions sur le périmètre. Si votre serveur web est nginx, le déroulement général est similaire, mais le plugin et les fichiers de configuration diffèrent. Utilisez plutôt la version de ce guide pour nginx. Si le service à sécuriser est réservé au réseau interne, par exemple un panneau d’administration sur une adresse privée ou un serveur de staging que personne d’autre ne consulte, vous n’avez pas besoin d’une autorité de certification. Un certificat autosigné nécessite moins de configuration et fonctionne hors ligne.

Prérequis et trois façons dont la procédure échoue avant même le lancement de Certbot

  • Apache doit déjà servir votre site en HTTP simple. Le plugin Apache de Certbot modifie un site existant ; il n’en crée pas. Si vous partez d’un VPS vierge, mettez d’abord en place la pile LAMP sur Ubuntu 24.04, puis revenez ici : ce guide en constitue le chapitre TLS manquant.
  • Un domaine public doit disposer d’un enregistrement A pointant vers l’adresse de votre VPS. Le challenge HTTP-01 de Let’s Encrypt signifie que ses serveurs de validation se connectent à votre serveur depuis Internet : pas de homelab derrière NAT sans redirection de port, pas de noms .local, pas d’adresses IP seules. dig +short example.com doit renvoyer l’adresse de votre VPS et, si vous avez modifié le DNS au cours de la dernière heure, attendez l’expiration du TTL de l’ancien enregistrement avant de lancer l’émission.
  • Si un enregistrement AAAA existe, il doit être correct. Let’s Encrypt privilégie IPv6 lorsqu’un enregistrement AAAA est publié. Un enregistrement AAAA obsolète fait donc échouer la validation, même si curl fonctionne correctement depuis votre ordinateur portable, probablement en IPv4. Publiez un enregistrement AAAA correct ou n’en publiez aucun.

Les ports 80 et 443 doivent être ouverts dans ufw et dans le firewall réseau de votre fournisseur. La plupart des panneaux d’hébergement disposent d’un second firewall que le système d’exploitation ne voit jamais. HTTP-01 utilise spécifiquement le port 80 pour la validation ; vous ne pouvez pas exécuter cette procédure uniquement sur 443.

sudo ufw allow "Apache Full"
sudo ufw status

Une fois ces conditions réunies, l’ensemble de la procédure prend quinze minutes, dont dix à lire.

Certbot via Snap ou apt ? Sur 24.04, apt convient enfin

Certbot est passé à la distribution via Snap il y a plusieurs années pour une bonne raison : les paquets des distributions s’étaient figés. Ubuntu 20.04 fournissait Certbot 0.40 et n’a jamais évolué, et le projet en a eu assez de devoir corriger des bugs vieux de cinq ans. Sur 24.04, cette raison n’existe plus : l’archive fournit Certbot 2.9.0, une version publiée en février 2024 dans la branche moderne 2.x, et unattended-upgrades installe toutes les mises à jour de sécurité qu’Ubuntu publie pour ce paquet. Le projet amont est depuis passé à la série 5.x, mais ce guide n’en a pas besoin. Pour ce système d’exploitation, je recommande donc apt. Vous évitez le daemon snapd, le plugin Apache est installé dans la même transaction et le timer de renouvellement s’intègre à systemd selon le fonctionnement habituel de Debian.

sudo apt update
sudo apt install -y certbot python3-certbot-apache
certbot --version

Résultat attendu : certbot 2.9.0. Le paquet python3-certbot-apache est le plugin qui lit et modifie vos configurations Apache. Sans lui, certbot --apache échoue avec The requested apache plugin does not appear to be installed.

Snap reste le bon choix dans deux cas : vous voulez utiliser la version la plus récente de Certbot dès sa publication, ou vous avez besoin d’un plugin DNS distribué uniquement sous forme de Snap, comme plusieurs plugins de fournisseurs certbot-dns-*. Si vous choisissez cette solution :

sudo apt remove -y certbot python3-certbot-apache
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Quel que soit votre choix, n’exécutez jamais les deux installations. Deux installations signifient deux planificateurs de renouvellement qui se disputent /etc/letsencrypt, et le certbot que votre shell trouve dans PATH n’est peut-être pas celui qui gère vos certificats. La ligne apt remove ci-dessus n’est pas facultative.

Les vhosts que Certbot modifie doivent déjà exister, le ServerName est déterminant

certbot --apache fonctionne en recherchant le virtual host sur le port 80 dont ServerName ou ServerAlias correspond à chaque domaine -d que vous indiquez. Il prouve ensuite que vous contrôlez le domaine, puis crée une copie SSL de ce vhost. Sans ServerName correspondant, aucune correspondance n’est trouvée. De plus, le 000-default.conf fourni par Ubuntu contient ServerName commenté. Cette seule ligne commentée est la cause la plus fréquente de l’échec de la commande unique de ce guide.

Avant d’utiliser Certbot, configurez donc un vhost basé sur le nom pour le site. Créez /etc/apache2/sites-available/example.com.conf :

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com
    ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
    CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>

Activez-le et vérifiez qu’Apache l’analyse correctement et qu’il dirige bien le nom vers ce vhost :

sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo apache2ctl -S

configtest doit afficher Syntax OK. S’il affiche également AH00558: apache2: Could not reliably determine the server's fully qualified domain name, il s’agit d’un avertissement concernant le ServerName global, et non votre vhost. Cet avertissement est sans conséquence ici. Vous pouvez le supprimer avec echo "ServerName $(hostname -f)" | sudo tee /etc/apache2/conf-available/servername.conf && sudo a2enconf servername && sudo systemctl reload apache2.

La sortie de -S est le contrôle important. Vous devez obtenir une ligne telle que port 80 namevhost example.com (/etc/apache2/sites-enabled/example.com.conf:1), avec alias www.example.com en dessous. Apache indique le lien symbolique sites-enabled qu’il a réellement lu, et non le fichier que vous avez modifié dans sites-available. Si example.com n’apparaît pas pour le port 80, Certbot ne le trouvera pas non plus.

Émettre le certificat : certbot --apache

sudo certbot --apache -d example.com -d www.example.com

Au premier lancement, trois éléments vous sont demandés : une adresse e-mail (Let’s Encrypt ne l’enregistre plus avec votre compte ACME et n’envoie plus d’avertissements d’expiration ; c’est donc à vous de surveiller les renouvellements), l’acceptation des conditions de Let’s Encrypt et l’autorisation de partager votre adresse e-mail avec l’EFF. La question concernant la redirection n’existe plus : depuis Certbot 1.0, l’installeur Apache redirige par défaut HTTP vers HTTPS (la question elle-même a été supprimée dans la version 1.4), ce qui correspond au comportement recherché. Utilisez --no-redirect si vous devez réellement continuer à servir du contenu en HTTP simple.

Le résultat doit ressembler à ceci. Lisez-le attentivement, sans vous contenter de le parcourir :

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2027-01-09.

Deploying certificate
Successfully deployed certificate for example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Successfully deployed certificate for www.example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.com

Derrière ce message, Certbot a effectué quatre opérations : il a activé le module Apache ssl s’il ne l’était pas déjà, il a écrit example.com-le-ssl.conf, une copie de votre vhost dans *:443 avec SSLEngine on et les chemins des certificats, il l’a activée, puis il a ajouté un bloc RewriteRule au vhost d’origine sur le port 80 afin de rediriger tout le trafic vers HTTPS avec le code 301. Votre fichier vhost d’origine est modifié, pas remplacé, et le jumeau SSL se trouve à côté. Vous pouvez donc lire chaque ligne ajoutée.

Emplacement réel du certificat et raison pour laquelle vous ne devez jamais le copier

Tout est placé sous /etc/letsencrypt/live/example.com/ : fullchain.pem (le certificat et la chaîne intermédiaire, vers lesquels les serveurs doivent pointer), privkey.pem (la clé privée, lisible uniquement par root), ainsi que cert.pem et chain.pem pour les logiciels qui veulent ces éléments séparément. Il s’agit de liens symboliques vers /etc/letsencrypt/archive/. Cette indirection assure le renouvellement : le renouvellement écrit les nouveaux fichiers dans archive/, puis réoriente les liens symboliques. Faites pointer les autres logiciels vers les chemins live/. Ils utiliseront alors automatiquement les certificats renouvelés. Si vous copiez les fichiers ailleurs, vous provoquez une interruption de service 90 days plus tard.

L’autre fichier à connaître est /etc/letsencrypt/renewal/example.com.conf. Il indique comment ce certificat a été émis, authenticator = apache, installer = apache, ainsi que les domaines. Le renouvellement peut ainsi répéter le processus sans intervention, notamment recharger Apache ensuite.

Le renouvellement est déjà planifié : vérifiez-le, ne le recréez pas

Les certificats Let’s Encrypt sont actuellement valides pendant 90 jours par conception, et le paquet apt a déjà installé le mécanisme nécessaire : un timer systemd qui exécute Certbot deux fois par jour à des heures aléatoires et renouvelle tout certificat arrivant à expiration dans les 30 jours. N’ajoutez pas de tâche cron en plus : un second planificateur n’apporte rien, si ce n’est du bruit dans les journaux et un risque supplémentaire de limitation de débit. Let’s Encrypt a annoncé qu’à partir du 10 février 2027, les nouveaux certificats auront par défaut une durée de validité de 64 jours. La fenêtre de 30 jours reste adaptée à ces certificats ; le renouvellement aura simplement lieu vers le 34e jour au lieu du 60e. Il n’y a donc rien à modifier sur ce serveur.

systemctl list-timers certbot.timer
sudo certbot renew --dry-run

La première commande affiche le timer actif, avec une heure NEXT située dans les 24 prochaines heures. La planification s’exécute deux fois par jour avec un délai aléatoire ; l’heure exacte est donc volontairement imprévisible (avec l’installation snap, le timer est snap.certbot.renew.timer à la place). Le dry run effectue une répétition complète du renouvellement auprès de l’environnement de staging de Let’s Encrypt, avec un vrai challenge mais sans émission de certificat ni consommation de quota de limitation de débit. Un résultat correct se termine par :

Congratulations, all simulated renewals succeeded:
  /etc/letsencrypt/live/example.com/fullchain.pem (success)

Si le dry run échoue, le renouvellement réel échouera de la même manière dans environ 60 jours. Corrigez le problème maintenant, tant que le certificat actuel est encore loin de son expiration. La cause la plus fréquente est une règle de firewall ajoutée après l’émission du certificat, qui a de nouveau fermé le port 80.

Vérifier avec curl et ce que doit afficher le cadenas

curl -sI http://example.com | head -n 3
curl -I https://example.com
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer -dates

La première commande doit renvoyer HTTP/1.1 301 Moved Permanently avec un en-tête Location: https://example.com/. Il s’agit de la redirection installée par Certbot. La deuxième doit renvoyer HTTP/1.1 200 OK sans avertissement TLS de la part de curl. La troisième affiche l’émetteur, une ligne O = Let's Encrypt avec un CN court comme YE1 ou YE2 (clés ECDSA), ou YR1 ou YR2 (clés RSA), ainsi qu’une date d’expiration située environ notAfter plus tard. Un certificat émis avant que Let's Encrypt ne retire ses anciennes autorités intermédiaires peut encore afficher un CN comme R12 ou E7 jusqu’à son prochain renouvellement ; ce n’est pas une erreur. Dans un navigateur, le cadenas s’affiche et un clic dessus montre le même émetteur. Si curl fonctionne mais que le navigateur affiche un avertissement, vous consultez presque certainement une page mise en cache ou le mauvais nom d’hôte, et non un problème de certificat.

Plusieurs sites : un certificat SAN ou un certificat par site

Les deux méthodes fonctionnent et se renouvellent de la même façon. Pour des sites sans lien entre eux sur le même serveur, exécutez la commande d’émission une fois par site. Chaque site possède son propre répertoire sous live/ et sa propre configuration de renouvellement. Un problème avec un domaine ne bloque donc jamais le renouvellement des autres. C’est l’approche que j’utilise par défaut.

Pour un seul site avec plusieurs noms, regroupez-les dans un certificat SAN. Un seul certificat peut contenir jusqu’à 100 noms. Vous l’avez déjà fait plus haut avec example.com et www.example.com. Pour ajouter ultérieurement un nom à un certificat existant, réémettez-le en indiquant le nom du certificat et la liste complète des nouveaux noms :

sudo certbot --apache --cert-name example.com -d example.com -d www.example.com -d blog.example.com

Certbot détecte la modification de l’ensemble des domaines, vous demande de confirmer l’extension, puis remplace le certificat sur place, au même emplacement live/. Aucune autre modification n’est donc nécessaire. Notez que la liste remplace la liste précédente : si vous omettez www de cette commande, le nouveau certificat le supprime sans avertissement.

Les wildcards nécessitent DNS-01, et vous n’avez généralement pas besoin d’un wildcard

HTTP-01 ne peut pas émettre *.example.com : placer un fichier sur un serveur web prouve le contrôle d’un seul nom d’hôte, pas celui de tout un espace de noms. Les wildcards nécessitent le challenge DNS-01 : Certbot crée un enregistrement TXT à l’emplacement _acme-challenge.example.com. En pratique, il faut donc un plugin certbot-dns-* avec des identifiants d’API pour votre fournisseur DNS, ou modifier manuellement les enregistrements TXT à chaque renouvellement avec --manual (une solution pénible, sur laquelle il ne faut pas baser votre configuration). Le guide complet, de la gestion des enregistrements TXT jusqu’à un plugin qui renouvelle les certificats sans intervention, se trouve dans certificats wildcard avec Certbot via DNS-01. Conseil pratique : si vous avez quatre sous-domaines connus, un certificat SAN qui les liste tous les quatre est plus simple qu’un wildcard et ne nécessite pas de conserver des clés d’API DNS sur le serveur.

Modes d’échec et messages affichés

Certbot refuse de démarrer parce que la configuration d’Apache est incorrecte.

The apache plugin is not working; there may be problems with your existing configuration.
The error was: MisconfigurationError('Error while running apache2ctl configtest.\n\nAction \'configtest\' failed.\nThe Apache error log may have more information.\n\nAH00526: Syntax error on line 12 of /etc/apache2/sites-enabled/example.com.conf')

Le plugin exécute configtest avant toute autre opération et s’arrête si Apache rencontre un problème. Les \n sont littéraux, car Certbot affiche la représentation de l’exception. Exécutez vous-même sudo apache2ctl configtest : la commande indique le fichier et la ligne concernés. Il s’agit généralement d’une faute de frappe après une modification manuelle, d’un SSLCertificateFile qui pointe vers un chemin inexistant, ou d’un module référencé mais non activé. Corrigez la configuration jusqu’à ce que la commande affiche Syntax OK, puis relancez Certbot.

Aucun vhost ne correspond au domaine.

Unable to find a virtual host listening on port 80 which is currently the only challenge port.

Il s’agit de l’échec lié à l’absence de ServerName mentionné plus haut, détecté au moment de l’émission. Certbot a recherché dans tous les vhosts du port 80 activés un ServerName/ServerAlias correspondant à votre -d, mais n’a rien trouvé. sudo apache2ctl -S indique le routage réel d’Apache. Ajoutez la ligne ServerName au bon vhost, rechargez la configuration, puis réessayez. Un problème proche se produit lorsque la validation atteint le mauvais vhost : la réponse au challenge revient Invalid response ... 404, car un autre site a traité la requête. Le diagnostic et l’outil sont les mêmes : apache2ctl -S.

La validation expire.

Certbot failed to authenticate some domains (authenticator: apache).
...
Detail: ...: Timeout during connect (likely firewall problem)

Let’s Encrypt n’a pas pu ouvrir de connexion TCP vers le port 80 à l’adresse annoncée par votre DNS. Par ordre de probabilité : le pare-feu réseau de votre fournisseur, distinct d’ufw et configuré dans le panneau d’hébergement ; un ensemble de règles ufw qui n’autorise que 443 ou uniquement SSH ; un DNS qui pointe encore vers un ancien serveur ; ou le problème d’un ancien enregistrement AAAA : leurs serveurs ont essayé IPv6, mais le vôtre ne répond qu’en IPv4. Testez depuis l’extérieur du VPS : curl -I http://example.com depuis votre ordinateur portable reproduit ce que voit leur validateur.

Vous avez atteint une limite de débit en réessayant trop souvent.

Error creating new order :: too many failed authorizations (5) for "example.com" in the last 1h0m0s, retry after ... UTC: see https://letsencrypt.org/docs/rate-limits/...

Let’s Encrypt autorise 5 validations échouées par nom d’hôte, par compte et par heure, sous la forme d’un quota qui se reconstitue progressivement et récupère environ une tentative toutes les 12 minutes. Réessayer sans arrêt contre un pare-feu incorrect épuise rapidement ce quota. Attendre fonctionne, mais la véritable correction concerne la méthode : après chaque échec, effectuez le diagnostic avec l’environnement de staging jusqu’à obtenir un succès.

sudo certbot certonly --apache --dry-run -d example.com -d www.example.com

Notez le certonly : --dry-run n’est accepté que par les sous-commandes certonly et renew, et la forme simple certbot --apache --dry-run refuse totalement de s’exécuter en indiquant --dry-run currently only works with the 'certonly' or 'renew' subcommands. La simulation valide la configuration auprès du staging, qui possède ses propres limites généreuses et ne délivre aucun certificat réel. Vous pouvez donc y provoquer des échecs toute l’après-midi. Ne relancez la commande réelle qu’une fois le staging validé. Les autres limites — 50 certificats par domaine enregistré et par semaine, et 5 certificats identiques pour le même ensemble de noms par semaine — ne seront atteintes que si un script renouvelle les certificats en boucle.

Une fois HTTPS opérationnel, souvenez-vous que le certificat sécurise le transport, pas le serveur : le port 22 continue de recevoir des tentatives de mot de passe toute la journée. Associer cette configuration à Fail2ban sur Ubuntu 24.04 est la prochaine étape logique de trente minutes.

FAQ

Dois-je installer Certbot avec snap ou apt pour Apache sur Ubuntu 24.04 ?

Utilisez apt. Ubuntu 24.04 fournit Certbot 2.9.0, une version suffisamment récente pour tout ce qui est présenté dans ce guide. Elle reçoit les mises à jour de sécurité publiées par Ubuntu via unattended-upgrades et ne nécessite pas snapd. Choisissez snap uniquement si vous avez besoin immédiatement de la dernière version ou d’un plugin DNS distribué exclusivement sous forme de snap. Si vous changez de méthode, apt remove certbot python3-certbot-apache d’abord afin que deux planificateurs de renouvellement ne fonctionnent jamais simultanément.

Pourquoi Certbot indique-t-il « Unable to find a virtual host listening on port 80 » ?

Aucun vhost activé sur le port 80 ne contient de ServerName ou de ServerAlias correspondant au domaine fourni avec -d. Le vhost par défaut d’Ubuntu fournit ServerName commenté. Exécutez sudo apache2ctl -S, trouvez ou créez le vhost qui doit gérer ce nom, ajoutez ServerName example.com, rechargez Apache, puis relancez Certbot.

Comment corriger « Timeout during connect (likely firewall problem) » ?

Let’s Encrypt n’a pas pu atteindre le port 80 à l’adresse publiée par votre DNS. Vérifiez le firewall réseau configuré dans le panneau de votre fournisseur ainsi que ufw. Confirmez que dig +short example.com renvoie vers ce VPS et supprimez ou corrigez tout enregistrement AAAA obsolète. La validation privilégie IPv6 lorsqu’une adresse IPv6 existe. Vérifiez la correction depuis l’extérieur du serveur avec curl -I http://example.com, puis effectuez un test avec sudo certbot certonly --apache --dry-run -d example.com avant l’émission réelle du certificat.

Certbot renouvelle-t-il automatiquement les certificats sur Ubuntu 24.04 ?

Oui. Le paquet apt installe certbot.timer, un timer systemd qui s’exécute deux fois par jour et renouvelle tout certificat dont l’expiration intervient dans les 30 jours. Il recharge ensuite Apache. Le snap utilise snap.certbot.renew.timer pour la même tâche. Vérifiez avec systemctl list-timers certbot.timer et effectuez un test avec sudo certbot renew --dry-run. N’ajoutez pas votre propre tâche cron en plus.

Comment obtenir un certificat wildcard avec Certbot et Apache ?

Les certificats wildcard nécessitent le challenge DNS-01. Certbot doit créer un enregistrement TXT à _acme-challenge.example.com. Il faut donc utiliser un plugin certbot-dns-* avec les identifiants API de votre fournisseur DNS. L’alternative --manual nécessite de modifier manuellement les enregistrements TXT à chaque renouvellement. Si vous ne disposez que de quelques sous-domaines connus, un certificat SAN qui les énumère explicitement est plus simple. Il évite également de conserver les clés API DNS sur le serveur.