NGINX теперь умеет выпускать сертификаты SSL сам: прощай, Certbot?

С 12 августа 2025 года в pre-release версии NGINX Open Source с поддержкой Rust-модулей появился официальный модуль ngx_http_acme_module. Это полноценная интеграция с ACME-протоколом от самой команды NGINX, без внешних скриптов. Он работает с Let’s Encrypt и позволяет запрашивать и обновлять сертификаты прямо из конфига сервера.

Интересно, что новость прошла без лишнего шума. Но в технических кругах — особенно среди DevOps-инженеров и тех, кто держит в проде десятки инстансов — это вызвало отклик. На Hacker News обсуждают перспективы, кто-то уже радуется, что можно будет «наконец-то забыть про certbot renew», кто-то выражает скепсис: «ждём поддержку DNS‑01, вот тогда поговорим».

В этой статье разбираемся, как это всё работает, чем отличается от прежней схемы, и почему я лично считаю это одним из самых приятных изменений в мире серверной рутины за последнее время.

Как мы раньше делали HTTPS

Если вы работали с Certbot — вы и так знаете, как это выглядело. Установить клиент, прописать зависимости, пробросить challenge, договориться с фаерволлом, убедиться, что всё сработает не только в тесте, но и через три месяца, когда сертификат надо будет обновить.

Я сам не раз думал, что весь этот процесс слишком муторный для такой рутинной задачи. Особенно когда речь шла о куче поддоменов или нестандартной инфраструктуре. Certbot, конечно, работал. Он делал своё дело. Но всегда оставалось чувство, что мы просто оборачиваем одну простую операцию в лишний слой автоматизации, который живёт своей жизнью.

И вот теперь мы получили то, чего давно не хватало: возможность делать всё это средствами самого NGINX. Без промежуточных сущностей. Без шансов забыть, где лежит ключ и почему вдруг не сработал перевыпуск сертификата.

Как это выглядит сейчач

Вот базовая конфигурация, которая включает ACME прямо в NGINX:

acme_issuer let's_encrypt {
    directory https://acme-v02.api.letsencrypt.org/directory;
    account_key /etc/nginx/acme/account.key;
    contact "mailto:admin@example.com";
}

acme_shared_zone acme_zone 64k;

server {
    listen 80;
    server_name example.com;

    acme_challenge_location /.well-known/acme-challenge;
}

server {
    listen 443 ssl;
    server_name example.com;

    acme_certificate /etc/nginx/acme/example.com.crt {
        private_key /etc/nginx/acme/example.com.key;
        issuer let's_encrypt;
        domains example.com;
        renew_window 14d;
    }

    ssl_certificate     $acme_certificate;
    ssl_certificate_key $acme_certificate_key;

    location / {
        return 200 "Hello, secure world!";
    }
}

Вся магия теперь прямо перед глазами. Больше не нужно вызывать сторонний скрипт, дергать вручную certonly, настраивать cron или systemd timer. Всё работает внутри самого сервера. Один конфиг. Один процесс. Один источник истины.

Мне лично нравится, что теперь всё предсказуемо. Ты видишь, где создаётся ключ, как он применяется, и не нужно потом полчаса искать, почему сертификат лежит в /etc/letsencrypt/live, а в конфиге указан другой путь.

Что здесь происходит: разбор по частям

acme_issuer

acme_issuer let's_encrypt {
    directory https://acme-v02.api.letsencrypt.org/directory;
    account_key /etc/nginx/acme/account.key;
    contact "mailto:admin@example.com";
}

Это определение “кто” будет выдавать сертификаты.
Мы явно указываем Let’s Encrypt и создаём аккаунтный ключ, с которым будем себя идентифицировать.
Ключ генерируем один раз — например, так:

openssl genrsa -out /etc/nginx/acme/account.key 4096

Email здесь не обязателен, но я всегда указываю — на него, как минимум, могут прилетать предупреждения о просрочке сертификатов. А это бывает.

acme_shared_zone

acme_shared_zone acme_zone 64k;

Это shared memory для обмена данными между воркерами NGINX. Не трогай — просто нужно. Работает как внутренняя зона обмена данными. Без неё ничего не будет происходить.

Первый server — для challenge

server {
    listen 80;
    server_name example.com;

    acme_challenge_location /.well-known/acme-challenge;
}

ACME должен как-то проверить, что ты владеешь доменом. И делает это через так называемый HTTP-01 challenge.
Этот сервер обрабатывает именно этот момент. Достаточно открыть порт 80, указать acme_challenge_location, и всё работает.

Лично я обычно не закрываю этот порт даже после получения сертификата — пусть будет, на случай renew.

Второй server — основной, с HTTPS

acme_certificate /etc/nginx/acme/example.com.crt {
    private_key /etc/nginx/acme/example.com.key;
    issuer let's_encrypt;
    domains example.com;
    renew_window 14d;
}

Вот тут создаётся и управляется сам сертификат. Указываем путь до ключа и сертификата, привязываем к issuer, и задаём, когда начинать обновление (renew_window).
На практике — если осталось меньше 14 дней до истечения, начинается обновление. Всё автоматом.

Потом просто подключаем сертификаты как обычно:

ssl_certificate     $acme_certificate;
ssl_certificate_key $acme_certificate_key;

Всё. Сервер готов.

Что нужно установить?

Если вы используете NGINX Plus, модуль уже доступен. Для Open Source NGINX — модуль пока доступен в виде Rust‑модуля, и его нужно собирать вручную. Немного сложнее, но вполне реально.

⚠️ Убедитесь, что вы используете NGINX с поддержкой динамических модулей, иначе не сможете подключить ngx_http_acme_module.

Подводные камни

  • Убедитесь, что на сервере установлен openssl >= 1.1 и есть доступ к Let’s Encrypt.
  • Работает только с HTTP‑01 challenge — никаких wildcard или DNS‑01 пока нет.
  • Не забудьте открыть порт 80 для внешнего мира.

Сертификаты и ключи нужно хранить в доступных для NGINX местах. Права доступа — критичны.

Обновление и деплой: что поменялось?

Самое приятное — больше не нужно думать о перевыпуске сертификата. Если всё настроено правильно, NGINX сам отслеживает срок действия сертификатов и начинает обновление за 14 дней до истечения. Без cron-джобов. Без systemd‑таймеров. Без “certbot renew —dry-run”.

Ты просто конфигурируешь один раз — и забываешь. На продакшене это особенно ценно. Меньше точек отказа. Меньше зависимости от сторонних скриптов, которые иногда ломаются после обновлений системы. Всё в одном процессе.

Когда ты деплоишь десятки инстансов — минимизация внешних зависимостей начинает звучать совсем по-другому. Особенно если раньше тебе приходилось через Ansible или Terraform прогонять шаблоны certbot, раскладывать ключи и добавлять костыли под специфические кейсы. Теперь всё это можно выбросить. Конфиг — это и есть deploy.

Мнение

Я считаю, что это один из самых зрелых шагов, которые NGINX сделал за последние годы. То, что должно было быть с самого начала.

Мне не хочется больше управлять certbot. Не потому что он плох, а потому что в современном стекe всё должно быть предсказуемым и атомарным. Особенно такие базовые настройки, как запуск проекта по HTTPS.

То, что теперь можно прописать всё прямо в конфиге и быть уверенным в результате — это дорогого стоит. Особенно если ты любишь, когда конфигурация — это одновременно и документация.

Больше полезной информации

Update cookies preferences
WhatsApp Получить консультацию