Картофельные лонгриды

Назад, к списку

Ops-костыли: Продлеваем и выпускаем SSL сертификаты автоматически (NGINX + Certbot)

Эта статья не похожа на “объясняющие”, которые я писал раньше; скорее, это пошаговый гайд, который можно добавить в дальние закладки и вспомнить, когда будете разворачивать что-то на новом домене.

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

Настройка автопродления

Подготавливаем NGINX

Если наш NGINX-контейнер уже был в compose, нужно лишь поменять команду для запуска и добавить пару volume’ов, чтобы упростить подкидывание файлов конфигурации и сертификатов:

Наша новая команда для запуска контейнера может казаться довольно сложной для понимания, но по факту она лишь перезагружает каждые шесть часов NGINX, чтобы он не забывал подхватывать новые файлики. Я это сделал таким путём — вы же можете написать свой скрипт покрасивее :)

Если вы уже запускали certbot вне докера для генерации сертификата, то в папку ./data/certbot/conf/ стоит переложить всю папку /etc/letsencrypt с вашего сервера.

Настройка SSL

Если у вас ещё не был настроен SSL, то у certbot есть пара готовых конфигурационных файлов для NGINX: первый выставляет рекомендуемые настройки для SSL, второй — специальный ключ, который увеличивает безопасность соединения. Подробнее о том, что это за ключ, можно прочитать, например, здесь.

Эти файлы я положу в локальную папку ./data/certbot/conf/ и подключу в директиву server вместе с сертификатами:

Не забудьте оставить на 80 порту раздачу /var/www/certbot — туда certbot будет класть токен для acme-challenge.

Автоматизация certbot

У certbot уже есть свой Docker-образ. Нужно только подключить его в наш compose и привязать volumes также, как делали для сервиса NGINX: чтобы свои данные и сертификаты certbot складывал в тот же `/etc/letsencrypt`, из которого мы будем его доставать в NGINX. Точка входа в этот образ — certbot renew каждые 12 часов.

И всё?

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

Выпуск сертификата

Если же вам нужно выпустить сертификат, то придется всё-таки настроить его для начала ручками, но есть один нюанс: при попытке поднять NGINX с уже включенным SSL и указанными путями к ещё несуществующим сертификатам, он упадет.

Нужно сначала поднять его с “фиктивными”, нерабочими сертификатами, удалить их, а уже потом выпускать сертификат нормально.

Сгенерировать подписанный локально сертификат нам поможет инструмент openssl:

openssl req -x509 -nodes -newkey rsa:4096 -days 1 -keyout './data/certbot/conf/live/<домен>/privkey.pem' -out './data/certbot/conf/live/<домен>/fullchain.pem' -subj '/CN=localhost'"

После этого можно спокойно поднимать отдельно nginx docker compose up -d nginx.

А затем спокойно выпускать сертификат с помощью certbot:

docker-compose run --rm --entrypoint " certbot certonly --webroot -w /var/www/certbot --email <свой e-mail> -d "<домен>" --rsa-key-size 4096 --agree-tos --force-renewal" certbot

Если вы ещё не видели команды docker-compose run, она позволяет поднять новый контейнер с указанным сервисом, а флаг --rm говорит докеру, чтобы он удалил контейнер после его завершения. Entrypoint этого контейнера — команда для выпуска сертификата certbot certonly. Про флаги, которые можно в ней использовать, можно прочитать в документации.

После успешного выпуска сертификата остается лишь перезагрузить nginx внутри контейнера, чтобы он увидел новые сертификаты. (docker-compose exec nginx nginx -s reload)

Готово! Вы восхитительны!

Если есть непонятные шаги или возникла какая-то ошибка — пишите мне на me@potatocat.dev, и я дополню этот гайд.