LetsEncrypt: NIC RU DNS API
Выписывать по сертификату на каждый поддоменный адрес конечно весело, но эффективнее использовать один сертификат на все поддомены.
Сразу хотелось бы стянуть с вас розовые очки. Если вы задумали завести адрес cdn.test.mydomain.ru, то wildcard сертификат для третьего уровня не покроет остальные. Придется выписывать еще сертификат *.test.mydomain.ru. Так что, если вы такой же ленивец как я, то подумайте пару раз. Может целесообразнее завести адрес в духе cdn-test.mydomain.ru?
Склонируем проект acme.sh:
git clone https://github.com/Neilpang/acme.sh
В файл dns_nic.sh запишем следующий код (источник):
#!/usr/bin/env sh
# Author: Alexey Ashihmin
# Created 04/07/2018
# Tool for nic.ru API to finish dns-01 verifications.
dns_nic_add() {
fulldomain=$1
txtvalue=$2
export domain=$(echo $fulldomain | cut -d '.' -f 2,3)
get_token
add_txt
}
dns_nic_rm() {
fulldomain=$1
txtvalue=$2
_info "Remove TXT record"
export domain=$(echo $fulldomain | cut -d '.' -f 2,3)
get_token
rm_txt
}
#################### Private functions below ##################################
get_token() {
APIURL="https://api.nic.ru/oauth/token"
DATA="grant_type=password&username=$username&password=$password&scope=(GET%7CPUT%7CPOST%7CDELETE)%3A%2Fdns-master%2Fservices%2F$services%2Fzones%2F$domain(%2F.%2B)%3F&="
AUTH=$(echo -n "$APPNAME:$APPPASS" | base64 -w 0)
_info "Try to get a token"
export _H1="application/x-www-form-urlencoded"
export _H2="Authorization: Basic $AUTH"
token="$(_post "${DATA}" "${APIURL}" "" "POST")"
token=$(echo $token | sed -n 's|.*"access_token":"\([^"]*\)".*|\1|p')
export NIC_Token=$token
_info "Success get API token"
}
add_txt() {
export _H1="Accept: application/xml"
export _H2="Authorization: Bearer $NIC_Token"
PUTURL="https://api.nic.ru/dns-master/services/$services/zones/$domain/records"
COMMIT="https://api.nic.ru/dns-master/services/$services/zones/$domain/commit"
_xml='<?xml version="1.0" encoding="UTF-8" ?>
<request>
<rr-list>
<rr>
<name>_acme-challenge</name>
<type>TXT</type>
<txt>
<string>'"$txtvalue"'</string>
</txt>
</rr>
</rr-list>
</request>'
_info "Adding record"
response="$(_post "${_xml}" "${PUTURL}" "" "PUT")"
_info "Success added"
_info "Reload DNS zones"
reload="$(_post "" "${COMMIT}" "" "POST")"
_info "Success reloaded"
}
rm_txt() {
export _H2="Authorization: Bearer $NIC_Token"
LISTURL="https://api.nic.ru/dns-master/services/$services/zones/$domain/records?token=$NIC_Token"
COMMIT="https://api.nic.ru/dns-master/services/$services/zones/$domain/commit"
txtlist="$(_post "" "${LISTURL}" "" "GET")"
txtid=$(echo $txtlist | grep -oP '(?<=<rr id=).*?(?=</rr>)' | grep "$txtvalue"| cut -c2-9)
DELETEURL="https://api.nic.ru/dns-master/services/$services/zones/$domain/records/$txtid"
rmtxt="$(_post "" "${DELETEURL}" "" "DELETE")"
reload="$(_post "" "${COMMIT}" "" "POST")"
_info "Success removed TXT record"
}
Перемещаем "dns_nic.sh" в директорию "acme.sh/dnsapi/" и задаем права на исполнение "chmod +x acme.sh/dnsapi/dns_nic.sh". Далее запускаем установку:
mkdir -p /usr/local/letsencrypt/{conf,cert}
./acme.sh --home /usr/local/letsencrypt --config-home /usr/local/letsencrypt/conf --cert-home /usr/local/letsencrypt/cert --install
Сертификаты рекомендуется обновлять каждый месяц.
Далее надо зарегистрировать приложение на сайте nic.ru после чего будет выдан логин и токен. Теперь идем в пункт "DNS хостинг" и смотрим поле "услуга". Перед запуском необходимо экспортировать переменные окружения с нужными данными:
export APPNAME="" # логин зарегистрированного приложения
export APPPASS="" # токен
export username="" # логин от аккаунта nic.ru
export password="" # пароль от аккаунта nic.ru
export services="" # идентификатор услуги
/usr/local/letsencrypt/acme.sh --issue --dns dns_nic -d '*.mydomain.ru' --dnssleep 500 --force
Сертификаты будут сохранены в домашней директории пользователя из под которого запускался acme.sh. В моем случае в /root/.acme.sh. Далее создадим симлинки:
ln -s /root/.acme.sh/\*.mydomain.ru/fullchain.cer /usr/local/letsencrypt/
ln -s /root/.acme.sh/\*.mydomain.ru/\*.mydomain.ru.key /usr/local/letsencrypt/
В конфигурации nginx указываем местоположение сертификата и ключа:
ssl_certificate /usr/local/letsencrypt/fullchain.cer;
ssl_certificate_key /usr/local/letsencrypt/*.mydomain.ru.key;
Вешаем задачу на cron:
#m #h #dom #mon #dow #command
40 0 1 * * /usr/local/letsencrypt/acme.sh --issue -d '*.mydomain.ru' --dns dns_nic --dnssleep 500 --force > /var/log/acme.log 2>&1 && nginx -s reload
Если что-то не понятно, то более подробно можно почитать здесь.
UPD 06.01.20
Вторая часть статьи вот тут.