Что такое ACME и DV-сертификат - механика на пальцах
ACME (Automatic Certificate Management Environment, RFC 8555) - это протокол диалога между твоим сервером и центром сертификации (CA), например Let's Encrypt. Никакого живого человека: всё машинно. Сертификат, который ты получаешь - DV (Domain Validation), то есть CA подтверждает только одно: ты реально управляешь доменом. Не компанией, не юрлицом - именно доменом. Для веб-сайта этого достаточно, браузер рисует тот же замок, что и для дорогого OV/EV.
Как CA убеждается, что домен твой? Он даёт тебе задачу - challenge - которую может выполнить только владелец домена. Три основных типа:
- HTTP-01 - CA говорит "положи файл с таким-то содержимым по адресу http://твойдомен/.well-known/acme-challenge/ТОКЕН и я его скачаю". Если файл на месте - значит, ты управляешь веб-сервером на 80 порту этого домена. Самый простой, но требует доступности по HTTP на 80 порту и НЕ умеет wildcard.
- DNS-01 - CA говорит "создай TXT-запись _acme-challenge.твойдомен со значением X". Проверяется через DNS. Единственный способ получить wildcard (*.example.com), работает даже для серверов без публичного доступа, но требует API к твоему DNS-провайдеру.
- TLS-ALPN-01 - валидация прямо в TLS-хендшейке на 443, нишевый вариант.

