Sommaire
Bonjour à toutes les moules de la place,
J’ai un petit soucis sur mon vps tournant avec une debian. Celui-ci héberge plusieurs sites web, via une infrastructure basée sur nginx, gunicorn, django.
Les sites en question possèdent un certificat ssl géré par let’s encrypt.
Le problème je crois arrive lorsque let’s encrypt veut renouveler les certificats.
L'erreur
Le journal system lorsque l'erreur apparaît :
Dec 12 00:01:46 vps465872 systemd[1]: Starting Certbot...
Dec 12 00:01:49 vps465872 systemd[1]: Stopping A high performance web server and a reverse proxy server...
Dec 12 00:01:49 vps465872 systemd[1]: Stopped A high performance web server and a reverse proxy server.
Dec 12 00:01:55 vps465872 certbot[600]: nginx: [error] open() "/run/nginx.pid" failed (2: No such file or directory)
Dec 12 00:01:56 vps465872 systemd[1]: Starting A high performance web server and a reverse proxy server...
Dec 12 00:01:56 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Dec 12 00:01:56 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Dec 12 00:01:57 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Dec 12 00:01:57 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Dec 12 00:01:57 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Dec 12 00:01:57 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Dec 12 00:01:58 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Dec 12 00:01:58 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Dec 12 00:01:58 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
Dec 12 00:01:58 vps465872 nginx[658]: nginx: [emerg] bind() to 0.0.0.0:443 failed (98: Address already in use)
Dec 12 00:01:59 vps465872 nginx[658]: nginx: [emerg] still could not bind()
Dec 12 00:01:59 vps465872 systemd[1]: nginx.service: Control process exited, code=exited status=1
Dec 12 00:01:59 vps465872 systemd[1]: Failed to start A high performance web server and a reverse proxy server.
Dec 12 00:01:59 vps465872 systemd[1]: nginx.service: Unit entered failed state.
Dec 12 00:01:59 vps465872 systemd[1]: nginx.service: Failed with result 'exit-code'.
Dec 12 00:01:59 vps465872 certbot[600]: Hook command "service nginx start" returned error code 1
Dec 12 00:01:59 vps465872 certbot[600]: Error output from service:
Dec 12 00:01:59 vps465872 certbot[600]: Job for nginx.service failed because the control process exited with error code.
Dec 12 00:01:59 vps465872 certbot[600]: See "systemctl status nginx.service" and "journalctl -xe" for details.
Bon après investigation, alors on dirait que le certbot arrête nginx, mais que celui-ci continu malgré tout à tourner, tout en ayant aucun fichier /run/nginx.pid. Alors quand il le relance il y a un conflit d'adresse, et nginx ne repart pas.
La reproduction
Soit. Refaisons le processus manuellement. Je tue tout ce qui traine de nginx :
ps -ef |grep nginx
kill -9 xxxx
kill -9 xxxx
Je relance nginx :
service nginx start
là tout marche correctement.
J'effectue un dry-run du certbot:
certbot renew --dry-run
et là c'est erreur :
Attempting to renew cert (xxx.fr) from /etc/letsencrypt/renewal/xxx.fr.conf produced an unexpected error: Problem binding to port 443: Could not bind to IPv4 or IPv6.. Skipping.
L'investigation
je regarde dans le répertoire run : le fichier nginx.pid n'existe plus.
Par contre un petit ps -ef |grep nginx
me dit que le processus tourne toujours, effectivement les sites web marchent. Par conséquent si je fait un service nginx start
, il me sort l'erreur du conflit d'adresse.
J'ai trouvé sur stackoverflow des personnes ayant le même problème que moi, mais les solutions ne marchent pas. Mais ça m'a donné des indices où chercher.
https://stackoverflow.com/questions/49571099/certbot-renew-nginx-error-open-run-nginx-pid-failed-2-no-such-file-or
donc je regarde :
les fichiers /etc/letsencrypt/renewal/xxx.fr.conf contiennent les hooks suivants:
[renewalparams]
authenticator = standalone
installer = nginx
pre_hook = service nginx stop
post_hook = service nginx start
Très bien. Je regarde les scripts associés /etc/init.d/nginx :
tout au début il extrait le pid via
PID=$(cat /etc/nginx/nginx.conf | grep -Ev '^\s*#' | awk 'BEGIN { RS="[;{}]" } { if ($1 == "pid") print $2 }' | head -n1)
cette commande marche bien
pour stopper :
stop_nginx() {
start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PID --name $NAME
RETVAL="$?"
sleep 1
return "$RETVAL"
}
pour démarrer
start_nginx() {
start-stop-daemon --start --quiet --pidfile $PID --exec $DAEMON --test > /dev/null \
|| return 1
start-stop-daemon --start --quiet --pidfile $PID --exec $DAEMON -- \
$DAEMON_OPTS 2>/dev/null \
|| return 2
}
Ça à l'aire d'être bon. D'ailleurs lorsque le service marche bien avec son pid, les commandes start et stop marchent très bien.
La conclusion
Bon bah c'est tout, me voilà avec un problème que je ne comprends pas. D'où ce post.
# solution trouvée
Posté par nnamrok . Évalué à 1.
On m'a soufflé une solution, en changeant le mode d'authentification du certificat.
il faut mettre dans les fichiers conf du certbot (il faut enlever le pre_hook):
Il faut changer les fichier conf de nginx avant afin de faire pointer /.well-know vers le répertoire précédemment définit.authenticator = webroot
webroot_path = /var/www/xxx/
post_hook = service nginx restart
Cette solution a l'avantage de ne pas arrêter le serveur pendant un court laps de temps.location /.well-know {
alias /var/www/xxx/;
}
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.