Comments 38
Теперь нужно просто поменять CA в конфиге на боевое значание и запустить скрипт ещё раз, добавив параметр --force.
Без этого параметра скрипт не станет заново генерировать сертификат, т.к. ещё не подошел срок устаревания, указанный в конфиге.
Столкнулся с этим недавно. Использовал
letsencrypt-auto renew
без --force-renewal
. В итоге сертификаты не обновились. Попробовал вручную — не обновляет, skipped… Несмотря на то, что срок истёк уж как 3 дня. С --force-renewal
обновилось. + потребовалось перегрузить nginx руками. Это похоже на годный гайд. Спасибо! Буду пробовать.
Лично мне как-то боязно на своих серверах крутить чей то черный ящик к коду которого доступа не предоставляется.
А с LE целое дело подтверждать сайт недоступный из интернета и даже для публичных до сих пор не сделали официальную поддержку nginx.
Странно, что производители железок не спешат добавлять ACME-клиент — даже в ASA сейчас кнопка для какого-то платного CA, хотя сама Cisco спонсирует LE.
https://github.com/EasyEngine/easyengine/issues/699
так что если не завелось вдруг, то проверьте, прописан ли WWW поддомен.
Насколько я понял, по ссылке issue насчет другого ПО (EasyEngine), которое автоматом создает сертификат на два домена: domain.com и www.domain.com.
И эта операция падает с ошибкой, если домена www.domain.com нет в dns.
Сам letsencrypt вполне может подписать сертификат на два домена, domain.com и www.domain.com, просто он проверит каждый домен на доступность.
А если какого-то домена нет, то он не сможет его проверить и откажет в подписи сертификата.
Мне кажется, это вполне логично.
Если откажет, то он сообщит, что не может найти WWW поддомен?
Не совсем понял вопрос, если честно.
Если запустить клиент letsencrypt для домена domain.com, он его проверит и сделает сертификат только для одного этого домена: domain.com. Он не будет проверять домен www.domain.com.
Если нужен сертификат для двух доменов, domain.com и www.domain.com, нужно это явно указать в запросе. Letsencrypt последовательно проверит оба эти домена. И если с ними все ок, сделает один сертификат для них. А если с одним из доменов что-то не так, как я понял, он просто не делает сертифкат.
Можно сделать два отдельных сертифтата: один для domain.com и один для www.domain.com
Мне кажется, что проблема в EasyEngine — там рассчитывают на то, что большинство удостоверяющих центров делают один сертификат на два домена — domain.com и www.domain.com.
Причем, вписывают два домена, даже не проверяя, а есть ли домен www.domain.com.
А letsencrypt так не делает — он проверяет каждый домен или поддомен.
UPD
Кажется, я понял ваш вопрос.
Для генерации сертификата нужно доказать, что вы управляете сайтом. Для этого нужно или положить файл (который запросит сервер letsencrypt), или сделать запись в DNS. Если в DNS нет домена www.domain.com, то и проверить сайт нельзя. В DNS его нет, а сайт по адресу www.domain.com уж тем более будет недоступен :)
Достаточно геморно автоматизировать всё это дело, каждый раз у nginx надо конфиг править.
у меня а-ля так:
Скрытый текст#!/bin/bash
tmp=«add_header public-key-pins '»
for D in "/etc/letsencrypt/live/"*
do
cx509=`openssl x509 -pubkey -noout -in $D/cert.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64`
echo -e `basename $D`"\t: "$cx509" ("`openssl x509 -startdate -noout -in $D/cert.pem`")"
tmp+='pin-sha256="'$cx509'"; '
done
for D in "/root/git/letsencrypt/"*.pem
do
cx509=`openssl x509 -pubkey -noout -in $D | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64`
echo -e `basename $D`"\t: "$cx509" ("`openssl x509 -enddate -noout -in $D`")"
tmp+='pin-sha256="'$cx509'"; '
done
tmp+='pin-sha256=«Vjs8r4z+80wjNcr1YKepWQboSIRi63WsWXhIMN+eWys=»;'
tmp+=«max-age=604800; includeSubDomains;';»
echo Write nginx pins.conf
echo $tmp > /etc/nginx/snippets/pins.conf
Хотя не понимаю почему обновлять ключи «правильно».
Достаточно делать reload
«При получении сигнала USR1 или graceful, родительский процесс призывает дочерние процессы к завершению работы сразу же после обработки своего текущего запроса (или к незамедлительной остановке, если дочерний процесс ничего не обрабатывает). Родительский процесс перечитывает конфигурационные файлы, открывает заново log-файлы (файлы, содержащие журнал работы сервера). После того, как какой-то из дочерних процессов завершает работу, родительский процесс заменяет его дочерним процессом нового поколения, т.е. с новой конфигурацией, который начинает обрабатывать новые запросы незамедлительно.»
/etc/init.d/httpd graceful
/etc/init.d/apache2 reload
apachectl -k graceful
Скажу банальщину, но я бы рекомендовал апач прятать за nginx.
Лично у меня так и крутится — апач слушает на 127.0.0.1:80, а nginx на внешний_ip:80,443.
Они друг другу не мешают. А за счет того, что апач тоже работает на 80 порту, нет глюков с редиректами.
Если апач вешать на 8080, иногда кодом или самим апачом генерируются редиректы на порт 8080.
Хоть автообновление в крон добавляй.
Хотя клиентов конечно море ( https://letsencrypt.org/docs/client-options/ ).
В общем, используя webroot плагин, обновление сертификатов (котрые истекают не ранее чем, через 30 дней) получается в одну строчку в кроне:
#certbot renew
если неохота использовать свой сервер nginx для подтверждения домена (обновления сертификата), можно запускать так:
#certbot renew --standalone --pre-hook "service nginx stop" --post-hook "service nginx start"
В этом случае сервер nginx останавливается, запускается standalne, нас проверяют, выдают сертификат, обратно включается nginx.
1. Теперь скрипт переименован, называется dehydrated и его репозитарий https://github.com/lukas2511/dehydrated, а статус на странице https://travis-ci.org/lukas2511/dehydrated
2. В dehydrated изменено умолчание для каталога, куда он помещает проверочные файлы, теперь это /var/www/dehydrated
3. Стоило указать используемый дистрибутив Linux и уточнить, что скрипту нужен (системный или специальный) конфиг openssl.cnf. В dehydrated по умолчанию конфиг формируется из переменной openssl «openssl directory», и это может оказаться неудачным вариантом.
4. Если уж использовать отдельного пользователя, нужно закрыть ему возможность модифицировать собственный скрипт и конфиг.
В итоге установку скрипта я сделал так:
git clone https://github.com/lukas2511/dehydrated /opt/dehydrated/
cp /opt/dehydrated/docs/examples/config /opt/dehydrated/config
echo "KEY_ALGO=secp384r1" >> /opt/dehydrated/config
echo "LOCKFILE=/tmp/dehydrated.lock" >> /opt/dehydrated/config
echo "OPENSSL_CNF=/etc/openssl/openssl.cnf" >> /opt/dehydrated/config
adduser --system --home /var/www/dehydrated -s /sbin/nologin _dehydrated
usermod -a -G _dehydrated _nginx
install -m 750 -o _dehydrated -g _dehydrated -d /opt/dehydrated/certs /opt/dehydrated/accounts /var/www/dehydrated
echo '#!/bin/sh
su dehydrated -c "/opt/dehydrated/dehydrated -c"
if ! ( cmp -s /etc/nginx/nginx/ssl/fullchain.pem /opt/dehydrated/certs/example.org/fullchain.pem \
&& cmp -s /etc/nginx/nginx/ssl/privkey.pem /opt/dehydrated/certs/example.org/privkey.pem ); then
install -o root -g _nginx -m 640 /opt/dehydrated/certs/example.org/fullchain.pem /opt/dehydrated/certs/example.org/privkey.pem /etc/nginx/nginx/ssl/
service nginx reload
fi
' >/etc/cron.monthly/dehydrated
chmod 744 /etc/cron.monthly/dehydrated
Остаётся задать контактный email и домены, например, тем же сопособом, как у вас:
echo CONTACT_EMAIL="example@example.org" >> /opt/dehydrated/config
echo "example.org" >> /opt/dehydrated/domains.txt
«4. Если уж использовать отдельного пользователя, нужно закрыть ему возможность модифицировать собственный скрипт и конфиг.» — пользователь _dehydrated может писать только в четыре каталога, это /tmp (туда может писать кто угодно, но чужие файлы как правило недоступны) и перечисленное в команде:
install -m 750 -o _dehydrated -g _dehydrated -d /opt/dehydrated/certs /opt/dehydrated/accounts /var/www/dehydrated
«3. Стоило указать используемый дистрибутив Linux и уточнить, что скрипту нужен (системный или специальный) конфиг openssl.cnf. В dehydrated по умолчанию конфиг формируется из переменной openssl «openssl directory», и это может оказаться неудачным вариантом.»
В разных дистрибутивах GNU/Linux разное содержимое того файла конфигурации openssl, который использует бибилиотека openssl.so при отсутствии прямого указания на конфиг. Не для всех случаев значения из этого файла подходят для dehydrated.
Что-то ещё непонятно?
Пример простой автоматизации letsencrypt