Hello les gens ! j’espère que tout le monde va bien. Aujourd’hui, on reste dans la pure technique avec un système que je suis en train d’évaluer chez nous, pour utiliser et dans la mesure du possible automatiser la mise à jours de certificats SSL publiques via Let’s Encrypt et injecter ceux-ci dans nos load balancers F5/BigIP.
Pour l’instant, et après pas mal d’heures de bidouillage, de tests et de difficultés diverses, je suis enfin parvenu à mes fins grâce à des scripts Shell. Comme je suis plus habitué à plutôt travailler en Shell, je vais passer la main à un collègue, lui-même spécialiste d’Ansible, pour automatiser le tout ensuite via des playbooks. Néanmoins, en attendant, je vous partage mes découvertes et les bases sur lesquelles je me suis appuyé pour simplifier au maximum la gestion de Let’s Encrypt, tout en gardant le contrôle des certificats.
Un p’tit schéma
Voici le principe général, un schéma valant toujours mieux qu’un long discours 🙂

En pratique, c’est relativement connu et simple : j’utilise donc Nginx Proxy Manager pour centraliser la gestion des certificats, à la fois intuitive et suivie. Deux raisons motivent ce choix : la simplicité d’utilisation et le suivi automatique des renouvellements. Même si l’objectif à terme est d’automatiser l’ensemble du processus, la confiance ne doit jamais exclure le contrôle, qu’il soit humain ou technique.
J’ai ainsi développé un script qui exploite l’API REST de nos load balancers F5 pour y injecter les certificats préalablement récupérés via NPM.
Nginx Proxy Manager
Pour votre info, globalement NPM ressemble à ça, pour ceux qui ne connaissent pas :

