Let's Encrypt Renewal

Let's Encrypt Renewal

Dorénavant, il vous est maintenant recommandé d'utiliser le client certbot* plutôt que le script letsencrypt.sh (comme ci-dessous) pour mettre en place et renouveler vos certificats Let's Encrypt. + d'infos

J'ai rédigé un autre article sur l'installation et la configuration de Let's Encrypt

Depuis novembre 2015 j'utilise les services de Let's Encrypt pour certifier mes connexions HTTPS, sur Nefald.fr et Hiob.fr entre autre. C'est très simple d'utilisation, libre et gratuit. Seulement du fait de la beta il est nécessaire de renouveler tous les trois mois ses certificats... et trois mois, ça passe vite.

La première fois que j'ai du renouveler ceux de Nefald je l'ai fait manuellement avec la méthode standalone, Let's Encrypt utilise alors son propre serveur web. Il me suffisait d'arrêter le serveur NGinx et de lancer l'opération de renouvellement ce qui peut en rebuter plus d'un lorsque ceux-ci sont en production.

Ce coup-ci je n'ai plus envie de m’embêter et préfère automatiser proprement tout ça au moyen de scripts et notamment de la méthode webroot, reposant sur le protocole ACME pour Automatic Certificate Management Environment.

Le principe est simple, Let's Encrypt va installer des fichiers dans un dossier accessible depuis le web afin de permettre l'authentification de votre serveur et des certificats.

Il va vous falloir configurer un poil NGinx pour le faire pointer sur un webroot, créer une configuration pour le renouvellement des certificats et automatiser tout ça avec Cron.

NGinx

Commençons par indiquer à NGinx un répertoire où Let's Encrypt pourra vous authentifier en toute tranquillité.
Sur Nefald nous utilisons moult sous-domaines, git.nefald.fr, jenkins.nefald.fr, map.nefald.fr, etc. Personnellement j'ai préféré créé un répertoire dédié à Let's Encrypt dans /var/www/ avec des sous-dossiers pour chaque domaine de deuxième niveau. Tel quel:

Ce n'est pas une précaution nécessaire mais au moins avec ça, nous avons le cœur net en ce qui concerne l'espace de travail de chacun de nos domaines.

1 - créons les dossiers en question

sudo mkdir /var/www/letsencrypt/domaine.ext

Éditons les configurations NGinx de vos différents sites de sorte à indiquer pour chaque domaines et sous-domaines le root fraîchement créé.

2 - Partons du principe que vous utiliser un fichier de configuration dédié pour chaque domaine de deuxième niveau, ses sous-domaines compris, localisé dans /etc/nginx/sites-available/. Ouvrons-le ...

sudo nano /etc/nginx/sites-available/domaine.ext

... et éditons-le afin d'y ajouter la location qui suit sous chaque nom de domaine:

    location '/.well-known/acme-challenge' {
        root /var/www/letsencrypt/domaine.ext/;
        try_files $uri /$1;
    }

De telle sorte:

server {
    listen 80;
    server_name domaine.ext sous.domaine.ext;
    return 301 https://$host$request_uri;
}

server {

    listen 443;
    server_name domaine.ext sous.domaine.ext;
    location '/.well-known/acme-challenge' {
      root /var/www/letsencrypt/domaine.ext/;
      try_files $uri /$1;
      }
}

Vous remarquerez que nous avons fait une redirection permanente (301) du HTTP vers le HTTPS.

On sauvegarde, on teste et on relance NGinx

sudo nginx -t
sudo service nginx restart

