Пошаговые руководства, шпаргалки, полезные ссылки...
Блог IT-KBДискуссии
Полезные Online-сервисы
Перечень Бесплатного ПО
Подписка на RSS-канал
Базовую настройку веб-сервера NGINX для поддержки HTTPS мы рассматривали ранее в заметке Настройка веб-сервера на базе стека LEMP в Ubuntu Server 14.04 LTS. Часть 11. Настройка поддержки HTTPS в Nginx, Wordpress и phpBB. В этой заметке мы немного расширим эту тему и рассмотрим то, как можно автоматизировать процесс регулярного обновления SSL сертификатов, привязанных к сайтам nginx. Бесплатные криптографические сертификаты X.509 будем получать в центре сертификации Let's Encrypt, а с помощью пакета certbot настроим автоматизацию обновления этих сертификатов с интеграцией в конфигурацию веб-сервера nginx.
Устанавливаем пакет certbot из стандартных репозиториев Debian Linux
# apt install certbot
Создаём каталог для временных файлов Let's Encrypt и делаем его владельцем пользователя и группу, в контексте которых работает веб-сервер:
# mkdir /var/www/letsencrypt # chown www-data:www-data /var/www/letsencrypt
Выносим текущую конфигурацию SSL из /etc/nginx/nginx.conf в отдельный файл /etc/nginx/snippets/ssl.conf
# nano /etc/nginx/snippets/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
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 Например:
ssl.conf
letsencrypt.conf
server
/etc/nginx/sites-available/*.conf
# nano /etc/nginx/sites-available/mydomain.conf
... server { listen 443 ssl; include snippets/ssl.conf; include snippets/letsencrypt.conf; ... }
Регистрируем экземпляр 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:
/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. ...
Добавляем полученные сертификаты в 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 можно добавить хук для перезапуска веб-сервера после обновления сертификатов
/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 ...
Как видим, есть два юнита:
По умолчанию юниты сконфигурированы следующим образом:
# 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.
certbot -q renew –no-random-sleep-on-renew
Если по какой-то причине таймер не включен, то включаем и запускаем его
# 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/.
/etc/letsencrypt/renewal-hooks/deploy/
Создадим хук в виде простого скрипта:
# nano /etc/letsencrypt/renewal-hooks/deploy/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 дней, если срок жизни стандартный).
reload-nginx.sh
Обратите внимание на то, что созданный нами хук в каталоге /etc/letsencrypt/renewal-hooks/deploy/ имеет глобальный характер. То есть он будет выполняться при каждой процедуре обновления certboot вне зависимости от того, каким приложением внутри нашей системы эти сертификаты используются.
В некоторых случаях в рамках одного сервера могут работать разные приложения, использующие разные сертификаты Let’s Encrypt. В таких ситуациях можно использовать иной подход к управлению хуками и конфигурация перезапуска приложений может настраиваться не глобально в /etc/letsencrypt/renewal-hooks/deploy/, а персонально для каждого сайта через редактирование файлов вида /etc/letsencrypt/renewal/mydomain.ru.conf. В этом файле можно добавить директиву перезапуска нужного приложения в секцию [renewalparams]
[renewalparams]
... [renewalparams] ... renew_hook = systemctl reload nginx
Сертификаты используемые в конфигурации веб-сервера хранятся в каталоге /etc/letsencrypt/live/, но иногда бывают ситуации, когда мы изменили состав альтернативных имён в сертификате и тогда получается, что в этом каталоге создаётся новая цепочка хранения. Например, в нашем случае, ранее это был подкаталог mydomain.ru, а после изменения состава имён образовалась новая структура в виде подкаталога mydomain.ru-0001.
/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/, то конфигурация поломается.
live/
archive/
renewal/
Как же правильно удалить более ненужные сертификаты в 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 в выводе предыдущей команды:
–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
При необходимости можно удалить все ранее запрошенные сертификаты, после чего запросить заново свежий сертификат.
Проверено на следующих конфигурациях:
Автор первичной редакции: Алексей Максимов Время публикации: 05.09.2025 11:50