Forum Linux.debian/ubuntu Service Nginx qui n'est pas arrêté proprement par le certbot et qui par conséquent ne redémarre pas.

Posté par  . Licence CC By‑SA.
Étiquettes : aucune
0
13
déc.
2018

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  . É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):

    authenticator = webroot
    webroot_path = /var/www/xxx/
    post_hook = service nginx restart
    Il faut changer les fichier conf de nginx avant afin de faire pointer /.well-know vers le répertoire précédemment définit.

    location /.well-know {
    alias /var/www/xxx/;
    }
    Cette solution a l'avantage de ne pas arrêter le serveur pendant un court laps de temps.

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.