nginx + certbot (Let’s Encrypt)

Возник давно вопрос поставить себе на сервер SSL-сертификат. Пару лет для этого я использовал бесплатный StartSSL, так же слышал про WoSign (но никогда не использовал).

Год назад я впервые услышал о проекте Let’s Encrypt. Автоматизированная система выдачи сертификатов, красота! Этой осенью она начала работать. Значит пришло время изучить данную технологию.

Для Gentoo есть уже ebuild готовый:

emerge -av app-crypt/certbot

Для остальных есть инструкция (по сути склонировать git-репозитарий).

Сертификаты выдаются автоматически с помощью клиента из консоли на 90 дней. Значит надо будет часто обновлять, но автоматизировать процесс не составит труда.

Клиент содержит специализированные плагины для веб-серверов, которые вносят рекомендованные настройки в конфиги серверов (а так же поддержка nginx пока экспериментальная). У меня довольно необычная настройка, поэтому я не доверил автоматике лезть в мои конфиги.

Так же у клиента есть плагин со встроенным веб-сервером для прохождения проверки. А это уже более интересный вариант, особенно учитывая что nginx хорошо справляется с ролью реверсивного прокси-сервера.

Создадим правильный шаблон для nginx - /etc/nginx/templates/certbot.conf

location ~ ^/(.well-known/acme-challenge/.*)$ {
    proxy_pass http://127.0.0.1:9999/$1;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

Если добавить в конфиг сайта строчку include templates/certbot.conf; до первого параметра location, то данный механизм позволит всем запросам на подтверждение certbot правильно пересылаться на встроенный в клиент веб-сервер, запущенный на порту 9999.

Встроенный в клиент веб-сервер запускается только на время проверки и потом отключается. Так что нет постоянно висящих лишних процессов.

Для запуска клиента я использую следующую команду:

certbot --agree-tos --renew-by-default --standalone --standalone-supported-challenges http-01 --http-01-port 9999 --server https://acme-v01.api.letsencrypt.org/directory certonly -d www.kami-no.ru

В итоге генерируются сертификаты в директории /etc/letsencrypt/archive/www.kami-no.ru/

Клиент рекомендует всё-же использовать симлинки из директории /etc/letsencrypt/live/www.kami-no.ru/

Поэтому в конфиге nginx я использую следующие инструкции:

ssl_certificate /etc/letsencrypt/live/www.kami-no.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.kami-no.ru/privkey.pem;

Останется только перезапустить веб-сервер.

Перевыпуск осуществляется командой letsencrypt-renewer используя cron в 3:00 первого числа каждого месяца:

0 3 1 * * /usr/bin/certbot renew >> /dev/null 2>&1
0 4 1 * * /usr/bin/systemctl reload nginx >> /dev/null 2>&1

Стоит учитывать так же, что существует ограничение на число выдаваемых сертификатов — rate limit. Пока-что механизм обновления не учитывает его, поэтому я предпочитаю обновление через ту же команду, что и выпуск нового сертификата. Если существует сертификат, она попробует его обновить =) В результате я ограничиваю перевыпуск тремя запросами в неделю.

Использование встроенного в клиент Let’s Encrypt веб-сервера позволяет вынести генерацию сертификатов даже на отдельный сервер в случае, если вы не хотите ставить на веб-сервер организации дополнительное ПО сомнительной пока надёжности. Перенос сертификатов можно будет тогда автоматизировать уже хоть через bash (можно в связке с git).