Publié le: 2016-09-19

LetsEncypt with a Nginx jail

LetsEncypt est une autorité de certification utilisant une API basée sur des appels HTTP et un client côté serveur qui va générer des tokens lus par les serveurs LetsEncrypt. Nous allons ici voir une architecture LetsEncrypt typique dans laquelle nous allons utiliser le client acme-client d’OpenBSD disponible dans les ports et les packages FreeBSD.

Installation

Dans un premier temps installez le client sur votre machine hôte (et pas votre jail web):

pkg install acme-client

Configuration de nginx

Nous allons maintenant configurer nginx afin de pouvoir interagir avec l’API letsencrypt. Créez tout d’abord le répertoire suivant dans votre jail avec l’utilisateur et le groupe nobody

mkdir /usr/local/www/.well-known && chown nobody:nobody /usr/local/www/.well-known

Ensuite configurez vos virtual hosts afin de faire pointer les appels vers /.well-known dans ce répertoire:

server {
        listen 80;
        server_name www.unix-experience.fr;
        location /.well-known {
            alias /usr/local/www/.well-known;
        }
        location / {
            return 301 https://www.unix-experience.fr$request_uri;
        }
        add_header X-Frame-Options "DENY";
        add_header Strict-Transport-Security "max-age=86400; preload";
}

Note: nous ajoutons ici le support du protocole HSTS avec un TTL d'1 journée spécifiant aux navigateurs que le site supporte SSL et qu’il faudrait passer dessus. Vous pouvez sans souci faire pointer plusieurs de vos virtual hosts dans ce même répertoire.

Configuration du client LetsEncrypt

Retournez maintenant sur votre hôte et créez le fichier /usr/local/etc/acme/domains.txt puis ajoutez y un domaine par ligne:

www.unix-experience.fr
ftp.unix-experience.fr

Créez ensuite le script ci-dessous (basé sur le script présent dans le même répertoire sous forme d’exemple) dans /usr/local/etc/acme/acme-client.sh

#!/bin/sh -e
WEBJAIL="web"
BASEDIR="/usr/local/etc/acme"
SSLDIR="/usr/local/etc/ssl/acme"
DOMAINSFILE="${BASEDIR}/domains.txt"
CHALLENGEDIR="/jails/${WEBJAIL}/usr/local/www/.well-known/acme-challenge"

[ ! -d "${SSLDIR}/private" ] && mkdir -pm700 "${SSLDIR}/private"

cat "${DOMAINSFILE}" | while read domain line ; do
   CERTSDIR="${SSLDIR}/${domain}"
   [ ! -d "${CERTSDIR}" ] && mkdir -pm755 "${CERTSDIR}"
   set +e # RC=2 when time to expire > 30 days
   acme-client -b -C "${CHALLENGEDIR}" \
               -k "${SSLDIR}/private/${domain}.pem" \
               -c "${CERTSDIR}" \
               -n -N -v \
               ${domain} ${line}
   RC=$?
   set -e
   [ $RC -ne 0 -a $RC -ne 2 ] && exit $RC
done

Ce script lit les domaines présents dans le fichier domains.txt puis il va s’occuper de créer vos clefs privées et de les faire signer par LetsEncrypt, en se basant sur le répertoire .well-known présent dans votre jail. Une fois ce script exécuté, si tout s’est passé correctement vous trouverez votre clef privée dans le répertoire /usr/local/etc/ssl/acme/private/example.org et votre clef publique et les chaînes de certificats dans le répertoire /usr/local/etc/ssl/acme/example.org. Ces répertoires sont situés sur votre hôte et non dans votre jail web. Pour déployer les scripts un script d’exemple est présent dans le répertoire **/usr/local/etc/**acme, mais nous allons légèrement le modifier. Créez le fichier /usr/local/etc/acme/deploy.sh:

#!/bin/sh

set -e

BASEDIR="/usr/local/etc/acme"
DOMAINSFILE="${BASEDIR}/domains.txt"
LEDIR="/usr/local/etc/ssl/acme"
JAILSDIR="/jails"
TARGETS="web"
cat "${DOMAINSFILE}" | while read domain line ; do
    for jail in ${TARGETS}; do
        targetdir="${JAILSDIR}/${jail}/etc/ssl"
        # Check if the certificate has changed
        [[ -z "`diff -rq ${LEDIR}/${domain}/fullchain.pem ${targetdir}/certs/${domain}.pem`" ]] && continue
        cp -L "${LEDIR}/private/${domain}.pem"   "${targetdir}/private/${domain}.pem"
        cp -L "${LEDIR}/${domain}/fullchain.pem" "${targetdir}/certs/${domain}.pem"
        chmod 400 "${targetdir}/private/${domain}.pem"
        chmod 644 "${targetdir}/certs/${domain}.pem"
        # Restart/-load relevant services
        [[ "${jail}" = "web" ]] && jexec ${jail} service nginx restart
    done
done

Ce script va copier tous les certificats associés à vos dernières négociations LetsEncrypt et va les déployer dans votre jail web puis redémarrer nginx.

Renouvellement automatique

Pour finir il ne reste plus qu’à configurer le cron ajouté par le paquet acme-client afin de configurer la tâche hebdomadaire. Pour se faire, éditez le fichier /usr/local/etc/periodic.conf et ajoutez les entrées suivantes:

# letsencrypt
weekly_acme_client_enable="YES"
weekly_acme_client_user="nobody"
weekly_acme_client_deployscript="/usr/local/etc/acme/deploy.sh"

Cela va vous permettre d’activer le cron, et de lancer le déploiement automatiquement toutes les semaines.

Conclusion

Vous pouvez désormais faire des demandes de certificats LetsEncrypt facilement et les renouveler automatiquement via un cron fourni par acme-client.