Cours Ubuntu 26.04 / Obtenir un certificat HTTPS et surveiller son renouvellement
Pour activer HTTPS sur un site Nginx Ubuntu, préparez un domaine public qui atteint réellement le serveur, obtenez le certificat avec Certbot, puis vérifiez son renouvellement et le certificat présenté aux visiteurs. Une émission réussie ne suffit pas : la résolution DNS, les accès nécessaires à la validation et la surveillance de l’expiration doivent continuer à fonctionner.
Préparer le domaine, les accès et le serveur public
Ce cours prolonge la configuration des sites Nginx, mais les noms .test et l’écoute 127.0.0.1:8080 du laboratoire précédent ne permettent pas une validation publique HTTP-01. Utilisez une VM ou un serveur dédié à cet exercice, un domaine que vous contrôlez, un accès sudo et une console de secours.
HTTPS associe HTTP au protocole TLS, qui chiffre la connexion et authentifie le serveur au moyen d’un certificat. ACME est le protocole utilisé par Certbot pour demander et renouveler les certificats ; la validation prouve le contrôle du nom demandé, pas la fiabilité de tout le contenu du site.
- Dans le DNS faisant autorité, faites pointer A vers l’adresse IPv4 publique du serveur. Publiez AAAA uniquement si IPv6 atteint aussi le bon serveur.
- Vérifiez les redirections de ports, le pare-feu du fournisseur et le pare-feu Ubuntu. HTTP-01 doit être joignable publiquement sur TCP 80 ; le service HTTPS doit ensuite être accessible sur TCP 443.
- Gardez les règles nécessaires à SSH et testez une nouvelle connexion d’administration avant toute modification des accès.
- Inspectez les sites existants, les écoutes et les sauvegardes ; ne détournez pas le domaine d’un service en production pour cet exercice.
La documentation des types de validation Let’s Encrypt distingue HTTP-01 de DNS-01. HTTP-01 utilise un jeton sous /.well-known/acme-challenge/ sur le port 80 et ne délivre pas de certificat générique. DNS-01 peut convenir à un nom générique ou à un serveur non accessible sur 80 ; son automatisation exige un greffon ou des hooks adaptés au fournisseur DNS et des identifiants strictement limités.
Créer un site HTTP complet avant la demande
Installez Nginx et les outils du laboratoire si nécessaire, puis examinez les sorties. Sur une machine existante, identifiez les installations et services déjà présents avant d’ajouter des paquets :
sudo apt update
sudo apt install nginx curl openssl dnsutils
sudo nginx -t
sudo nginx -T
sudo ss -lntp
sudo ufw status verbose
Enregistrez le script complet ci-dessous dans prepare-public-http.sh. Il crée une racine et une configuration nouvelles, refuse leurs collisions, puis sauvegarde /etc/nginx dans un répertoire privé. La validation du nom est seulement syntaxique ; elle ne vérifie ni sa propriété ni son DNS. Le script attend un nom ASCII réel, éventuellement sa forme Punycode, sans schéma ni chemin.
set -euo pipefail
if [ "$#" -ne 1 ]; then
printf 'Usage: bash prepare-public-http.sh YOUR_DOMAIN\n' >&2; exit 2
fi
domain=$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')
if [[ ! "$domain" =~ ^([a-z0-9]([a-z0-9-]*[a-z0-9])?\.)+[a-z]([a-z0-9-]*[a-z0-9])?$ ]]; then
printf 'Use a valid ASCII hostname you control.\n' >&2; exit 2
fi
case "$domain" in
*.test|*.invalid|*.localhost|*.example|example.com|*.example.com|example.net|*.example.net|example.org|*.example.org)
printf 'Use your real domain, not an example name.\n' >&2; exit 2 ;;
esac
if (( ${#domain} > 253 )); then
printf 'Hostname too long.\n' >&2; exit 2
fi
IFS=. read -r -a labels <<< "$domain"
for label in "${labels[@]}"; do
if (( ${#label} > 63 )); then
printf 'Hostname label too long.\n' >&2; exit 2
fi
done
site=/etc/nginx/sites-available/ubuntu-course-public
enabled=/etc/nginx/sites-enabled/ubuntu-course-public
root_dir=/srv/ubuntu-course-public
for path in "$site" "$enabled" "$root_dir"; do
if sudo test -e "$path" || sudo test -L "$path"; then
printf 'Existing lab path: %s; stop and inspect.\n' "$path" >&2; exit 1
fi
done
backup_dir=$(sudo mktemp -d /root/nginx-before-public.XXXXXX)
sudo cp -a /etc/nginx "$backup_dir/"
sudo install -d -m 0755 "$root_dir"
printf 'public-http-lab\n' | sudo sh -c 'set -C; cat > "$1/index.html"' sh "$root_dir"
sudo chmod 0644 "$root_dir/index.html"
sudo sh -c 'set -C; cat > "$1"' sh "$site" <<EOF
server {
listen 80;
listen [::]:80;
server_name $domain;
root /srv/ubuntu-course-public;
index index.html;
location / {
try_files \$uri \$uri/ =404;
}
}
EOF
sudo ln -sT "$site" "$enabled"
sudo nginx -t
sudo systemctl reload nginx
printf 'HTTP site prepared; backup: %s\n' "$backup_dir"
Exécutez-le dans Bash en saisissant votre domaine :
read -r -p 'Domaine public contrôlé : ' domain
bash prepare-public-http.sh "$domain"
La directive [::]:80 suppose IPv6 disponible sur le serveur. Si cette écoute n’est pas prise en charge, adaptez le fichier avant validation et ne publiez pas d’enregistrement AAAA inutilisable. Le script s’arrête sur une erreur ; si la validation échoue après création du lien, ne rechargez pas en ignorant le problème. Inspectez le fichier et retirez seulement le lien de cet exercice si vous devez annuler son activation.
Sur un serveur dont UFW est déjà actif, autorisez les ports publics nécessaires seulement après avoir préservé SSH, puis contrôlez les nouvelles règles. Les règles du fournisseur et du routeur restent indépendantes :
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw status verbose
Depuis un client situé hors du réseau du serveur, consultez A et AAAA et faites une requête HTTP. Ressaisissez la variable domain dans chaque nouveau terminal, car celle du script enfant n’est pas transmise au shell parent :
read -r -p 'Domaine public contrôlé : ' domain
dig +short A "$domain"
dig +short AAAA "$domain"
curl --noproxy '*' --fail --show-error "http://$domain/"
Le contenu attendu est public-http-lab. Une requête locale ou un fichier hosts modifié ne prouve pas la résolution publique. Si un mandataire inverse ou un réseau de diffusion de contenu intervient, identifiez où la validation et TLS se terminent ; ce cours suppose que Nginx reçoit directement les connexions publiques. Avec plusieurs serveurs frontaux, tous doivent pouvoir répondre au défi.
Installer une seule méthode Certbot et demander le certificat
Les instructions officielles Certbot pour Nginx avec Snap décrivent l’installation classique. Vérifiez d’abord si Certbot est déjà fourni par APT, Snap ou une autre méthode ; une migration doit conserver les certificats, les paramètres et la planification existants. N’ajoutez pas un second mécanisme de renouvellement sans examiner le premier.
command -v certbot
snap list certbot
dpkg-query -W certbot python3-certbot-nginx
systemctl list-timers --all
Une commande peut signaler l’absence du paquet : lisez son résultat au lieu de considérer l’ensemble comme un script à exécuter sans contrôle. Sur cette VM neuve équipée de snapd, sans autre installation Certbot à migrer, installez le paquet puis appelez son chemin explicite :
sudo snap install --classic certbot
sudo /snap/bin/certbot --version
Le mode classic donne un accès étendu au système ; choisissez l’éditeur officiel et évitez les paquets homonymes. Le chemin /snap/bin/certbot permet ici de savoir quelle installation est invoquée sans remplacer un lien existant dans /usr/local/bin.
Avant la demande, conservez une seconde sauvegarde privée, propre à l’état HTTP validé :
(
set -eu
backup_dir=$(sudo mktemp -d /root/nginx-before-https.XXXXXX)
sudo cp -a /etc/nginx "$backup_dir/"
printf 'Sauvegarde : %s/nginx\n' "$backup_dir"
sudo nginx -t
)
read -r -p 'Domaine public contrôlé : ' domain
sudo /snap/bin/certbot --nginx -d "$domain"
sudo nginx -t
Le greffon Nginx peut modifier la configuration et installer HTTPS. Lisez les écrans interactifs : indiquez une adresse de contact suivie, examinez les conditions du service et choisissez la redirection HTTP vers HTTPS en fonction du site. N’ajoutez pas un second nom avec -d tant que son DNS et sa validation ne sont pas prêts. Une erreur ne se résout pas en répétant rapidement les demandes ; corrigez sa cause et tenez compte des limites de l’autorité.
Vérifier le nom, la chaîne et la réponse du site
Depuis le client externe, contrôlez la réponse HTTPS et, si vous avez choisi une redirection, la réponse HTTP initiale. N’utilisez pas -k pour contourner une erreur de confiance :
read -r -p 'Domaine public contrôlé : ' domain
curl --noproxy '*' --fail --show-error "https://$domain/"
curl --noproxy '*' -I "http://$domain/"
openssl s_client -connect "$domain:443" -servername "$domain" \
-verify_hostname "$domain" -verify_return_error < /dev/null
Attendez le contenu du bon site, une chaîne approuvée et un certificat correspondant au nom. -servername envoie le nom SNI pour sélectionner le site TLS ; -verify_hostname vérifie ce nom et -verify_return_error rend les erreurs de vérification bloquantes. Le manuel openssl s_client précise ces comportements. La seule présence d’un certificat dans /etc/letsencrypt ne prouve pas qu’il est servi sur Internet.
Si IPv4 et IPv6 sont publiés, testez les deux chemins avec curl -4 et curl -6 depuis un client qui possède ces connectivités. Comparez aussi les noms supplémentaires demandés et les éventuels autres serveurs frontaux. Un seul résultat réussi ne couvre pas tous les points d’entrée.
Tester le renouvellement et contrôler sa planification
Relevez le Certificate Name exact affiché par Certbot, qui peut différer du domaine. Testez ensuite seulement ce certificat :
sudo /snap/bin/certbot certificates
read -r -p 'Certificate Name exact : ' cert_name
sudo /snap/bin/certbot renew --cert-name "$cert_name" --dry-run
systemctl list-timers --all
sudo journalctl --since '7 days ago' --no-pager
Le guide de renouvellement Certbot documente le réemploi des paramètres et le test. Avec le serveur ACME standard, --dry-run utilise la plate-forme d’essai et ne remplace pas le certificat de production. Examinez toutefois tout serveur personnalisé, les hooks et les options existants : ce test peut recharger Nginx et modifier temporairement sa configuration.
Dans la liste des minuteurs, identifiez l’unité réellement installée pour Certbot, son prochain déclenchement et le service qu’elle lance. Consultez ensuite systemctl status et journalctl -u avec ces noms exacts, ainsi que /var/log/letsencrypt/letsencrypt.log. Ne supposez pas que les noms d’unités APT et Snap sont identiques. Un test manuel réussi ne garantit ni l’exécution du minuteur ni la réussite future après un changement DNS ou de pare-feu.
Surveiller l’expiration réellement présentée et traiter les échecs
Ne fixez pas une durée de validité supposée : lisez notAfter et mettez une alerte avant cette date. Ce bloc Bash récupère le certificat public servi, contrôle la chaîne et le nom, puis vérifie un seuil d’exemple de sept jours. Il crée uniquement un nouveau répertoire privé de résultats dans le dossier personnel :
(
set -euo pipefail
umask 077
read -r -p 'Domaine public contrôlé : ' domain
cert_dir=$(mktemp -d "$HOME/tls-check.XXXXXX")
openssl s_client -connect "$domain:443" -servername "$domain" \
-verify_hostname "$domain" -verify_return_error < /dev/null \
| openssl x509 -out "$cert_dir/served.pem"
openssl x509 -in "$cert_dir/served.pem" -noout -subject -issuer -dates
openssl x509 -in "$cert_dir/served.pem" -noout -checkend 604800
printf 'Certificat public conservé : %s/served.pem\n' "$cert_dir"
)
Selon le manuel openssl x509, -checkend renvoie un état non nul si l’expiration arrive dans le délai demandé. Grâce à pipefail, un échec de connexion ne devient pas un succès parce que la dernière commande a réussi. Le seuil de sept jours est un exemple d’alerte, pas la durée du certificat ni une politique suffisante pour tous les services.
Automatisez séparément la remontée des échecs de renouvellement et un contrôle externe du certificat présenté. Vérifiez le canal d’alerte et son destinataire ; un journal jamais consulté ne prévient personne. Après renouvellement, contrôlez aussi que Nginx ou le frontal a chargé le nouveau certificat.
En cas d’échec, examinez DNS A/AAAA, accès 80 pour HTTP-01, horloge, limites d’émission, configuration Nginx et journaux avant de relancer. Conservez /etc/letsencrypt et ses clés privées dans une sauvegarde protégée, jamais dans la racine publique. Pour annuler une modification Nginx, comparez les fichiers à la sauvegarde et restaurez seulement ceux concernés, puis validez et rechargez. Ne restaurez pas aveuglément tout /etc/nginx si d’autres changements sont intervenus et ne supprimez pas manuellement les certificats utilisés par d’autres sites.




