Получаем wildcard сертификат letsencrypt с помощью acme.sh
Привет. Указанные ниже скрипты работают на виртуалке, которая занимается получением сертификатов. Потом на эту виртуалку приходит ansible по крону, забирает сертификаты и раскатывает их по всем остальным серверам и виртуалкам, где оно нужно.
Настраиваем cloudflare
На cloudflare делаешь аккаунт. Здесь всё просто и без подсказок справишься.
На втором этапе необходимо определить, DNS обслуживание домена будет происходить на cloudflare или же на другом ресурсе.
Если на cloudflare, то переносишь туда доменную зону, к примеру, pasha.com.
Если нет, то на cloudflare заводишь какой-либо «технический» домен, через который будешь получать и обновлять wildcard сертификаты для всех остальных доменов, например, pasha-on-cf.com
На cloudflare делаешь Global API KEY в My profile → API Tokens. Скорее всего можно через API Tokens, но я не пробовал, нужно проверять, какие права выдавать такому токену и тестировать.
Настраиваем DNS записи в домене
Если идёшь по схеме pasha.com, то ничего больше не делаешь на этом этапе.
Если идёшь по схеме pasha-on-cf.com, то в редакторе твоего DNS хостера/сервера для домена pasha.com нужно добавить CNAME запись вида:
_acme-challenge.pasha.com. CNAME _acme-challenge.pasha-on-cf.com.
Устанавливаешь acme.sh
Я устанавливаю под root пользователем, все дальнейшие скрипты исходят из этого.
На данном этапе укажи свой email и выполняй.
curl https://get.acme.sh | sh -s email=me@pashasemail.hiscom
Создай bash скрипт с авторизационными данными
Все скрипты лежат у меня в /opt/acme/
Здесь указываешь email от cloudflare аккаунта и Global API KEY.
Файл назови acme.cf.creds.sh
#!/bin/bash
export CF_Key="TOKeN-from_CloudFlaRe"
export CF_Email="your@email.org
Теперь создаём bash скрипты для получения сертификата
Для домена pasha-on-cf.com предлагается такой скрипт acme.issue.pasha-on-cf.com.sh
Напомню, что этот домен обслуживается на cloudflare.
Имя домена скрипт берёт из названия скрипта. Вложенность домена не играет роли, можно получить wildcard сертификат и для домена 3 го уровня и дальше. Однако здесь стоит уточнить, что для домена 3 го уровня нужно прописывать дополнительную CNAME запись, например,
_acme-challenge.3dlevel.pasha.com. CNAME _acme-challenge.pasha-on-cf.com.
.Получать сертификат можно у letsencrypt или zerossl или у других. Просто поменяй строчку 17. По последним тестам zerossl не выдаёт сертификаты для домена .ru
В строке 18 указано, куда класть готовые сертификаты. У меня они складываются в /opt/ssl/ и права меняются (строка 23) на того пользователя, который приходит ансиблом за этими сертификатами.
В приведённом ниже скрипте указано /etc/ssl/private/ — стандартизированное для меня расположение на всех серверах и виртуалках, куда обращаются nginx, proftpd и прочие апачи. И владелец с группой меняется на www-data из предположения, что скрипт будет работать на том же вебсервере, где и располагается сам nginx.
Почему файлы сертификата имеют названия domain.crt и domain.crt.key? — было испытано, что haproxy в таком наименовании поглощает сертификаты без каких-либо вопросов и дополнительных настроек, просто указываешь haproxy, где смотреть и он подтягивает все сертификаты, которые там есть.
#!/bin/bash
set -e
THIS=`readlink -f "${BASH_SOURCE[0]}"`
DIR=`dirname "${THIS}"`
pushd $DIR > /dev/null
TMP1="${THIS%.*}"
TMP2="${TMP1#*.}"
domain="${TMP2#*.}"
echo $domain;
date=`/bin/date +%Y%m%d.%H%M%S`
if [[ ! -f "acme.issue.$domain.done" ]]; then
. ./acme.cf.creds.sh
pushd /root/.acme.sh > /dev/null
./acme.sh --issue -d $domain -d '*.'$domain --dns dns_cf --server letsencrypt \
--key-file /etc/ssl/private/$domain.crt.key --fullchain-file /etc/ssl/private/$domain.crt --keylength 4096
# --force
# --debug
popd > /dev/null
echo $date > acme.issue.$domain.done
chown www-data. /etc/ssl/private/$domain.cr*
fi
popd > /dev/null
Для домена pasha.com предлагается такой скрипт acme.issue.pasha.com.sh
Напомню, что DNS этого домена обслуживается где-то ещё, а не на cloudflare.
И сертификат для домена pasha.com получается через «технический» домен pasha-on-cf.com.
Скрипт будет называться
acme.issue.pasha.com.sh
со следующим содержимым.Отличие от предыдущего скрипта ищи в строке 17 в параметре
--challenge-alias pasha-on-cf.com
, именно для этого в самом начале ты создавал запись CNAME.В строке 18 можешь указать длину ключа не 4096, а 2048, как вариант.
При успешном завершении скрипт создаёт флаг вида acme.issue.domain.done, который указывает, что сертификат успешно получен и не даёт скрипту исполняться повторно.
#!/bin/bash
set -e
THIS=`readlink -f "${BASH_SOURCE[0]}"`
DIR=`dirname "${THIS}"`
pushd $DIR > /dev/null
TMP1="${THIS%.*}"
TMP2="${TMP1#*.}"
domain="${TMP2#*.}"
echo $domain;
date=`/bin/date +%Y%m%d.%H%M%S`
if [[ ! -f "acme.issue.$domain.done" ]]; then
. ./acme.cf.creds.sh
pushd /root/.acme.sh > /dev/null
./acme.sh --issue -d $domain -d '*.'$domain --dns dns_cf --challenge-alias pasha-on-cf.com --server letsencrypt \
--key-file /etc/ssl/private/$domain.crt.key --fullchain-file /etc/ssl/private/$domain.crt --keylength 4096
# --force
# --debug
popd > /dev/null
echo $date > acme.issue.$domain.done
chown www-data. /etc/ssl/private/$domain.cr*
fi
popd > /dev/null
Получение сертификата
Теперь запускай один из скриптов, в названии которого ты указал свой домен, например:
acme.issue.mx.kamuzon.tech.sh, этот скрипт получит сертификаты для домена mx.kamuzon.tech и доменов *.mx.kamuzon.tech.
Если всё случилось, то последние строки должны быть такими:
[Fri Sep 20 12:53:08 UTC 2024] Cert success.
-----BEGIN CERTIFICATE-----
....
-----END CERTIFICATE-----
[Fri Sep 20 12:53:08 UTC 2024] Your cert is in: /root/.acme.sh/mx.kamuzon.tech/mx.kamuzon.tech.cer
[Fri Sep 20 12:53:08 UTC 2024] Your cert key is in: /root/.acme.sh/mx.kamuzon.tech/mx.kamuzon.tech.key
[Fri Sep 20 12:53:08 UTC 2024] The intermediate CA cert is in: /root/.acme.sh/mx.kamuzon.tech/ca.cer
[Fri Sep 20 12:53:08 UTC 2024] And the full chain certs is there: /root/.acme.sh/mx.kamuzon.tech/fullchain.cer
[Fri Sep 20 12:53:08 UTC 2024] Installing key to: /opt/ssl/mx.kamuzon.tech.crt.key
[Fri Sep 20 12:53:08 UTC 2024] Installing full chain to: /opt/ssl/mx.kamuzon.tech.crt
Если сертификат успешно получен, то можно настроить его автоматическое продление.
Обновление сертификата
В crontab -e
добавь строку
5 3 */5 * * root "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
Или в /etc/cron.d/ положи файл aсme с содержимым:
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
5 3 */5 * * root "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
Обновление сертификатов будет происходить раз в 5 суток.
Чаще на мой взгляд не имеет смысла, чтобы не создавать лишнюю нагрузку на сервера letsencypt, а то им скоро придётся апгрейдиться на процессоры AMD SUPER EPIC.
Да и своему серверу какой смысл каждый день проверять, не протух ли сертификат. С учётом того, что новый сертификат выдаётся за дней 15–20 до истекания текущего.