NPM est un reverse proxy basé sur Nginx, comme peut l’être Traefik, qui permet en plus et très facilement de gérer la sécurité SSL de tous vos points d’accès web frontend. Idéal pour un petit Home Lab. Pour ce qui me concerne, je n’utilise que les fonctions de pilotages des certificat Let’s Encrypt en coordination avec OVH qui fournit une API direct avec notamment la gestion de ses domaines.
Le script shell principal
Voici le script shell en question (franchement , ça ne s’invente pas … si vous n’êtes pas un spécialiste de ces environnements, je trouve cela assez compliqué chez Big IP, honnêtement) :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
######## Récupérer un token d'authentification BASEURL="https://loadbalancer.fdqn.intranet.fr" echo "BaseURL: $BASEURL" echo "Recup token ..." TOKEN=`curl -sk -X POST "$BASEURL/mgmt/shared/authn/login" -H "Content-Type: application/json" -d '{ "username":"xxxxxxxx","password":"xxxxxxxx","loginProviderName": "tmos" }' | jq .token.token | tr -d '"'` ######## Preparation echo "Preparation... " KEY=`./extract-file.sh monsiteweb.fr key` CERT=`./extract-file.sh monsiteweb.fr cert` KEYSIZE=`stat -Lc%s $KEY` KEYRANGE=$(( $KEYSIZE - 1)) CERTSIZE=`stat -Lc%s $CERT` CERTRANGE=$(( $CERTSIZE - 1)) ######## Upload echo "Token: $TOKEN" echo "Keyfile: $KEY ($KEYSIZE/$KEYRANGE)" echo "Certfile: $CERT ($CERTSIZE/$CERTRANGE)" # Certificat echo "Cert ----------" curl -sk -X POST \ -H "X-F5-Auth-Token: $TOKEN" \ -H "Content-Type: application/octet-stream" \ -H "Content-Range: 0-$CERTRANGE/$CERTSIZE" \ --data-binary "@$CERT" \ "$BASEURL/mgmt/shared/file-transfer/uploads/prod-clisson-cert.pem" | jq # Clé privée echo "Clef ----------" curl -sk -X POST \ -H "X-F5-Auth-Token: $TOKEN" \ -H "Content-Type: application/octet-stream" \ -H "Content-Range: 0-$KEYRANGE/$KEYSIZE" \ --data-binary "@$KEY" \ "$BASEURL/mgmt/shared/file-transfer/uploads/prod-clisson-key.pem" | jq ######## Installation # Conteneur dans F5 créer une fois via import direct, avec la racine de l'AC Let's Encrypt CERTSTORE="LETS-ENCRYPT-BASE" echo "CertStore : $CERTSTORE" DATACERT='{"command":"install","name":"'$CERTSTORE'","from-local-file":"/var/config/rest/downloads/prod-clisson-cert.pem"}' DATAKEY='{"command":"install","name":"'$CERTSTORE'","from-local-file":"/var/config/rest/downloads/prod-clisson-key.pem"}' echo "DataCert : $DATACERT" echo "DataKey : $DATAKEY" echo "Install cert ----------" curl -sk -X POST \ -H "X-F5-Auth-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d $DATACERT \ "$BASEURL/mgmt/tm/sys/crypto/cert" | jq echo "Install clef ----------" curl -sk -X POST \ -H "X-F5-Auth-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d $DATAKEY \ "$BASEURL/mgmt/tm/sys/crypto/key" | jq ######## Activation du profile DATAUSE='{"certKeyChain": [{"cert":"/Common/'$CERTSTORE'","key":"/Common/'$CERTSTORE',"chain":"/Common/'$CERTSTORE'","name":'$CERTSTORE' }]}' echo "DataUse: $DATAUSE" echo "Modification du profil SERVERPROFILE ----------" curl -sk -X PATCH \ -H "X-F5-Auth-Token: $TOKEN" \ -H "Content-Type: application/json" \ -d $DATAUSE \ "$BASEURL/mgmt/tm/ltm/profile/client-ssl/~Common~SERVERPROFILE" |
Un exemple de sortie interactive de ce script :
|
1 2 |
user@host-slt01:/datas/nginx-proxyman-stack# ./extract-file.sh www.test-domain.fr key nginx-proxy/letsencrypt/live/npm-6/privkey.pem |
j’ai également un script qui me sort la list de tous les certificats gérés par NPM, je ne l’utilise pas ici, car pas besoin, mais ça permet d’avoir une vue d’ensemble :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# !/bin/bash # HOMEDIR=`pwd` echo "HOMEDIR: $HOMEDIR" echo "------" DIRLIST=`find ./nginx-proxy/letsencrypt/live/* -type d` for courant in $DIRLIST ; do echo -n "SubjectName: " extract=`openssl x509 -in $courant/cert.pem -noout -text | grep DNS | tr -d 'DNS:' | awk '{ print $1 ; }'` echo $extract echo "Repertoire : " $HOMEDIR\/$courant echo -n "Clé privée : " $HOMEDIR\/$courant"/privkey.pem - date de maj:" date -r $courant/privkey.pem "+%Y-%m-%d" echo -n "Certificat : " $HOMEDIR\/$courant"/cert.pem - date de maj:" date -r $courant/cert.pem "+%Y-%m-%d" echo -n "FullChain : " $HOMEDIR\/$courant"/fullchain.pem - date de maj:" date -r $courant/fullchain.pem "+%Y-%m-%d" echo -n "Expiration du certificat" openssl x509 -in $courant/cert.pem -noout -text | grep "Not After" echo "------" done |
Ce qui donne ce genre de choses :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
user@host-slt01:/datas/nginx-proxyman-stack# ./certlist.sh HOMEDIR: /datas/nginx-proxyman-stack ------ SubjectName: testcert.test-domain.fr Repertoire : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-1 Clé privée : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-1/privkey.pem - date de maj:2025-09-25 Certificat : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-1/cert.pem - date de maj:2025-09-25 FullChain : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-1/fullchain.pem - date de maj:2025-09-25 Expiration du certificat Not After : Dec 24 15:03:49 2025 GMT ------ SubjectName: testcert2.fqdn.fr Repertoire : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-2 Clé privée : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-2/privkey.pem - date de maj:2025-09-25 Certificat : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-2/cert.pem - date de maj:2025-09-25 FullChain : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-2/fullchain.pem - date de maj:2025-09-25 Expiration du certificat Not After : Dec 24 15:02:50 2025 GMT ------ SubjectName: www.test-domain.fr Repertoire : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-6 Clé privée : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-6/privkey.pem - date de maj:2025-11-19 Certificat : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-6/cert.pem - date de maj:2025-11-19 FullChain : /datas/nginx-proxyman-stack/./nginx-proxy/letsencrypt/live/npm-6/fullchain.pem - date de maj:2025-11-19 Expiration du certificat Not After : Feb 17 07:44:32 2026 GMT ------ user@host-slt01:/datas/nginx-proxyman-stack# |
Vous voyez, c’est relativement basique : il s’agit de transformer cela en un playbook Ansible pour obtenir une version plus industrielle et entièrement automatisée. À terme, il suffira d’appuyer sur un bouton et de superviser le renouvellement des certificats une fois par semaine, via une procédure dédiée.
L’évolution souhaitée, à plus long terme, est d’automatiser intégralement le processus et de ne plus utiliser du tout Nginx Proxy Manager. Mais cela fera partie de la prochaine étape via par exemple certbot ou d’autres scripts Let’s Encrypt… mais chaque chose en son temps !
