Let's Encrypt et NGinx

Le mardi 29 décembre 2015 par Benjamin Boudoir

J'héberge 2~3 choses que j'estime nécessiter du HTTPS. Pas tout, parce que je n'ai pas les moyens de payer des certificats pour ça et que sinon ça ferait fuire les personnes qui viendraient consulter des choses qui pourraient les aider.

Mais cette époque est révolue et je vais pouvoir, progressivement, tout passer en HTTPS.

Tout ça parce que Let's Encrypt.

Je vais pas parler de ce qu'est Let's Encrypt, mais de comment j'ai fait le pas, parce que bien évidement, je n'ai pas fait comme c'était recommandé.

Le client

En premier lieu, je n'ai pas utilisé le client officiel, mais un client écrit intégralement en shell script.

Pourquoi ? Parce que je n'avais pas envie d'un truc qui chierait dans mes fichiers de config.

le.sh a quelques défaut (notament : il ignore rigoureusement un certain nombre de paramètres), au moins il s'occupe uniquement de la communication avec le serveur ACME et de sauvegarder des certificats.

J'ai une haine sincère des softs qui font des choses "automatiquement" sans se soucier de documenter la méthode manuelle (enfin... Si, c'est documenté... Pour les devs, pas pour les admins). Le client officiel Let's Encrypt est d'iceux.

Bref, ici, c'est simple :

root@server:~# ./le.sh
Usage: issue|renew|renewAll|createAccountKey|createDomainKey|createCSR|install|uninstall
root@server:~# ./le.sh issue
Usage: ./le.sh webroot a.com [www.a.com,b.com,c.com]  [key-length] [cert-file-path] [key-file-path] [reloadCmd]
root@server:~# ./le.sh issue /var/www/acme/ domain.tld alt.domain.tld,www.domain.tld 4096

Quand je disais qu'il ignorait un certain nombre de paramètres : il s'arrête à [key-length]. Tout sera donc stocké dans $HOME/.le/domain.tld/.

C'est le seul reproche que j'ai à lui faire (pour le moment).

Ma config NGinx

On arrive à la partie qui explique pourquoi j'ai préféré me passer du client officiel... J'ai de tout sur la config de mon serveur web :

  • mass virtual hosting
  • proxy
  • etc.

Tout un tas de choses que je vois mal être correctement prises en charge par un script qui s'adresse à tout le monde (soit : des serveurs Wordpress derrière Apache, quasi exclusivement)

Entre autre, parmi les particularités de ma configuration, j'ai un joli :

location ~ /\.
{
  deny  all;
}

Que je trouve très pratique, mais qui est légèrement gênant car il bloque aussi le dossier /.well-known/ défini par la RFC 5785 et qui est, bien évidement utilisé par Let's Encrypt pour valider que vous êtes bien propriétaire du domaine dont vous cherchez à créer un certificat.

Pour by-passer tout ça, il y a un joli opérateur particulier pour location : ^~.

Il a le bon goût (à l'instar de =, mais en moins rigide) de ne pas chercher à continuer d'interpréter les expressions rationnelles une fois que cette location concorde. On se retrouve donc avec un joli fichier de conf très court et qui marche partout :

well-known.conf

location ^~  '/.well-known/acme-challenge'
{
  default_type "text/plain";
  root         /var/www/acme/;
  allow        all;
}

Il est important de garder la même racine pour s'éviter les surprises lors des définitions des domaines alternatifs.

Et après, on peut ajouter ce petit bout de configuration partout :

include well-known.conf;

Merveilleux.

Et le renouvelement alors ?

Bon, effectivement, j'aurais aimé qu'il me sorte les certificats où je le voulais, renouveler mon certificat disons 1 semaine ~ 1 mois avant expiration, tester gentiment et rollback en cas de problème.

Mais ça n'a pas l'air de le faire, alors en attendant je fais ça de façon un peu bourrine :

/etc/cron.d/letsencrypt

* * * * * root /ust/local/bin/le.sh renewAll > /dev/null && /etc/init.d/nginx reload

Et maintenant ?

On attend, on voit ce que ça donne dans 90 jours (durée limite des certificats Let's Encrypt) et ensuite on généralise ça (aussi parce que j'ai pourri mon rate limit avec des certificats moisis pour tester le fonctionnement du bouzzin).

Quand ça sera plus sûr, je réfléchirai à la façon de déployer ça automatiquement sur mon SMTP.