У меня небольшая проблема с моим vps, работающим с Debian. На нем размещено несколько веб-сайтов через инфраструктуру на основе nginx, gunicorn, django. У рассматриваемых сайтов есть ssl-сертификат, которым управляет let's encrypt.
Я думаю, что проблема возникает, когда let's encrypt хочет обновить сертификаты.
Ошибка
Системный журнал при появлении ошибки:
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.
Репродукция
Быть по сему. Повторим процесс вручную. Убиваю все, что лежит вокруг nginx:
ps -ef |grep nginx
kill -9 xxxx
kill -9 xxxx
Я перезапускаю nginx:
service nginx start
тогда все работает нормально.
Я делаю пробный запуск certbot:
certbot renew --dry-run
и теперь у меня есть ошибка:
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.
Расследование
Смотрю в директорию /run: файла nginx.pid уже нет.
С другой стороны, небольшой ps -ef |grep nginx говорит мне, что процесс все еще работает, и сайты действительно работают. Поэтому, если я запускаю службу запуска nginx, она выводит мне ошибку конфликта адресов.
Я нашел людей на stackoverflow с той же проблемой, что и я, но решения не работают. Но это дало мне подсказку, где искать. Обновление Certbot: nginx : [ошибка] open() /run/nginx.pid не удалось (2: Нет такого файла или каталога)
так что я смотрю: файлы /etc/letsencrypt/renewal/xxx.fr.conf содержат следующие хуки:
[renewalparams]
authenticator = standalone
installer = nginx
pre_hook = service nginx stop
post_hook = service nginx start
Очень хорошо. Смотрю сопутствующие скрипты /etc/init.d/nginx: в самом начале извлекает pid через
PID=$(cat /etc/nginx/nginx/nginx.conf | grep -Ev' ^\s*#' | awk' BEGIN { RS="[;{}]" } { if ($1 == "pid") print $2 }' | head -n1)
эта команда работает хорошо.
прекратить:
stop_nginx() {
start-stop-daemon --stop --quiet --retry=$STOP_SCHEDULE --pidfile $PID --name $NAME
RETVAL="$?"
sleep 1
return "$RETVAL"
}
начать
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
}
Похоже, это хорошо. Более того, когда служба хорошо работает со своим pid, команды запуска и остановки работают очень хорошо.
Вывод
Ну вот и все, вот и я с проблемой, которую не понимаю.