Voilà.
L'opération est on ne peut plus simple, il suffit de l'appliquer à chacun de vos sites. Attention aux coquilles et aux doublons, votre redirection HTTPS pourrait sauter (ça m'est arrivé).

Let's Encrypt

Si comme moi lors de la première mise en place de Let's Encrypt vous n'aviez pas pas indiquer l'option --renew-by-default dans votre commande, il va vous falloir créer le fichier de configuration nécessaire par vous-même. C'est toujours plus sympa au sens où vous saurez comment tout cela fonctionne.

1 - Créons-le ...

sudo nano /usr/local/etc/letsencrypt/domaine.ext.ini

...et indiquons-y ce qui suit

# We use a 4096 bit RSA key instead of 2048
rsa-key-size = 4096

email = mail@domaine.ext
domains = domaine.ext,www.domaine.ext

authenticator = webroot

# This is the webroot directory of your domain in which
# letsencrypt will write a hash in /.well-known/acme-challenge directory.
webroot-path = /var/www/letsencrypt/domaine/

Techniquement tout devrait fonctionner tel quel, il vous suffit de taper la commande suivante pour renouveler vos certificats selon le fichier de configuration créé ci-dessus:

./letsencrypt-auto certonly --webroot --agree-tos --renew-by-default --config /usr/local/etc/letsencrypt/domaine.ext.ini
  • --webroot - La méthode d'authentification à utiliser, en l'occurrence la webroot.
  • --agree-tos - Agree to the terms-of-service. Acceptez les termes de service.
  • --renew-by-default - Renouveler par défaut les certificats
  • --config - Permet d'indiquer un fichier de configuration grâce à un chemin absolu.

Au passage pour rajouter un nom de domaine indiquez l'option --expand.
Automatisons tout ça.

Script / Crontab

Le script ci-dessous n'est pas de moi, on le retrouve un peu partout sur différents blogs et documentations.

1 - Créez et éditez un script dans le même répertoire que vos fichiers de configuration pour Let's Encrypt

sudo nano /usr/local/etc/letsencrypt/lets-encrypt-renewal.sh

2 - Collez-y ce qui suit en l'adaptant à vos besoins, notamment les paramètres en début de script.

  • CONFIG_FILE - Chemin absolu vers le ou les fichiers de configuration. Indiquez *.ini pour que le script prenne en compte tous les .ini présents dans le répertoire.
  • LE_PATH - Chemin absolu vers votre installation de Let's Encrypt
  • EXP_LIMIT - Défini la limite en jours avant le renouvellement
#!/bin/bash

WEB_SERVICE='nginx'
CONFIG_FILE='/usr/local/etc/letsencrypt/*.ini'
LE_PATH='/tmp/letsencrypt/'
EXP_LIMIT=30;

if [ ! -f $CONFIG_FILE ]; then
        echo "[ERROR] config file does not exist: $CONFIG_FILE"
        exit 1;
fi

DOMAIN=`grep "^\s*domains" $CONFIG_FILE | sed "s/^\s*domains\s*=\s*//" | sed 's/(\s*)\|,.*$//'`
CERT_FILE="/etc/letsencrypt/live/$DOMAIN/fullchain.pem"

if [ ! -f $CERT_FILE ]; then
	echo "[ERROR] certificate file not found for domain $DOMAIN."
fi

DATE_NOW=$(date -d "now" +%s)
EXP_DATE=$(date -d "`openssl x509 -in $CERT_FILE -text -noout | grep "Not After" | cut -c 25-`" +%s)
EXP_DAYS=$(echo \( $EXP_DATE - $DATE_NOW \) / 86400 |bc)

echo "Checking expiration date for $DOMAIN..."

if [ "$EXP_DAYS" -gt "$EXP_LIMIT" ] ; then
	echo "The certificate is up to date, no need for renewal ($EXP_LIMIT days left)."
	exit 0;
else
	echo "The certificate for $DOMAIN is about to expire soon. Starting webroot renewal script..."
        $LE_PATH/letsencrypt-auto certonly --webroot --agree-tos --renew-by-default --config $CONFIG_FILE
	echo "Reloading $WEB_SERVICE"
	/usr/sbin/service $WEB_SERVICE reload
	echo "Renewal process finished for domain $DOMAIN"
	exit 0;
fi

3 - Rendez-le exécutable

chmod +x /usr/local/etc/letsencrypt/lets-encrypt-renewal.sh

4 - Testez-le.

./usr/local/etc/letsencrypt/lets-encrypt-renewal.sh

5 - Il ne nous reste plus qu'à rendre tout cela automatique grâce au crontab. Dans le terminal tapez crontab -e afin de l'éditer et indiquez-y la ligne suivante:

30 2 * * 1 /usr/local/etc/letsencrypt/lets-encrypt-renewal.sh >> /var/log/lets-encrypt-renewal.log

Voilà, vous venez de créer une tâche cron qui fera en sorte d'exécuter toutes les lundis à 2h30 du matin et qui le logguera dans /var/log/lets-encrypt-renewal.log. De quoi voir venir en sachant que dans le script il est précisés (par défaut) de renouveler les certificats 30 jours avant l'expiration.

Vous voilà tranquille!

Sources / Liens