Задача: использовать сертификаты Let's Encrypt для персонального сервера Debian/Ubuntu: вебсервер, почта, xmpp. Для операций над сертификатами используем certbot.
Серверный софт: Nginx, Prosody, Exim4.
Дальше все инструкции для моих доменов, это в точности та конфигурация, которая у меня на сервере.
Текст будет обновляться по мере возникновения новых проблем.
Шаг 1. Подготовка серверного окружения¶
Ставим certbot:
$ sudo apt install certbot
Certbot хранит свою конфигурацию в каталоге /etc/letsencrypt/
и лучше не лазить туда руками, а пользоваться только командой certbot.
Для корректной работы плагина webroot
я решил сделать отдельный каталог, куда бы certbot
писал необходимые файлы для подтверждения домена (источник).
$ sudo mkdir -p /var/www/certbot
Дальше создаём сниппет для nginx. Пишем в файл /etc/nginx/snippets/certbot-webroot-acme-challenge.conf
следующее:
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /var/www/certbot;
}
location = /.well-known/acme-challenge/ {
return 404;
}
Или можете скачать готовый так:
$ sudo wget 'https://raw.githubusercontent.com/sigsergv/blog-data/master/letsencrypt/certbot-webroot-acme-challenge.conf' \
-O /etc/nginx/snippets/certbot-webroot-acme-challenge.conf
Дальше во все необходимые конфиги (/etc/nginx/sites-enabled/
) добавляем такую строчку в секцию server
:
server {
listen 80;
....здесь остальные строки конфига....
include /etc/nginx/snippets/certbot-webroot-acme-challenge.conf;
}
Перезапускаем nginx:
$ sudo systemctl restart nginx
Шаг 2. Создание сертификата¶
Я сделал два сертификата. Один для nginx и доменов regolit.com, blog.regolit.com, www.regolit.com, misc.regolit.com, smtp.regolit.com
, второй — специально для домена jabber.regolit.com
. Делаются они такими командами:
$ sudo certbot certonly --webroot -d regolit.com,blog.regolit.com,www.regolit.com,misc.regolit.com,smtp.regolit.com --webroot-path /var/www/certbot
$ sudo certbot certonly --webroot -d jabber.regolit.com --webroot-path /var/www/certbot
После успешного завершения скрипта будет показана вся нужная информация: что было создано и куда положено.
Я НЕ пользуюсь фичами certbot по установке сертификатов, вместо этого я их сам раскладываю куда надо.
Шаг 3. Установка сертификатов¶
nginx¶
Для nginx в конфиг (у меня это /etc/nginx/sites-enabled/default
) нужно прописать такое:
ssl_certificate_key /etc/letsencrypt/live/regolit.com-0001/privkey.pem;
ssl_certificate /etc/letsencrypt/live/regolit.com-0001/fullchain.pem;
prosody¶
К сожалению, для prosody нельзя указать напрямую путь к приватному ключу (и сертификату) из хранилища certbot, поскольку программа запускается не от юзера root, а все файлы в каталоге /etc/letsencrypt/live/
доступны для чтения только юзеру root. Поэтому ключ и сертификат сначала копируем в каталог prosody и меняем пермиссии с владельцем. Всё эти команды (они дальше уйдут в hook-файл, запускаемый автоматически после обновления сертификата):
cp /etc/letsencrypt/live/jabber.regolit.com/privkey.pem /etc/prosody/certs/jabber.regolit.key
cp /etc/letsencrypt/live/jabber.regolit.com/fullchain.pem /etc/prosody/certs/jabber.regolit.pem
chown prosody:prosody /etc/prosody/certs/jabber.regolit.{key,pem}
chmod 0600 /etc/prosody/certs/jabber.regolit.{key,pem}
Для Prosody конфиг /etc/prosody/conf.avail/regolit.com.cfg.lua
меняется так:
VirtualHost "regolit.com"
ssl = {
key = "/etc/prosody/certs/jabber.regolit.key";
certificate = "/etc/prosody/certs/jabber.regolit.pem";
}
Шаг 4. Настройка обновления сертификата¶
certbot устанавливает cron-скрипт /etc/cron.d/certbot
, который автоматически обновляет сертификат, когда в этом возникает необходимость. Вручную можно запустить обновление для всех локальных сертификатов так:
$ sudo certbot renew
Можно протестировать обновление, добавив аргумент --dry-run
, в этом случае certbot не будет сохранять на диск новые сертификаты. Однако какие-то новые файлы в /etc/letsencrypt/
созданы всё равно появятся.
После обновления сертификата на диске нужно как минимум перезапустить затронутые серверы. А для prosody нужно ещё и обновить копии сертификата и ключа.
Но моя цель — полностью автоматизировать всё: при появлении нового сертификата должны перезапуститься серверы, а для prosody нужно ещё и скопировать новые сертификаты куда надо и перезапустить.
Также в этом файле мы копируем сертификат и ключ в файлы exim4, он тоже как и prosody не умеет корректно работать с симлинками.
Для этого создаём файл /root/certbot-post-hook
:
#!/bin/bash
cp /etc/letsencrypt/live/jabber.regolit.com/privkey.pem /etc/prosody/certs/jabber.regolit.key
cp /etc/letsencrypt/live/jabber.regolit.com/fullchain.pem /etc/prosody/certs/jabber.regolit.pem
chown prosody:prosody /etc/prosody/certs/jabber.regolit.{key,pem}
chmod 0600 /etc/prosody/certs/jabber.regolit.{key,pem}
cat /etc/letsencrypt/live/regolit.com-0001/privkey.pem > /etc/exim4/regolit.com.key
cat /etc/letsencrypt/live/regolit.com-0001/fullchain.pem > /etc/exim4/regolit.com.pem
/bin/systemctl reload prosody # since version 0.10 it will reload certificates
/bin/systemctl reload nginx
Его можно скачать и установить так:
$ wget -O /root/certbot-post-hook https://raw.githubusercontent.com/sigsergv/blog-data/master/letsencrypt/certbot-post-hook
$ chmod +x /root/certbot-post-hook
Дальше нужно отредактировать cron-скрипт /etc/cron.d/certbot
:
# /etc/cron.d/certbot: crontab entries for the certbot package
#
# Upstream recommends attempting renewal twice a day
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --post-hook /root/certbot-post-hook
Рандомная скриптота¶
Список всех сертификатов в локальном хранилище¶
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Found the following certs:
Certificate Name: jabber.regolit.com
Domains: jabber.regolit.com
Expiry Date: XXXX-XX-XX XX:XX:XX+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/jabber.regolit.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/jabber.regolit.com/privkey.pem
Certificate Name: regolit.com
Domains: regolit.com blog.regolit.com jabber.regolit.com misc.regolit.com www.regolit.com
Expiry Date: XXXX-XX-XX XX:XX:XX+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/regolit.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/regolit.com/privkey.pem
Certificate Name: regolit.com-0001
Domains: regolit.com blog.regolit.com misc.regolit.com www.regolit.com
Expiry Date: XXXX-XX-XX XX:XX:XX+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/regolit.com-0001/fullchain.pem
Private Key Path: /etc/letsencrypt/live/regolit.com-0001/privkey.pem
-------------------------------------------------------------------------------
Отзыв сертификата¶
$ sudo certbot revoke --cert-path /etc/letsencrypt/live/regolit.com/fullchain.pem
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Congratulations! You have successfully revoked the certificate that was located
at /etc/letsencrypt/live/regolit.com/fullchain.pem
-------------------------------------------------------------------------------
После отзыва сертификат остаётся в локальном хранилище. Удалить его оттуда можно так:
$ sudo certbot delete --cert-name regolit.com
Saving debug log to /var/log/letsencrypt/letsencrypt.log
-------------------------------------------------------------------------------
Deleted all files relating to certificate regolit.com.
-------------------------------------------------------------------------------