# теория · шаг 1 из 5
ACME и certbot
Коротко
Сертификат живёт 90 дней. Продлевать руками четыре раза в год - гарантия однажды забыть, поэтому выпуск автоматизируют по протоколу ACME.
- Проверка http-01 идёт снаружи, по 80-му порту, на путь
/.well-known/acme-challenge/. - Этот путь отдают явным location.
return 301на уровнеserverсрабатывает раньше выбора location и уводит проверку в редирект - замер: 200 против 301. - Продление автоматическое, но новые файлы nginx не подхватит сам: сертификат
живёт в памяти, нужен
reloadчерез--deploy-hook. - Эксперименты гоняют с
--staging: лимит на боевом сервере расходуется быстро.
Если знаешь, почему челлендж отдают отдельным location, и помнишь про --deploy-hook - листай до «Теперь сам».
Сначала ответь сам
server {
listen 80;
server_name shop.local;
return 301 https://$host$request_uri;
location /.well-known/acme-challenge/ { root /var/www/certbot; }
}
Location для проверки написан. Отдаст ли этот блок файл челленджа?
301 https://shop.local/.well-known/acme-challenge/abc
Нет. return на уровне server выполняется на фазе перезаписиРазбирается в разделе 13, глава «return против rewrite»: Фазы: кто и когда решает -
раннем шаге обработки, до того, как выбран location. Ниже, в «Правиле», редирект
перенесён внутрь location /, и тогда тот же путь отдаётся честно - 200 вместо
301. (Два замера сняты с двух блоков стенда на разных портах, поэтому во второй
команде другой порт; на боевом порт один.)
Коварство в том, что Let's Encrypt следует за редиректами, и такая схема работает - пока жив https-сертификат. Протухнет он - и продление сломается именно здесь: редирект уводит на https, где сертификат уже недействителен.
На что это похоже
Заказное письмо с уведомлением. Почтальон приходит по адресу и должен вручить конверт лично, а не оставить записку. Если на двери висит табличка «мы переехали, все вопросы в новый офис», письмо поедет туда - и однажды выяснится, что в новом офисе не работает замок, который открывался как раз этим письмом.
Проверку домена делают ровно там, где её ждут, и не переадресуют.
Механизм: как проходит http-01
Правило
server {
listen 80;
server_name shop.local www.shop.local;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
certbot certonly --webroot -w /var/www/certbot -d shop.local -d www.shop.local
certonly - только выпустить сертификат, не трогая конфиг; --webroot -w -
каталог, из которого nginx отдаёт файлы челленджа; -d - имя (можно повторять).
Редирект живёт внутри location /, а не на уровне server. Порядок между двумя
блоками решается длиной префикса (четвёртый раздел): путь челленджа длиннее и
побеждает.
Второй способ - плагин certbot --nginx: он сам правит конфиг на время проверки
и возвращает как было. Быстрее для типового сайта, но правит твои файлы, и это
иногда сюрприз.
Разбор: почему продление «прошло», а сертификат старый
Замер из прошлой главы: файлы на диске подменили, сервер продолжает отдавать
прежний серийный номер, и только reload меняет картину. Сертификат живёт в
памяти процесса с момента загрузки конфига.
certbot renew --deploy-hook "nginx -s reload"
Пакетные установки часто кладут готовый хук в
/etc/letsencrypt/renewal-hooks/deploy/. Проверить стоит: симптом «сертификат
продлился, а браузер показывает старый и просроченный» - ровно это.
Сравнить файл и то, что реально отдаётся, - две команды:
openssl x509 -in /etc/letsencrypt/live/shop.local/fullchain.pem -noout -enddate
openssl s_client -connect shop.local:443 -servername shop.local </dev/null 2>/dev/null | openssl x509 -noout -enddate
Даты разошлись - не было перезагрузки.
Разбор: что проверять до поломки
certbot renew --dry-run
Прогоняет всю процедуру на тестовом сервере ACME, ничего не выпуская. Это единственный способ узнать, что продление сломано, до того, как оно сломается по-настоящему: закрыли 80-й порт файрволом, переписали конфиг, увели DNS на другой сервер - всё это всплывёт здесь, а не за неделю до истечения.
Таймер продления - это системный планировщик задач (управляется командой
systemctl): его ставит пакет certbot, он ходит дважды в день и обновляет
сертификат, когда до конца остаётся меньше 30 дней.
systemctl list-timers | grep certbot
Что ломается без этого
Лимиты. Let's Encrypt ограничивает число сертификатов на домен в неделю.
Пока эксперименты идут с боевым сервером ACME, лимит расходуется за десяток
попыток, и дальше приходится ждать несколько дней. Для отладки берут
--staging: сертификат оттуда браузер не примет, но всю процедуру проверки
прогонит честно.
Закрытый 80-й порт. Схема «наружу торчит только 443, http закрыт» выглядит разумно и ломает http-01 полностью: центр не сможет забрать файл. Либо открывают 80-й ровно под этот путь, либо переходят на проверку dns-01.
Зачем это в работе
Продление ломается не в день установки, а через два-три месяца, когда все уже
забыли, как настраивали. Поэтому после первого выпуска стоит сделать три вещи:
прогнать --dry-run, убедиться, что хук на месте, и завести мониторинг на срок
сертификата - тот, который смотрит на живое соединение, а не на файл.
Проверка снаружи занимает одну строку:
echo | openssl s_client -connect shop.local:443 -servername shop.local 2>/dev/null | openssl x509 -noout -enddate
Теперь сам
Сайт переехал на новый сервер, DNS переключили, старый сервер пока жив. Через два месяца certbot на новом сервере не может продлить сертификат: проверка http-01 не проходит, хотя 80-й порт открыт и location на месте. Что случилось?
Скорее всего, DNS указывает не туда, куда ты думаешь: часть записей осталась на
старый сервер, и центр сертификации забирает файл именно оттуда, а certbot
кладёт его на новый. Проверяется тем же путём, что использует центр, - запросом
из интернета: curl http://shop.local/.well-known/acme-challenge/тест с чужой
машины, а не с самого сервера.
Главное
Проверка http-01 идёт снаружи, по 80-му порту, на /.well-known/acme-challenge/,
и этот путь отдают явным location: return 301 на уровне server выполняется
раньше выбора location и уводит проверку в редирект. Продление автоматическое,
но nginx держит сертификат в памяти - нужен --deploy-hook "nginx -s reload",
иначе браузер продолжит видеть старый. Настройку проверяют certbot renew
--dry-run до поломки, а эксперименты гоняют с --staging, чтобы не выбрать
недельный лимит.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий