influunt media

influunt media

Who am I?

Блог разработчика: обзор инструментов, практические примеры, мысли и исследования


Продление сертификата Let's Encrypt


Центр сертификации Let's Encrypt выдает SSL сертификат на срок в 90 дней. Продление рекомендуется делать раз в 60 дней. Когда что-то пойдет не так - останется 30 дней на устранение проблем.

Продление сертификатов реализовано по протоколу ACME (Automatic Certificate Management Environment). Для работы с ним потребуется один из рекомендуемых клиентов. В рамках статьи рассмотрен GetSSL.

Let's Encrypt ввел ограничение на количество запросов: 20 запросов в неделю для каждого домена. Установка GetSSL, отладка и получение сертификата описано в статье получение сертификата Let's Encrypt.

Автоматизация продления сертификата

Участие пользователя в обновлении нежелательно. Человеческий фактор - причина возникновения исключительных ситуаций. Частичная автоматизация процесса поможет избежать приключений и сохранить здоровый сон. Она достигается с помощью таймер юнита systemd.

Настройка GetSSL

Процесс продления аналогичен получению. Команда getssl domain.tld обновит сертификат для каждого домена.

Nginx не сканирует изменения в файловой системе. Чтобы применить обновленный сертификат нужно перезапустить сервис Nginx. В конфигурационном файле GetSSL за это отвечает параметр RELOAD_CMD:

RELOAD_CMD="systemctl restart nginx"
Убираем человека из процесса

Научить systemd запускать GetSSL можно с помощью сервиса. Сервис юнит (файл с расширением ".service") описывает процесс запуска и остановки демона. Файл должен содержать секцию [Service]: в ней указывается информация о процессе и том, как его контролировать.

GetSSL - bash скрипт. Время его жизни после запуска ограничено. Тип сервиса oneshot будет достаточен. В рамках него выполняется только одна комманда: ExecStart=. Создайте файл сервиса /etc/systemd/system/lets-encrypt-renewal.service:

[Unit]
Description=Let's Encrypt certificate renewal

[Service]
Type=oneshot
ExecStart=/bin/getssl domain.tld

Секция [Install] намеренно опущена. Сервис нельзя добавлять в автозагрузку. Его запуск должен инициироваться по событию от таймера. В противном случае, после перезагрузки системы systemd запустит процесс продления сертификата. Превышение 20 запросов в неделю приводит к блокировке.

Добавление GetSSL в автозапуск

Таймер юнит (файл с расширением ".timer") описывает события при которых нужно запустить сервис. Секция [Timer] позволяет указывать время относительно: даты загрузки системы, времени работы сервиса, времени последней активации, календаря и других.

Срок валидности сертификата начинается с момента его получения. С помощью параметра OnUnitActiveSec= можно задать время цикла повторений. Интервал между продлениями примем за 60 дней. Флаг Persistent=true сделает юнит персистентным: после перезагрузки таймер продолжится с последнего значения. Создайте файл таймера /etc/systemd/system/lets-encrypt-renewal.timer:

[Unit]
Description=Let's Encrypt certificate renewal

[Timer]
OnUnitActiveSec=60d
Persistent=true

[Install]
WantedBy=timers.target

И поместите его в автозагрузку:

srv ~ # systemctl enable lets-encrypt-renewal.timer
Created symlink from /etc/systemd/system/timers.target.wants/lets-encrypt-renewal.timer to /etc/systemd/system/lets-encrypt-renewal.timer.
srv ~ # 
Запуск и проверка результата

Старт юнитов из автозагрузки выполняется только при старте системы. Поэтому таймер нужно запустить вручную:

srv ~ # systemctl start lets-encrypt-renewal.timer
srv ~ # systemctl list-timers
NEXT                          LEFT                  LAST                          PASSED       UNIT                         ACTIVATES
Wed 2016-11-09 19:51:37 SAMT  15h left              Tue 2016-11-08 19:51:36 SAMT  8h ago       systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service
Sun 2017-01-08 03:19:18 SAMT  1 months 29 days left Wed 2016-11-09 02:41:30 SAMT  1h 12min ago lets-encrypt-renewal.timer   lets-encrypt-renewal.service

2 timers listed.
Pass --all to see loaded but inactive timers, too.
srv ~ #

Команда systemctl list-timers выводит список запущенных в системе таймеров. Ваш список может отличаться. Если вы видите его в списке - таймер был успешно запущен.

Чтобы убедиться в работоспособности сервиса продления lets-encrypt-renewal запустите его:

srv ~ # systemctl start lets-encrypt-renewal && journalctl -f -u lets-encrypt-renewal
Nov 09 03:58:58 srv systemd[1]: Starting Let's Encrypt certificate renewal...
Nov 09 03:58:58 srv getssl[10568]: Registering account
Nov 09 03:58:58 srv getssl[10568]: Verify each domain
Nov 09 03:58:58 srv getssl[10568]: Verifing domain.tld
Nov 09 03:58:58 srv getssl[10568]: copying challenge token to /var/www/domain.tld/web/.well-known/acme-challenge/ICeEYD-dhUrDxTfm0DqGoiaifej_UvogBsoacW67Ckg
Nov 09 03:58:58 srv getssl[10568]: Verified domain.tld
Nov 09 03:58:58 srv getssl[10568]: Verifing www.domain.tld
copying challenge token to /var/www/domain.tld/web/.well-known/acme-challenge/gZVmGkR-zDpdQ63XgOhWaKx3WetiqtrYXLifNRTv1_A
Nov 09 03:58:58 srv getssl[10568]: Verified www.domain.tld
Nov 09 03:58:58 srv getssl[10568]: Verification completed, obtaining certificate.
Nov 09 03:58:58 srv getssl[10568]: Certificate saved in /root/.getssl/domain.tld/domain.tld.crt
Nov 09 03:58:58 srv getssl[10568]: The intermediate CA cert is in /root/.getssl/domain.tld/chain.crt
Nov 09 03:58:58 srv getssl[10568]: copying domain certificate to /etc/ssl/domain.tld.crt
Nov 09 03:58:58 srv getssl[10568]: copying private key to /etc/ssl/domain.tld.key
Nov 09 03:58:58 srv getssl[10568]: copying CA certificate to /etc/ssl/chain.crt
Nov 09 03:58:58 srv getssl[10568]: copying full chain to /etc/ssl/domain-chain.crt
Nov 09 03:58:58 srv getssl[10568]: reloading SSL services
Nov 09 03:58:58 inf-1 systemd[1]: Started Let's Encrypt certificate renewal.
srv ~ # 

Команда journalctl -f -u lets-encrypt-renewal выводит лог сервиса. Если вы видите в нем Verification completed, obtaining certificate. - сертификат был успешно продлен.

Обновление сертификата должно было вызвать перезапуск Nginx. Проверить срок действия можно с помощью openssl. Запустите команду:

srv ~ # echo | openssl s_client -connect domain.tld:443 2>/dev/null | openssl x509 -noout -dates
notBefore=Nov 09 03:59:05 2016 GMT
notAfter=Feb 07 03:59:05 2017 GMT
srv ~ #

Не забудьте заменить domain.tld:443 на ваше доменное имя и порт

Если срок выдачи изменился - вся цепочка работает и не требует сторонних действий.

Немного дёгтя на последок

В Nginx отсутствует возможность "перечитать" настройки. Чтобы применить продленный сертификат приходится его перезапускать. Последствия? Очищенный кэш и потенциально разорванные соединения - цена, с которой придется мириться.