Вики IT-KB

Пошаговые руководства, шпаргалки, полезные ссылки...

Инструменты пользователя

Инструменты сайта


web-server-nginx:setting-up-automatic-renewal-of-lets-encrypt-ssl-certificates-in-nginx-using-certbot-on-debian-13

Настройка автоматического обновления SSL сертификатов Let's Encrypt в NGINX с помощью Certbot на Debian Linux 13

Базовую настройку веб-сервера NGINX для поддержки HTTPS мы рассматривали ранее в заметке Настройка веб-сервера на базе стека LEMP в Ubuntu Server 14.04 LTS. Часть 11. Настройка поддержки HTTPS в Nginx, Wordpress и phpBB. В этой заметке мы немного расширим эту тему и рассмотрим то, как можно автоматизировать процесс регулярного обновления SSL сертификатов, привязанных к сайтам nginx. Бесплатные криптографические сертификаты X.509 будем получать в центре сертификации Let's Encrypt, а с помощью пакета certbot настроим автоматизацию обновления этих сертификатов с интеграцией в конфигурацию веб-сервера nginx.


Установка Certbot

Устанавливаем пакет certbot из стандартных репозиториев Debian Linux

# apt install certbot

Создаём каталог для временных файлов Let's Encrypt и делаем его владельцем пользователя и группу, в контексте которых работает веб-сервер:

# mkdir /var/www/letsencrypt
# chown www-data:www-data /var/www/letsencrypt

Подготовка NGINX

Выносим текущую конфигурацию SSL из /etc/nginx/nginx.conf в отдельный файл /etc/nginx/snippets/ssl.conf

# nano /etc/nginx/snippets/ssl.conf
ssl.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+ECDSA+AESGCM:AES128+EECDH:AES128+EDH:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!CAMELLIA:!ADH";
ssl_session_cache shared:TLS:20m;
#ssl_stapling on;
#ssl_stapling_verify on;
resolver 77.88.8.8 77.88.8.1 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 10s;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
ssl_dhparam /etc/ssl/dhparams.pem;
ssl_certificate /etc/ssl/mydomain.crt;
ssl_certificate_key /etc/ssl/private/mydomain.key;

Создаём конфигурацию Let's Encrypt для работы certbot:

# nano /etc/nginx/snippets/letsencrypt.conf
letsencrypt.conf
location ^~ /.well-known/acme-challenge/ {
   default_type "text/plain";
   root /var/www/letsencrypt;
}
location = /.well-known/acme-challenge/ {
   return 404;
}