nginx certbot: три способа получить бесплатный сертификат
В ванильном nginx своего ACME-клиента в ядре НЕТ. Стандартный инструмент - certbot. У него три рабочих режима, и выбор между ними определяет всю эксплуатацию.
Режим 1: плагин --nginx (магия "сделай всё за меня"). Certbot сам читает твой nginx.conf, временно правит его под HTTP-01, выпускает сертификат и вписывает ssl_certificate в конфиг:
Код: Выделить всё
certbot --nginx -d example.com -d www.example.com
Режим 2: webroot (контроль в твоих руках). Certbot только кладёт challenge-файл в каталог, который ты сам отдаёшь по HTTP, и не трогает конфиг вообще:
Код: Выделить всё
certbot certonly --webroot -w /var/www/acme -d example.com -d www.example.com
Код: Выделить всё
location ^~ /.well-known/acme-challenge/ {
root /var/www/acme;
default_type "text/plain";
allow all;
access_log off;
}
Режим 3: DNS-01 для wildcard. Если нужен nginx wildcard сертификат (*.example.com - один сертификат на все поддомены), HTTP-01 не подойдёт в принципе, только DNS-01:
Код: Выделить всё
certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /etc/letsencrypt/cf.ini \
-d example.com -d "*.example.com"
Альтернатива certbot - acme.sh, чистый shell-скрипт без зависимостей от Python, с поддержкой десятков DNS-провайдеров из коробки. Логика та же, многие предпочитают его на минималистичных серверах за лёгкость и отсутствие питоновского окружения.
Автопродление и reload: чтобы nginx ssl автоматически не протух
Выпустить сертификат - половина дела. Вторая половина - продлевать его без участия человека и подхватывать новый файл. Современный пакет certbot ставит systemd-таймер, который дважды в день дёргает renew:
Код: Выделить всё
systemctl list-timers | grep certbot
certbot renew --dry-run
Код: Выделить всё
certbot renew --deploy-hook "nginx -s reload"
Код: Выделить всё
17 3 * * * certbot renew --quiet --deploy-hook "nginx -s reload"
Про цепочку сертификатов. CA выдаёт не один файл, а лист (твой сертификат) + промежуточные (intermediate) сертификаты CA. Браузеру нужна вся цепочка до доверенного корня, иначе часть клиентов (особенно старый Android и боты) получит ошибку доверия. Certbot складывает готовую цепочку в fullchain.pem - в ssl_certificate указывай ИМЕННО его, не cert.pem:
Код: Выделить всё
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
angie acme: нативный ACME прямо в конфиге - киллер-фича 2026
А теперь главное отличие 2026 года. Angie (форк nginx от части бывшей команды разработки) принёс то, чего нет в ядре nginx: нативный ACME-клиент прямо в конфигурации, бесплатно и без внешних инструментов. Никакого certbot, никаких systemd-таймеров, никаких deploy-hook. Объявляешь acme_client в http-блоке - и Angie сам выпускает, продлевает и подгружает сертификат БЕЗ reload. Сертификаты ECDSA из коробки. Конфиг буквально такой:
Код: Выделить всё
http {
resolver 1.1.1.1 8.8.8.8 valid=300s;
acme_client le https://acme-v02.api.letsencrypt.org/directory;
server {
listen 443 ssl;
server_name example.com www.example.com;
acme le;
ssl_certificate $acme_cert_le;
ssl_certificate_key $acme_cert_key_le;
location / {
root /var/www/html;
}
}
}
Это серьёзно меняет эксплуатацию: один файл конфига вместо связки nginx + certbot + cron + hooks. Для нового продакшена в 2026 это сильный аргумент в пользу Angie. Оговорка: встроенный модуль Angie работает по HTTP-01, поэтому wildcard через него не выпустить - для *.example.com по-прежнему нужен DNS-01 через внешний acme.sh/certbot или DNS-провайдера, и сертификат подаётся обычным ssl_certificate.
А что в ванильном nginx - ACME через модуль, но не в ядре
Чтобы не было путаницы: в самом nginx нативного ACME в ядре НЕТ - не ищи core-директиву acme в ванильном nginx, её там не существует. Но в 2025-2026 появились ОФИЦИАЛЬНЫЕ модули от команды nginx, которые добавляют ACME через подключаемый модуль:
- nginx-acme (модуль ngx_http_acme_module) - новый модуль на Rust SDK, ставится пакетом nginx-module-acme, доступен и для OSS, и для Plus с версии 1.29.0. На момент 2026 он в статусе preview и поддерживает только HTTP-01 (DNS-01 и wildcard - в планах, но ещё нет).
- njs-acme - реализация на njs (JavaScript-движке nginx) поверх ngx_http_js_module, библиотека работает с Let's Encrypt без reload.
Типичные грабли
- Rate limits Let's Encrypt. Это боль номер один. Лимит - 50 сертификатов на зарегистрированный домен за 7 дней и (важнее при отладке) всего 5 дубликатов одного и того же набора имён за неделю. Перевыпустил конфиг пять раз подряд в проде - и ты в бане на неделю с реальным доменом. Поэтому отлаживай ТОЛЬКО против staging LE (--test-cert или --dry-run): там лимиты огромные, а сертификат невалидный, но процесс полностью идентичен.
- Редирект перехватывает .well-known. Общий return 301 на HTTPS или фильтры из app_redirects_security ловят /.well-known/acme-challenge раньше нужного location. CA получает редирект вместо токена и валидация падает. Лечение - location ^~ /.well-known/acme-challenge/ выше всех редиректов, без редиректа на HTTPS.
- Забыл reload после продления. Файл на диске обновился, а nginx держит в памяти старый - и за день до истечения отдаёт протухший сертификат. Всегда deploy-hook "nginx -s reload". У Angie этой грабли нет - он перечитывает сам.
- Подставил cert.pem вместо fullchain.pem. Неполная цепочка, часть клиентов получает ошибку доверия. Только fullchain.pem.
- 80 порт закрыт фаерволом/CDN. HTTP-01 требует, чтобы CA достучался до твоего сервера по 80. За проксирующим CDN или с закрытым 80 - переходи на DNS-01.
- OCSP stapling устарел. Не тащи вслепую ssl_stapling из старых гайдов: Let's Encrypt убрал OCSP-URL в мае 2025, для LE стэплинг фактически мёртв, это legacy.
Повтори руками по шагам.
Часть A - nginx + certbot webroot:
- Создай каталог: mkdir -p /var/www/acme
- Добавь в server-блок location ^~ /.well-known/acme-challenge/ с root /var/www/acme (см. выше), выше любых редиректов. Проверь nginx -t и nginx -s reload.
- Выпусти против staging: certbot certonly --webroot -w /var/www/acme -d твойдомен --test-cert
- Убедись, что прошло, потом убери --test-cert и выпусти боевой.
- Пропиши fullchain.pem/privkey.pem в ssl_certificate, reload.
- Настрой автопродление: certbot renew --dry-run, затем deploy-hook с nginx -s reload.
- Поставь Angie, добавь в http-блок resolver и acme_client le с URL директории LE.
- В server-блоке добавь acme le и ssl_certificate $acme_cert_le; ssl_certificate_key $acme_cert_key_le;
- angie -t, перезапусти, посмотри в error_log как клиент проходит challenge и выписывает сертификат.
- Сравни ощущения: в Angie ты не настраивал ни location под challenge, ни cron, ни reload.
- Почему wildcard-сертификат *.example.com нельзя получить через HTTP-01 и какой challenge нужен?
- Зачем в ssl_certificate указывают fullchain.pem, а не cert.pem? Что сломается при ошибке?
- Чем нативный ACME в Angie (acme_client) принципиально отличается от связки nginx + certbot по эксплуатации?
- Что такое rate limit "5 дубликатов в неделю" у Let's Encrypt и как не попасть в бан при отладке?
ACME превратил выпуск TLS в фоновую автоматику. Для ванильного nginx рабочая лошадка - certbot (webroot для контроля, DNS-01 для wildcard) или acme.sh, с обязательным автопродлением и reload-хуком. Нативного ACME в ядре nginx нет - только подключаемые модули nginx-acme (Rust) и njs-acme. А вот Angie в 2026 даёт нативный acme_client прямо в конфиге без certbot и без reload - это его реальная киллер-фича. Главные грабли - rate limits (отлаживай на staging), перехват .well-known редиректом и неполная цепочка. Освоишь это - и красный замок в понедельник утром останется в прошлом.