Кому не интересно читать небольшую предысторию, для перехода к установке и настройке жмите сюда.
Некоторое время для выпуска сертификатов Letsencrypt пользовался клиентом acme-client.sh . Но в мае 2019 он был удален из портов и перестал поддерживаться разработчиком, т.к. был включен в OpenBSD. Пользовался я им еще с пол года, хотя это доставляло некоторые неудобства при обновлении портов.
Но момент замены все же настал. В декабре попытался выпустить сертификат, а Letsencrypt сказал хрен тебе с этим клиентом, а не сертификат для нового домена, только перевыпуск для старых…. Обновляйся!
Ну что же, ладно. Иду на Letsencrypt и смотрю кто там требует минимум доп зависимостей. Оказалось на bash есть 4 клиента:
- GetSSL
- acme.sh
- dehydrated
- ght-acme.sh
dehydrated мне был уже знаком, начну думаю с него. Установил из портов, начинаю настраивать сертификаты… И тут бац:
# INFO: Using main config file /usr/local/etc/dehydrated/config
ERROR: DEHYDRATED_USER set but sudo not available. Please install sudo.
gold,pts,/usr/local/etc/dehydrated,6$id
uid=443(_letsencrypt) gid=443(_letsencrypt) groups=443(_letsencrypt)
gold,pts,/usr/local/etc/dehydrated,7$grep DEHYDRATED_USER /usr/local/etc/dehydrated/config
DEHYDRATED_USER=_letsencrypt
sudo не установлен и не хочу. С рута заводить его не хочется… :/
На GitHub есть репорт по этой проблеме еще с 20.08.2019. Разработчик обещал пофиксить, но на сегодняшний момент так этого и не сделал. Ладно, раз ты такой скоростной идем дальше.
Дальше думаю возьму acme.sh …
Установка Acme.sh
Ладно, хватит лирики. Поехали.
Клиент будет работать без рута, от юзера acme. Папка с сертификатами и конфигами тут: /var/db/acme/. (Добавляются по дефолту при установке)
# cd /usr/ports/security/acme.sh
# make config
# make install clean
Создаем необходимые папки: 1-я для проверки Letsencrypt на принадлежность домена; 2-я для сертификатов. И устанавливаем им права.
# mkdir /usr/local/www/acme-ssl
# chown acme:www /usr/local/www/acme-ssl
# mkdir /usr/local/etc/nginx/ssl
# chown acme:www /usr/local/etc/nginx/ssl
Создадим общий конфиг для всех доменов:
# cd /usr/local/etc/nginx/conf.d
# touch acme-ssl.conf
Далее любимым редактором в файл acme-ssl.conf пишем:
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
alias /usr/local/www/acme-ssl/.well-known/acme-challenge/;
try_files $uri =404;
}
Перед выпуском сертификата добавляем в конфиг nginx для домена:
server {
...
include /usr/local/etc/nginx/conf.d/acme-ssl.conf
...
}
Не забываем перезагрузить конфиги:
# service nginx reload
Выпуск и установка сертификата
# su acme -c "acme.sh --issue -d zajtcev.org -w /usr/local/www/acme-ssl"
Выпуск сертификата для нескольких поддоменов в одном сертификате:
# su acme -c "acme.sh --issue -d zajtcev.org -d www.zajtcev.org -d cp.zajtcev.org -w /usr/local/www/acme-ssl"
Для выпуска использую webroot. Если захотите wildcard сертификат, тогда только dns-01
Создаем папку для сертификатов:
# mkdir /usr/local/etc/nginx/ssl/zajtcev.org
# chown acme:www /usr/local/etc/nginx/ssl/zajtcev.org
Устанавливаем сертификаты, в заранее созданную папку:
# su acme -c 'acme.sh --install-cert -d zajtcev.org --key-file /usr/local/etc/nginx/ssl/zajtcev.org/privkey.pem --ca-file /usr/local/etc/nginx/ssl/zajtcev.org/chain.pem --cert-file /usr/local/etc/nginx/ssl/zajtcev.org/cert.pem --fullchain-file /usr/local/etc/nginx/ssl/zajtcev.org/fullchain.pem --reloadcmd "touch /var/db/acme/.restart_nginx"'
Сертификаты будут скопированы в папку для nginx и эти пути будут прописаны в конфигах для последующих обновлений.
Отдельно стоит отметить —reloadcmd. Но к этому вернемся чуть ниже.
Далее пропишем сертификаты в nginx.
server {
...
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /usr/local/etc/nginx/ssl/zajtcev.org/fullchain.pem;
ssl_certificate_key /usr/local/etc/nginx/ssl/zajtcev.org/privkey.pem;
ssl_trusted_certificate /usr/local/etc/nginx/ssl/zajtcev.org/fullchain.pem;
...
}
Ну и конечно же проверяем и применяем конфиги nginx:
# service nginx configtest
# service nginx reload
Если до этого момента ошибок не возникло, Поздравляю! Сертификаты установлены и сайт даже возможно уже работает по https. :)
Осталось дело за малым — настроить автоматический перевыпуск сертификатов. Поехали.
Перевыпуск сертификатов —cron
Теперь вернемся к -reloadcmd.
Т.к. клиент будет работать от юзера acme, а не от рута, то он не сможет перезагрузить nginx.
Сначала пытался разобраться с кодами ответов при проверке/обновлении сертификатов, но вне зависимости от обновления сертификатов или нет, он постоянно отвечал 0.
На форуме freebsd один пользователь подсказал идею с файлом. Т.е. если обновится сертификат будет создан файл .restart_nginx. А мы уже от рута будем проверять есть ли этот файл или нет и перегружать nginx.
# touch /home/scripts/acme_deploy.sh
Ну и сам простенький код:
#!/bin/sh
set -e
if [ -f /var/db/acme/.restart_nginx ]; then
service nginx reload
rm -rf /var/db/acme/.restart_nginx
fi
Теперь Добавим в крон обновление сертификатов для юзера acme
# su acme
# crontab -e
#minute hour mday month wday command
10 05 * * * /usr/local/sbin/acme.sh --cron --home "/var/db/acme/.acme.sh"
Возвращаемся к руту
#exit
Теперь для рута добавим задание
# crontab -e
#minute hour mday month wday who command
15 05 * * * /bin/sh /home/scripts/acme_deploy.sh
Выше я проверяю сертификаты в 05:10 и в 05:15 проверяю наличие файла для применения сертификатов каждый день. Но сейчас подумываю делать это раз в неделю, как было у меня раньше.
И так, Практически готово. Осталось добавить ротацию логов и все.
# ee /usr/local/etc/newsyslog.conf.d/newsyslog.conf
/var/log/acme.sh.log acme:acme 640 90 * @T00 BC
Удаление Домена из Списка Acme.sh Автообновления
Для удаления необходимо выполнить следующие три команды
# su acme -c "acme.sh --remove -d zajtcev.org"
# rm -r /var/db/acme/certs/zajtcev.org
# rm -r /usr/local/etc/nginx/ssl/zajtcev.org
Ну Вот вроде и все. :)
Послесловие. Полезные команды.
Для расширенного просмотра ответов acme.sh добавляйте —debug
Посмотреть список всех доменов для которых были выпущены сертификаты и срок окончания дествия сертификата:
# su acme -c 'acme.sh --list'
Ручное обновление сертификата для одного домена:
# su acme -c "acme.sh --renew -d zajtcev.org --force"
Ручное обновление сертификатов для всех доменов:
# su acme -c "acme.sh --renew-all --force "
Удалить домен:
# su acme -c "acme.sh --remove -d zajtcev.org"
Если установите /usr/sbin/nologin для юзера acme, тогда все команды su делаем с -m модификатором и прописываем пути для home и log. Пример:
# su -m acme -c "acme.sh --issue -d zajtcev.org --home /var/db/acme/certs -w /usr/local/www/acme-ssl --log /var/log/acme.sh.log"
PS. Если что-то упустил или столкнулись с трудностью пишите в комментах.