Expertus metuit
Let's Encrypt, certbot и debian
2018-03-10 13:35

Задача: использовать сертификаты Let's Encrypt для персонального сервера: вебсервер, почта, xmpp.

Серверный софт: Nginx, Prosody. В будущем — Exim4.

Базовая инструкция: https://certbot.eff.org/#debianstretch-nginx

Дальше всё для моего домена, это в точности та конфигурация, которая у меня на сервере.

Текст будет обновляться по мере возникновения новых проблем.

Шаг 1. Подготовка серверного окружения

Ставим certbot:

$ sudo apt install 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;
}

Шаг 2. Создание сертификата

Я сделал два сертификата. Один для nginx и доменов regolit.com, blog.regolit.com, www.regolit.com, misc.regolit.com, второй — специально для домена jabber.regolit.com. Делаются они такими командами:

$ sudo certbot certonly --webroot -d regolit.com,blog.regolit.com,www.regolit.com,misc.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-скрипт, который автоматически обновляет сертификат, когда в этом возникает необходимость. Вручную можно запустить обновление для всех локальных сертификатов так:

$ sudo certbot renew

Можно протестировать обновление, добавив аргумент --dry-run, в этом случае certbot не будет сохранять на диск новые сертификаты. Однако какие-то новые файлы в /etc/letsencrypt/ созданы всё равно появятся.

После обновления сертификата на диске нужно как минимум перезапустить затронутые серверы. А для prosody нужно ещё и обновить копии сертификата и ключа.

Но моя цель — полностью автоматизировать всё: при появлении нового сертификата должны перезапуститься серверы, а для 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}
/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

Рандомная скриптота

Не стоит ручками лазить в каталог /etc/letsencrypt/, вместо этого пользуйтесь командами certbot.

Список всех сертификатов в локальном хранилище

$ 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.
-------------------------------------------------------------------------------

Комментарии

Текст комментария (разметка: *курсив*, **полужирная**, [ссылка](http://example.com) или <http://example.com> ещё)
Имя (обязательно, 50 символов или меньше)
Опциональный email, на который получать ответы (не будет опубликован)
Веб-сайт
© 2006—2018 Sergey Stolyarov | Работает на Pyrone