Nginx Proxy Manager и Let's Encrypt
У меня используется Nginx Proxy Manager(NPM) в качестве обратного прокси для моих сервисов в докере. Ранее я использовал связку DuckDNS и сертификат от LE. Идея простая: регистрируем бесплатный домен 3 уровня на DuckDNS, направляем его на наши хосты и в NPM получаем сертификат от LE методом dns challenge. Все максимально просто, нужно лишь указать свой ключ для доступа к апи DuckDNS, как результат получаем домены для всех домашних сервисов с ssl. По этому поводу если неплохое видео на youtube:
Но что делать если у нас есть домен находящийся на NS'ах с которыми NPM не может работать по api и нужно получить wcard сертификат?
Тут есть 2 варианта:
- перенести домен на сервера с которыми Let's Encrypt certbot умеет работать по апи.
- получить сертификат вручную.
Я решил пойти по второму пути.
Получение сертификата.
Так как NPM штатно не умеет получать сертификат от LE вручную для wildcard доменов, то придется делать руками это через консоль:
- Заходим в контейнер с NPM:
root@hub ~ # docker exec -it nginx_proxy /bin/bash
_ _ _ ____ __ __
| \ | | __ _(_)_ __ __ _| _ \ _ __ _____ ___ _| \/ | __ _ _ __ __ _ __ _ ___ _ __
| \| |/ _` | | '_ \\ \/ / |_) | '__/ _ \ \/ / | | | |\/| |/ _` | '_ \ / _` |/ _` |/ _ \ '__|
| |\ | (_| | | | | |> <| __/| | | (_) > <| |_| | | | | (_| | | | | (_| | (_| | __/ |
|_| \_|\__, |_|_| |_/_/\_\_| |_| \___/_/\_\\__, |_| |_|\__,_|_| |_|\__,_|\__, |\___|_|
|___/ |___/ |___/
Version 2.11.3 (35d7a3a) 2024-07-01 11:42:06 UTC, OpenResty 1.21.4.3, debian 12 (bookworm), Certbot certbot 2.11.0
Base: debian:bookworm-slim, linux/amd64
Certbot: nginxproxymanager/nginx-full:latest, linux/amd64
Node: nginxproxymanager/nginx-full:certbot, linux/amd64
[root@docker-42520cfafb61:/app]#
- Пробуем получить сертификат вручную:
[root@docker-42520cfafb61:/app]# certbot certonly --manual --preferred-challenges dns -d cave-labs.ru,*.cave-labs.ru
В процессе бот попросит нас добавить TXT запись с ключом для домена _acme-challenge.cave-labs.ru. После добавления ждем несколько минут пока обновятся dns и подтверждаем что запись добавлена, в конце бот сообщит что сертификат получен и покажет куда он его сохранил.
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/cave-labs.ru/fullchain.pem
Key is saved at: /etc/letsencrypt/live/cave-labs.ru/privkey.pem
This certificate expires on 2025-01-24.
Так у нас есть wcard сертификат от let's encrypt. Далее я вытащил ключ с сертификатом из контейнера и вручную добавил его в NPM через web
Обновление сертификата.
Как же обновить сам сертификат если мы выпускали его вручную? Выпускать заново сертификат не нужно, certbot умеет обновлять текущий сертификат. Я это делал вручную:
[root@docker-42520cfafb61:/app]# certbot certonly --manual --expand --force-renewal --preferred-challenges dns -d cave-labs.ru,*.cave-labs.ru
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Renewing an existing certificate for cave-labs.ru and *.cave-labs.ru
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/cave-labs.ru/fullchain.pem
Key is saved at: /etc/letsencrypt/live/cave-labs.ru/privkey.pem
This certificate expires on 2025-01-24.
These files will be updated when the certificate renews.
NEXT STEPS:
- This certificate will not be renewed automatically. Autorenewal of --manual certificates requires the use of an authentication hook script (--manual-auth-hook) but one was not provided. To renew this certificate, repeat this same certbot command before the certificate's expiry date.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ключ --expand дополнит уже существующий сертификат, а --force-renewal принудительно перезапишет файлы. В моем же случае можно создать отдельный контейнер с кроном и туда добавить туда задание на обновление сертификата либо обновлять сертификат вручную.
На этом можно было бы и остановиться, но в таком случае пришлось бы каждые 3 месяца перепрописывать новый сертификат для всех хостов которых может быть много. Поэтому я решил немного обмануть систему и сделать так чтоб при обновлении wcard сертификата мне не пришлось бы прописывать новый сертификат для каждого хоста отдельно. Тут есть 2 варианта:
- скопировать новый сертификат на место старого тем самым заменив его.
- сделать вместо сертификата ссылку на тот что получил certbot
Для начала смотрим где лежит сертификат установленный через web грепнув конфиги:
[root@docker-42520cfafb61:/app]# grep -rn ssl_certificate /data/nginx/proxy_host/ | awk '{print $3}' | sort | uniq -c
8 /data/custom_ssl/npm-13/fullchain.pem;
8 /data/custom_ssl/npm-13/privkey.pem;
1 /etc/letsencrypt/live/npm-12/fullchain.pem;
1 /etc/letsencrypt/live/npm-12/privkey.pem;
Нас интересует custom_ssl, на первое время я просто заменил сертификат на новый:
# cp -f /etc/letsencrypt/live/cave-labs.ru/fullchain.pem /data/custom_ssl/npm-13/fullchain.pem
cp: overwrite '/data/custom_ssl/npm-13/fullchain.pem'? y
# cp -f /etc/letsencrypt/live/cave-labs.ru/privkey.pem /data/custom_ssl/npm-13/privkey.pem
cp: overwrite '/data/custom_ssl/npm-13/privkey.pem'? y
Однако в данном случае придется каждый раз заменять сертификат. Для того чтобы этого избежать целесообразней сделать символьную ссылку:
[root@docker-42520cfafb61:/app]# rm /data/custom_ssl/npm-13/fullchain.pem
rm: remove regular file '/data/custom_ssl/npm-13/fullchain.pem'? y
[root@docker-42520cfafb61:/app]# ln -s ../../../etc/letsencrypt/live/cave-labs.ru/fullchain.pem /data/custom_ssl/npm-13/fullchain.pem
[root@docker-42520cfafb61:/app]# rm /data/custom_ssl/npm-13/privkey.pem
rm: remove regular file '/data/custom_ssl/npm-13/privkey.pem'? y
[root@docker-42520cfafb61:/app]# ln -s ../../../etc/letsencrypt/live/cave-labs.ru/privkey.pem /data/custom_ssl/npm-13/privkey.pem
[root@docker-42520cfafb61:/app]# ls -l
total 0
lrwxrwxrwx 1 root root 56 Oct 26 23:45 fullchain.pem -> ../../../etc/letsencrypt/live/cave-labs.ru/fullchain.pem
lrwxrwxrwx 1 root root 54 Oct 26 23:46 privkey.pem -> ../../../etc/letsencrypt/live/cave-labs.ru/privkey.pem
Документацию по certbot можно посмотреть тут.