Автоматическое обновление сертификатов Certbot для Nginx по таймеру Systemd
SSL-сертификаты от Certbot легко ставить, ими удобно пользоваться, но действуют они только 90 дней, а значит вы наверняка захотите автоматизировать их обновление.
Если вы используете Ubuntu, Debian или другую систему с предустановленным Systemd, то регулярный запуск процесса обновления вы можете организовать с помощью юнита и таймера Systemd. Каждую неделю Systemd будет запускать программу certbot
, чтобы та сама обновила сертификаты и предупредила об этом сервер Nginx, а вы сможете контролировать процесс с помощью логов и journalctl
.
Из этого туториала вы узнаете, как настроить автоматическое обновление SSL-сертификатов для Nginx с помощью Certbot и Systemd.
Прежде чем приступить
Чтобы суметь пройти по этоту туториалу вам понадобятся:
- Linux-сервер для экспериментов
- Nginx на сервере
- Домен для сервера
- Установленный Certbot
- Навыки работы с Systemd
Обновляем сертификат вручную
Прежде, чем браться за автоматизацию, давайте проверим всю схему вручную.
К этому моменту у вас уже должен быть Linux-сервер с доменным именем, там настроены Nginx и Certbot. В туториале мы сразу перейдём к проблеме обновления сетрификата.
Обновлением SSL-сертификата занимается та же программа, что его создаёт – это certbot. Запустим программу с ключом renew
:
# certbot renew
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/demosite.dvmn.org.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cert not yet due for renewal
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The following certificates are not due for renewal yet:
/etc/letsencrypt/live/demosite.dvmn.org/fullchain.pem expires on 2021-08-22 (skipped)
No renewals were attempted.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Вывод программы выглядит хорошо, ничего не взорвалось. Но если приглядеться внимательнее, то заметим, что certbot обновлять сертификаты даже и не пытался:
No renewals were attempted.
Не удивительно, что у Certbot всё получилось .
Чтобы тестирование скриптов было надёжным, заставим certbot
отключить проверку устаревания сертификатов и принудительно их обновить. Отключить эту проверку можно с помощью флага --force-renewal
:
# certbot renew --force-renewal
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/demosite.dvmn.org.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate for demosite.dvmn.org
Running deploy-hook command: systemctl reload nginx.service
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
new certificate deployed with reload of nginx server; fullchain is
/etc/letsencrypt/live/demosite.dvmn.org/fullchain.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all renewals succeeded:
/etc/letsencrypt/live/demosite.dvmn.org/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
На этот раз Certbot действительно обновил сертификат. Программа работает, можно двигаться дальше.
Лимит на количество попыток.
Certbot разрешает обновлять сертификат не чаще 5 раз в неделю. Если превысите лимит, варианты действий у вас будут такие:
- подождать неделю
- продолжить эксперименты на другом поддомене
- дальше для тестов использовать
--dry-run
, что не так надёжно, но за неимением лучшего может и сойти…
Чтобы пройти по туториалу вам достаточно всего трёх-четырёх попыток, и в лимит вы уложитесь.
О превышении лимита Certbot сообщит вам ошибкой в консоли.
Как выглядит превышение лимита.
# certbot renew --force-renewal
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/demosite.dvmn.org.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Plugins selected: Authenticator nginx, Installer nginx
Renewing an existing certificate for demosite.dvmn.org
Failed to renew certificate demosite.dvmn.org with error: urn:ietf:params:acme:error:rateLimited :: There were too many requests of a given type :: Error creating new order :: too many certificates already issued for exact set of domains: demosite.dvmn.org: see https://letsencrypt.org/docs/rate-limits/
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
All renewals failed. The following certificates could not be renewed:
/etc/letsencrypt/live/demosite.dvmn.org/fullchain.pem (failure)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1 renew failure(s), 0 parse failure(s)
Перезагружаем конфигурацию Nginx
SSL-сертификат нужен для работы веб-сервера Nginx. Каждый раз, когда к нему обращается браузер или другой клиент, то общение с сервером начинается с проверки подлинности сертификата. Для этого Nginx считывает содержимое файлов, созданных Certbot:
Congratulations, all renewals succeeded:
/etc/letsencrypt/live/demosite.dvmn.org/fullchain.pem (success)
Однако, Nginx не будет считывать файлы при каждом новом обращении. Вместо этого он считывает сертификаты всего лишь раз, запоминает, и дальше пользуется закэшированной их версией. По этой причине Nginx не узнает об изменении сертификатов, пока вы сами ему не сообщите.
У Nginx есть как минимум два способа сбросить кэш с SSL-сертификатами: это restart
и reload
. Первая команда restart
перезапускает Nginx целиком, и делает сайт недоступным для пользователей на время перезапуска. Вторая команда reload
позволяет Nginx продолжить работу, но требует перечитать конфиги и связанные с ними файлы.
Чтобы не отлючать лишний раз сайт выберем команду reload
. Проверим её работу вручную:
# systemctl reload nginx.service
В консоли нет явных подтверждений того, что перезапуск прошёл успешно, поэтому заглянем в логи Nginx.
# systemctl status nginx.service
...
Active: active (running) since Mon 2021-05-24 08:50:33 UTC; 5 days ago
...
May 29 09:45:00 systemd[1]: Reloading A high performance web server and a reverse proxy server.
May 29 09:45:00 systemd[1]: Reloaded A high performance web server and a reverse proxy server.
По строке Active
видим, что Nginx работает без остановок уже пять дней, а значит операция reload
никак не мешает пользователям сайта, что здорово. Последние две строки сообщают об успешной перезагрузке конфигурации сервера. Отметки времени подтверждают, что это “свежий” Reload
, случившийся буквально только что.
Теперь совместим обновление сертификата с перезагрузкой конфигов Nginx. Сделать это можно с помощью стандартного “хука” Certbot post-hook
. Через эту настройку можно указать какая команда будет выполнена после обновления сертификата:
# certbot renew --force-renewal --post-hook "systemctl reload nginx.service"
...
Running post-hook command: systemctl reload nginx.service
Ещё раз заглянем в лог Nginx, проверим что перезагрузка конфигов прошла успешно:
# systemctl status nginx.service
...
May 29 09:45:00 systemd[1]: Reloading A high performance web server and a reverse proxy server.
May 29 09:45:00 systemd[1]: Reloaded A high performance web server and a reverse proxy server.
May 29 09:59:07 systemd[1]: Reloading A high performance web server and a reverse proxy server.
May 29 09:59:07 systemd[1]: Reloaded A high performance web server and a reverse proxy server.
В логе появились две свежие записи о перезагрузке конфигов. Значит, всё в порядке.
Пишем service-файл
Теперь, когда надёжно протестирована команда обновления сертификатов, можем заняться настройкой Systemd. Он нужен для автоматизации. Systemd сам будет каждую неделю запускать обновление сертификатов на сервере.
Для регулярных запусков Systemd требует два файла файла с настройками. Это юниты *.service
и *.timer
. Начнём с первого.
Создадим новый файл с настройками certbot-renewal.service
. Его содержимое выглядит так:
# Содержимое файла /etc/systemd/system/certbot-renewal.service
[Unit]
Description=Certbot Renewal
[Service]
ExecStart={полный путь к certbot} renew --force-renewal --post-hook "systemctl reload nginx.service"
В конфиге не хватает полного пути к certbot. Узнайте его с помощью whereis
:
# whereis certbot
certbot: /usr/bin/certbot /snap/bin/certbot
Подставляем путь в certbot-renewal.service
:
# Содержимое файла /etc/systemd/system/certbot-renewal.service
[Unit]
Description=Certbot Renewal
[Service]
ExecStart=/usr/bin/certbot renew --force-renewal --post-hook "systemctl reload nginx.service"
Проверим работу юнита: запустим его, дождёмся окончания работы, проверим обновились ли настройки Nginx:
# systemctl start certbot-renewal.service
# systemctl status certbot-renewal.service
# # ... ждём завершения работы "сервиса" ...
# systemctl status nginx.service
...
May 29 10:04:13 systemd[1]: Reloading A high performance web server and a reverse proxy server.
May 29 10:04:13 systemd[1]: Reloaded A high performance web server and a reverse proxy server.
Создаём таймер
Настройки для регулярно запускаемых программ Systemd хранит в отдельных файлах *.timer
. Они являются дополнением к обычным файлам *.service
и, по умолчанию, должны иметь такие же названия. Например, если файл certbot-renewal.service
описывает что и как запускать, то когда это делать описано в соседнем файле certbot-renewal.timer
.
Создадим новый файл certbot-renewal.timer
в той же директории, где находится certbot-renewal.service
. Настройки ниже будут запускать обновление SSL-сертификата раз в неделю, не раньше чем через 300 секунд с момента включения сервера:
# Файл /etc/systemd/system/certbot-renewal.timer
[Unit]
Description=Timer for Certbot Renewal
[Timer]
OnBootSec=300
OnUnitActiveSec=1w
[Install]
WantedBy=multi-user.target
Включим таймер, чтобы он начал свой отсчёт:
# sudo systemctl start certbot-renewal.timer
Настроим автоматическое включение таймера на случай перезапуска сервера:
# sudo systemctl enable certbot-renewal.timer
Заглянем в статус таймера, чтобы узнать когда было последнее обновление SSL-сертификата и когда планируется следующее:
# systemctl status certbot-renewal.timer
● certbot-renewal.timer - Timer for Certbot Renewal
Loaded: loaded (/etc/systemd/system/certbot-renewal.timer; enabled; vendor preset: enabled)
Active: active (waiting) since Sat 2021-05-29 10:49:24 UTC; 3min 4s ago
Trigger: Sat 2021-06-05 10:52:07 UTC; 6 days left
Triggers: ● certbot-renewal.service
Вывод в консоль показывает, что последний запуск обновления сертификатов был три минуты назад, а следующий планируется через шесть дней. Как раз то, что нужно.
Для верности заглянем ещё раз в логи Nginx и проверим, есть ли там отчёт о последней “свежей” перезагрузке конфигурации:
# systemctl status nginx.service
...
May 29 10:52:07 systemd[1]: Reloading A high performance web server and a reverse proxy server.
May 29 10:52:07 systemd[1]: Reloaded A high performance web server and a reverse proxy server.
Значит, всё готово. Теперь сертификат будет обновляться раз в неделю, а Nginx подхватит эти изменения.
Читать дальше
Что почитать, если хочется больше деталей:
Попробуйте бесплатные уроки по Python
Получите крутое код-ревью от практикующих программистов с разбором ошибок и рекомендациями, на что обратить внимание — бесплатно.
Переходите на страницу учебных модулей «Девмана» и выбирайте тему.