Включаем конфиги ssl.conf и letsencrypt.conf в секцию server для конфигураций сайтов nginx в файлы /etc/nginx/sites-available/*.conf Например:

# nano /etc/nginx/sites-available/mydomain.conf
mydomain.conf
...
server {
        listen 443 ssl;
        include snippets/ssl.conf;
        include snippets/letsencrypt.conf;
 
	...	
}

Регистрация Certbot

Регистрируем экземпляр certbot. В ходе регистрации будет задана пара вопросов.

# certbot register -m petya@mydomain.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please read the Terms of Service at: https://letsencrypt.org/documents/LE-SA-v1.5-February-24-2025.pdf You must agree in order to register with the ACME server. Do you agree? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Yes - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Would you be willing, once your first certificate is successfully issued, to share your email address with the Electronic Frontier Foundation, a founding partner of the Let's Encrypt project and the non-profit organization that develops Certbot? We'd like to send you email about our work encrypting the web, EFF news, campaigns, and ways to support digital freedom. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: No Account registered.

Регистрационные файлы попадут в подкаталог /etc/letsencrypt/accounts:

# tree /etc/letsencrypt/
/etc/letsencrypt/ ├── accounts │   └── acme-v02.api.letsencrypt.org │   └── directory │   └── 4f50a3d608bead7e9ae31a15b605af4a │   ├── meta.json │   ├── private_key.json │   └── regr.json ├── cli.ini └── renewal-hooks ├── deploy ├── post └── pre 9 directories, 4 files

Запрос сертификатов

Перед тестированием следует убедиться в том, что сайты, для которых будут запрашиваться сертификаты, доступны из Интернета.

Тестируем работу certbot без фактической генерации сертификатов Let's Encrypt («холостой» запуск):

# certbot certonly --dry-run --webroot -w /var/www/letsencrypt -d mydomain.ru \
-d blog.mydomain.ru -d forum.mydomain.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log Simulating a certificate request for mydomain.ru and 2 more domains The dry run was successful.

Фактически запрашиваем сертификаты Let's Encrypt:

# certbot certonly --webroot -w /var/www/letsencrypt -d mydomain.ru \
-d blog.mydomain.ru -d forum.mydomain.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log Requesting a certificate for mydomain.ru and 2 more domains Successfully received certificate. Certificate is saved at: /etc/letsencrypt/live/mydomain.ru/fullchain.pem Key is saved at: /etc/letsencrypt/live/mydomain.ru/privkey.pem This certificate expires on 2025-11-15. These files will be updated when the certificate renews. Certbot has set up a scheduled task to automatically renew this certificate in the background. ...

Конфигурация NGINX

Добавляем полученные сертификаты в ssl.conf, закомментировав ссылки на используемые ранее сертификаты длительного срока действия:

# nano /etc/nginx/snippets/ssl.conf
ssl.conf
...
#ssl_certificate /etc/ssl/mydomain.crt;
#ssl_certificate_key /etc/ssl/private/mydomain.key;
ssl_certificate /etc/letsencrypt/live/mydomain.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain.ru/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/mydomain.ru/chain.pem;

Перезапускаем nginx и проверяем результат:

# systemctl restart nginx

Автоматизация обновления

Срок действия SSL сертификатов Let's Encrypt - 3 месяца. Настроим автоматическое обновление сертификатов, чтобы не следить за истечением срока и не обновлять вручную каждый раз эти сертификаты.

Выполним проверку обновления («холостой» запуск):

# certbot renew --dry-run
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/mydomain.ru.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Simulating renewal of an existing certificate for mydomain.ru and 2 more domains - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations, all simulated renewals succeeded: /etc/letsencrypt/live/mydomain.ru/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Если проверка прошла без ошибок, то можем выполнить фактическое обновление:

# certbot renew

Если срок действия сертификата не близок к окончанию, то он обновлён не будет. Если требуется выполнить форсированное обновление, безотносительно строка действия сертификата, то выполняем такой запуск:

# certbot renew --force-renewal

В конфиг /etc/letsencrypt/renewal/mydomain.ru.conf можно добавить хук для перезапуска веб-сервера после обновления сертификатов

renew-hook  = systemctl reload nginx.service

Но более простым вариантом передачи хука является запуск certbot с передачей хуков в качестве параметра. Этим мы и воспользуемся для того, чтобы настроить автоматическое применение обновлённых сертификатов службой веб-сервера.

В нашем случае после установки пакета certbot в системе появляются два новых юнита systemd, поэтому создавать собственные юниты, как это описано, например, здесь, у нас необходимости нет. Проверим наличие этих юнитов:

# systemctl list-unit-files | grep certbot
UNIT FILE STATE PRESET ... certbot.service static - certbot.timer enabled enabled ...

Как видим, есть два юнита:

  • Юнит certbot.service отвечает за конфигурацию запуска certbot
  • Юнит certbot.timer отвечает за автоматический запуск юнита certbot.service по определённому расписанию.

По умолчанию юниты сконфигурированы следующим образом:

# systemctl cat certbot.service
# /usr/lib/systemd/system/certbot.service [Unit] Description=Certbot Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html Documentation=https://certbot.eff.org/docs [Service] Type=oneshot ExecStart=/usr/bin/certbot -q renew --no-random-sleep-on-renew PrivateTmp=true
# systemctl cat certbot.timer
# /usr/lib/systemd/system/certbot.timer [Unit] Description=Run certbot twice daily [Timer] OnCalendar=*-*-* 00,12:00:00 RandomizedDelaySec=43200 Persistent=true [Install] WantedBy=timers.target

Таким образом, в конфигурации по умолчанию этими двумя юнитами настроен запуск команды «certbot -q renew –no-random-sleep-on-renew» с расписанием дважды в сутки с рандомизированным сдвигом (RandomizedDelaySec) чтобы избежать DDoS Let's Encrypt.

Если по какой-то причине таймер не включен, то включаем и запускаем его

# systemctl enable --now certbot.timer

Убедимся в том, что таймер появился в списке активных таймеров:

# systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES ... 2025-08-22 20:43:01 10h 2025-08-22 09:58:30 2min 42s ago certbot.timer certbot.service ...

В такой конфигурации обновление сертификатов с помощью certbot произойдёт автоматически тогда, когда до окончания срока действия сертификата останется меньше 30 дней. И всё что нам остаётся - настроить применение новых сертификатов в конфигурации ngix.

В Debian пакетный certbot кладёт хуки в каталог /etc/letsencrypt/renewal-hooks/deploy/.

Создадим хук в виде простого скрипта:

# nano /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh
reload-nginx.sh
#!/bin/sh
systemctl reload nginx

Сделаем файл исполняемым

# chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh

Созданный нами хук reload-nginx.sh не должен срабатывать при каждом запуске службы certbot.service инициированном таймером certbit.timer (в нашем случае ~ каждые 12 часов), но должен сработать только в момент, когда Let’s Encrypt реально выпустит новый сертификат (раз в ~60–90 дней, если срок жизни стандартный).

Обратите внимание на то, что созданный нами хук в каталоге /etc/letsencrypt/renewal-hooks/deploy/ имеет глобальный характер. То есть он будет выполняться при каждой процедуре обновления certboot вне зависимости от того, каким приложением внутри нашей системы эти сертификаты используются.

В некоторых случаях в рамках одного сервера могут работать разные приложения, использующие разные сертификаты Let’s Encrypt. В таких ситуациях можно использовать иной подход к управлению хуками и конфигурация перезапуска приложений может настраиваться не глобально в /etc/letsencrypt/renewal-hooks/deploy/, а персонально для каждого сайта через редактирование файлов вида /etc/letsencrypt/renewal/mydomain.ru.conf. В этом файле можно добавить директиву перезапуска нужного приложения в секцию [renewalparams]

mydomain.ru.conf
...
[renewalparams]
...
renew_hook = systemctl reload nginx

Удаление ненужных сертификатов

Сертификаты используемые в конфигурации веб-сервера хранятся в каталоге /etc/letsencrypt/live/, но иногда бывают ситуации, когда мы изменили состав альтернативных имён в сертификате и тогда получается, что в этом каталоге создаётся новая цепочка хранения. Например, в нашем случае, ранее это был подкаталог mydomain.ru, а после изменения состава имён образовалась новая структура в виде подкаталога mydomain.ru-0001.

# tree /etc/letsencrypt/live/
/etc/letsencrypt/live/ ├── mydomain.ru │   ├── cert.pem -> ../../archive/mydomain.ru/cert2.pem │   ├── chain.pem -> ../../archive/mydomain.ru/chain2.pem │   ├── fullchain.pem -> ../../archive/mydomain.ru/fullchain2.pem │   ├── privkey.pem -> ../../archive/mydomain.ru/privkey2.pem │   └── README ├── mydomain.ru-0001 │   ├── cert.pem -> ../../archive/mydomain.ru-0001/cert1.pem │   ├── chain.pem -> ../../archive/mydomain.ru-0001/chain1.pem │   ├── fullchain.pem -> ../../archive/mydomain.ru-0001/fullchain1.pem │   ├── privkey.pem -> ../../archive/mydomain.ru-0001/privkey1.pem │   └── README └── README

И если мы забыли откорректировать конфигурацию SSL в nginx, то могут возникнуть проблемы с работой сайта.

В этом случае, может потребоваться удаление неиспользуемых сертификатов.

Однако, руками просто так удалять подкаталог в /etc/letsencrypt/live/ не следует. Certbot устроен так, что live/ содержит лишь символические ссылки на файлы из archive/, а ещё есть метаданные в renewal/. Если удалить только в live/, то конфигурация поломается.

Как же правильно удалить более ненужные сертификаты в Certbot?

Посмотрим список сертификатов:

# certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: mydomain.ru-0001 Serial Number: 674520824f3d4bf6c2f3125899466351d8f Key Type: ECDSA Domains: mydomain.ru blog.mydomain.ru forum.mydomain.ru wiki.mydomain.ru Expiry Date: 2025-11-20 06:24:03+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/mydomain.ru-0001/fullchain.pem Private Key Path: /etc/letsencrypt/live/mydomain.ru-0001/privkey.pem Certificate Name: mydomain.ru Serial Number: 5010a32577f823b796c290d3192cf898642 Key Type: ECDSA Domains: mydomain.ru blog.mydomain.ru forum.mydomain.ru Expiry Date: 2025-11-15 11:25:20+00:00 (VALID: 85 days) Certificate Path: /etc/letsencrypt/live/mydomain.ru/fullchain.pem Private Key Path: /etc/letsencrypt/live/mydomain.ru/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Удалим ненужный сертификат, указав в параметре –cert-name значение из Certificate Name в выводе предыдущей команды:

# certbot delete --cert-name mydomain.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The following certificate(s) are selected for deletion: * mydomain.ru WARNING: Before continuing, ensure that the listed certificates are not being used by any installed server software (e.g. Apache, nginx, mail servers). Deleting a certificate that is still being used will cause the server software to stop working. See https://certbot.org/deleting-certs for information on deleting certificates safely. Are you sure you want to delete the above certificate(s)? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y Deleted all files relating to certificate mydomain.ru.

Такой метод удаления сертификата безопасный, так как certbot уберёт ссылки из live/, файлы из archive/ и соответствующий .conf в renewal/.

После этого проверяем список сертификатов повторно:

# certbot certificates

При необходимости можно удалить все ранее запрошенные сертификаты, после чего запросить заново свежий сертификат.


Проверено на следующих конфигурациях:

Версия ОС Версия certbot Версия NGINX
Debian GNU/Linux 13.0 (Trixie) certbot 4.0.0-2 nginx 1.26.3-3

Автор первичной редакции:
Алексей Максимов
Время публикации: 05.09.2025 11:50

Обсуждение

Ваш комментарий:
 
web-server-nginx/setting-up-automatic-renewal-of-lets-encrypt-ssl-certificates-in-nginx-using-certbot-on-debian-13.txt · Последнее изменение: Алексей Максимов

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki