OSEN-НИЙ SAAALEСкидка 50% на виртуальный хостинг и VDS
до 30.11.2025 Подробнее
Выберите продукт

Apache mod_md и ACME: автоматизация SSL без и с cron

Покажу, как включить модуль mod_md в Apache и настроить автоматизацию ACME с Let’s Encrypt без внешних скриптов. Разберём рабочие конфиги, стратегию с cron как страховкой, логи, диагностику и типичные ловушки. Подходит и для продакшна, и для тестовых сред.
Apache mod_md и ACME: автоматизация SSL без и с cron

Если вы устали поддерживать внешние скрипты для выпуска и продления сертификатов, модуль Apache mod_md — ровно то, что нужно. Он встроенно реализует клиент ACME, умеет сам запрашивать и обновлять сертификаты (в том числе от Let’s Encrypt), хранит ключи и перезагружает сервер по готовности. Вопрос «а где cron?» закономерен: в большинстве случаев он не нужен вовсе — за расписание отвечает внутренний watchdog. Но есть ситуации, когда cron всё же полезен как дополнительная страховка. Разберём весь путь, от установки до продления и отладки.

Зачем mod_md, если есть certbot?

Классический подход — внешний клиент (например, certbot) плюс cron/systemd‑таймер для продления и отдельный apachectl reload. mod_md меняет модель: ACME‑клиент находится внутри Apache, поэтому:

  • не нужны отдельные скрипты для размещения challenge и выдачи сертификатов — всё делает сам mod_md;
  • не нужно описывать сертификаты в VirtualHost — модуль сам подставит их в mod_ssl;
  • перезагрузка сервера по готовности нового сертификата выполняется автоматически через MDNotifyCmd;
  • встроенный watchdog запускает проверки и продления по внутреннему расписанию, без crontab.

Коротко: с mod_md Apache сам себе «certbot», а cron чаще всего не нужен. Но оставить один небольшой cron‑джоб как страховку — хорошая практика.

Требования и подготовка

Версия Apache и модули

Рекомендуется Apache 2.4.46+ (в этих версиях mod_md уже достаточно зрелый). Должны быть включены:

  • mod_ssl — для TLS;
  • mod_md — собственно ACME‑клиент;
  • mod_watchdog — внутренний планировщик для фоновых задач.
# Debian/Ubuntu
sudo a2enmod ssl
sudo a2enmod watchdog
sudo a2enmod md
sudo systemctl reload apache2

# RHEL/CentOS/AlmaLinux/Rocky (пакет и имя службы могут отличаться)
sudo dnf install mod_md
sudo systemctl reload httpd

Проверьте загрузку модулей:

apachectl -M | grep -E "(ssl|md|watchdog)_module"

Сетевые требования

  • 80/tcp должен быть доступен снаружи для http-01 (по умолчанию именно им пользуется mod_md);
  • 443/tcp — для боевого сайта и возможных альтернативных проверок;
  • DNS‑имена должны резолвиться на ваш сервер (A/AAAA записи корректны). Если домен ещё не зарегистрирован или не делегирован, начните с шага «регистрация доменов».

Фрагмент конфига mod_md с MDCertificateAuthority и MDomain

Базовая настройка mod_md под ACME/Let’s Encrypt

Глобальные директивы

Создайте отдельный конфиг, например conf-available/md.conf (путь зависит от дистрибутива) и задайте общие параметры:

# Контакт для ACME (почта администратора)
MDContactEmail admin@example.com

# Где хранить ключи/сертификаты (по умолчанию подходит системный каталог)
# MDStoreDir /var/lib/apache2/md

# Когда начинать продление (процент от срока жизни)
MDRenewWindow 20%

# Куда обращаться за сертификатами (боевой каталог Let's Encrypt)
MDCertificateAuthority "https://acme-v02.api.letsencrypt.org/directory"

# Что делать, когда новый сертификат готов: мягко перегрузим Apache
MDNotifyCmd "/usr/sbin/apachectl graceful"

# Описываем управляемые домены (SAN) — одна строка = один Managed Domain
MDomain example.com www.example.com

Далее активируйте конфиг и перезагрузите Apache. При первом старте mod_md создаст ключи и запросит сертификаты.

Виртуальные хосты: без указания файлов сертификатов

В VirtualHost не нужно прописывать SSLCertificateFile/SSLCertificateKeyFile: mod_md сделает это за вас, когда сертификат будет готов. Достаточно корректно указать имена хостов в ServerName/ServerAlias и описать управляемые домены через MDomain (глобально или в контексте сервера).

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example
</VirtualHost>

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example
    Protocols h2 http/1.1
    # Никаких SSLCertificateFile — mod_md подставит сам
</VirtualHost>

После успешной валидации ACME и выполнения MDNotifyCmd виртуальный хост на 443 начнёт отдавать полноценный сертификат.

Как работает продление и зачем (иногда) cron

Встроенный watchdog mod_md

В Apache работает поток‑«надсмотрщик», планирующий задачи mod_md: проверку срока жизни, выпуск/продление, установку и уведомление. Он же занимается повтором попыток при ошибках сети и лимитов. В таком режиме отдельный cron для продления не нужен — это принципиальное отличие от внешних клиентов.

Cron как страховка

Тем не менее в продакшне часто добавляют один простой cron‑джоб:

  • мягкий reload по расписанию: если по какой-то причине MDNotifyCmd не сработал (например, разовая ошибка), reload раз в сутки подберёт уже подготовленный сертификат;
  • health‑check срока жизни. На проектах с оркестрацией и sidecar‑обвязками это особенно полезно; если у вас сайт на VDS, такой подход даст дополнительную устойчивость.

Пример crontab для ежедневного graceful‑перезапуска:

# Каждый день в 03:05
5 3 * * * /usr/sbin/apachectl -k graceful

Простой мониторинг истечения через локальный TLS (без внешних зависимостей):

#!/usr/bin/env bash
set -euo pipefail
warn_days=20
hosts=("example.com" "www.example.com")
for h in "${hosts[@]}"; do
  exp=$(echo | openssl s_client -connect 127.0.0.1:443 -servername "$h" 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
  exp_epoch=$(date -d "$exp" +%s)
  now=$(date +%s)
  days=$(( (exp_epoch - now) / 86400 ))
  if [ "$days" -lt "$warn_days" ]; then
    logger -t md-expiry "TLS cert for $h expires in $days days"
  fi
done

Этот скрипт можно запускать раз в день, вывод пойдёт в системный журнал. Такой «ремень и подтяжки» подходит для сред, где reload «по событию» не всегда надёжен (нестандартные обвязки, контейнерные оркестраторы и т. п.).

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Отладка: логи и диагностика

  • Включите подробный лог для mod_md на время отладки:
LogLevel md:trace2
  • Смотрите журнал службы:
journalctl -u apache2 -f    # Debian/Ubuntu
journalctl -u httpd -f      # RHEL-подобные
  • Проверьте, что модуль загружен и видит управляемые домены:
apachectl -M | grep md
  • Хранилище сертификатов (MDStoreDir) по умолчанию находится в системном каталоге, например /var/lib/apache2/md или близком по смыслу. Там вы увидите подкаталоги доменов и статусы staged/active.

TXT-запись _acme-challenge и проверка через dig в терминале

Мультидомены, SAN и wildcard

Для одного сертификата на несколько имён используйте одну директиву MDomain с перечислением всех SAN:

MDomain example.com www.example.com static.example.com

Wildcard (*.example.com) потребует dns-01. mod_md поддерживает DNS‑проверку через внешние хуки. Идея простая: вы настраиваете вызов скрипта, который умеет создавать и удалять TXT‑записи у вашего DNS‑провайдера. Общая схема:

  1. включаете DNS‑проверку в конфиге;
  2. пишете скрипт‑адаптер к API провайдера (или используете их консольную утилиту);
  3. скрипт читает переменные окружения, которые передаёт mod_md (имя домена, требуемое значение TXT, идентификатор операции), создаёт/удаляет запись и ждёт DNS‑распространения.

Пример структуры (псевдо‑скрипт, адаптируйте под свой API):

# /usr/local/bin/md-dns-hook.sh
#!/usr/bin/env bash
set -euo pipefail
# Доступны переменные окружения, которые передаёт mod_md, например:
# MDomain, MDChallenge, MDAction (setup/teardown), MDTxtValue, MDTxtDomain
case "${MDAction:-}" in
  setup)
    # создать TXT запись _acme-challenge для $MDomain со значением $MDTxtValue
    # <вызов API провайдера>
    ;;
  teardown)
    # удалить TXT запись
    ;;
  *)
    echo "Unknown action" >&2; exit 1
    ;;
esac
# опционально подождать распространения (sleep или проверка через dig)

Если wildcard не критичен, проще остаться на http-01. По теме см. также DNS-01 для wildcard: пошаговая автоматизация.

Let’s Encrypt: стадирование и лимиты

При первых экспериментах или массовой настройке лучше использовать staging‑окружение, чтобы не упереться в лимиты выпуска сертификатов. Затем переключиться на продакшн.

# Staging-директория Let's Encrypt (для тестов)
MDCertificateAuthority "https://acme-staging-v02.api.letsencrypt.org/directory"

# ... протестировали, затем переключаемся обратно на production
MDCertificateAuthority "https://acme-v02.api.letsencrypt.org/directory"

После переключения перезагрузите Apache. Для проверки используйте логи md:trace2 и просмотрите сертификат (Issuer должен меняться со staging на production). Про ограничения выпусков и группировку SAN читайте в заметке Лимиты Let’s Encrypt и стратегии объединения SAN. Если вам нужен OV/EV или специализированные типы сертификатов, рассмотрите SSL-сертификаты.

FastFox SSL
Надежные SSL-сертификаты
Мы предлагаем широкий спектр SSL-сертификатов от GlobalSign по самым низким ценам. Поможем с покупкой и установкой SSL бесплатно!

Безопасность: права и процессы

  • Ограничьте доступ к каталогу MDStoreDir (по умолчанию это уже так): приватные ключи не должны быть читаемы пользователями, кроме пользователя/группы Apache и root.
  • Не запускайте произвольные команды из MDNotifyCmd. Типовой и достаточный вариант — apachectl graceful.
  • Если используете DNS‑хуки, храните токены провайдера в отдельном защищённом файле с правами 600, под тем же пользователем, что и Apache, и не логируйте секреты.

Типичные проблемы и решения

  • Порт 80 закрыт или редиректит до проверки. Для http-01 дайте возможность отдавать challenge без 301/302/JS‑редиректов. Правила редиректа на HTTPS исключите для пути /.well-known/acme-challenge/.
  • DNS ведёт на другой сервер или IPv6 битый. Проверьте A/AAAA. Если AAAA указывает на неготовый IPv6, ACME‑проверка может падать даже при рабочем IPv4.
  • CDN или WAF мешает challenge. Временно обойдите CDN на валидацию или настройте исключение для /.well-known/acme-challenge/.
  • Apache не подхватывает новый сертификат. Убедитесь, что сработал MDNotifyCmd, или запланируйте ежедневный apachectl -k graceful в cron.
  • Права на хранилище. Если меняли MDStoreDir, убедитесь в корректных владельцах/правах. Иначе модуль не сможет записать ключи и цепочку.
  • Лимиты Let’s Encrypt. При массовой настройке используйте staging и аккуратно группируйте SAN’ы в MDomain вместо выпуска множества отдельных сертификатов.

Практические рекомендации

  • Для большинства сайтов достаточно: MDomain, MDContactEmail, MDRenewWindow, MDNotifyCmd и prod‑директория CA. Никакого cron не требуется.
  • Добавьте один ежедневный graceful через cron или systemd‑таймер как «страховку» — он безвреден и закрывает редкие углы.
  • В логе держите обычный уровень, а md:trace2 включайте точечно на отладку.
  • Если нужен wildcard, заранее подготовьте DNS‑хуки и испытайте их на staging.

Итоги

mod_md заметно упрощает жизнь админа: ACME‑автоматизация внутри Apache, прозрачная интеграция с mod_ssl, грамотное хранение ключей и нативный перезапуск по событию. В 90% случаев cron вам не нужен. В оставшихся 10% — один небольшой graceful по расписанию и чек срока жизни дают ту самую «вторую линию обороны». Настройте однажды — и забудьте о ручных продлениях: Apache сам позаботится о ваших SSL‑сертификатах. При необходимости масштабирования выберите подходящую платформу — от виртуального хостинга до гибкого VDS.

Поделиться статьей

Вам будет интересно

Nginx proxy_cache_path: разбор keys_zone, max_size, inactive и тонкая настройка OpenAI Статья написана AI (GPT 5)

Nginx proxy_cache_path: разбор keys_zone, max_size, inactive и тонкая настройка

Если вы кэшируете ответы через Nginx, директива proxy_cache_path определяет каталог на диске, глубину levels, объём keys_zone и пр ...
HAProxy HTTP Cache: практическое руководство для реверс‑прокси OpenAI Статья написана AI (GPT 5)

HAProxy HTTP Cache: практическое руководство для реверс‑прокси

Разбираем встроенный HTTP cache в HAProxy: когда он уместен, как писать правила и учитывать headers, выбирать TTL, нормализовать з ...
MTA-STS и TLSRPT: настраиваем защищённый SMTP и отчётность в Postfix OpenAI Статья написана AI (GPT 5)

MTA-STS и TLSRPT: настраиваем защищённый SMTP и отчётность в Postfix

MTA-STS и TLSRPT закрывают две болезненные точки SMTP: принудительный TLS для исходящих отправителей и прозрачность ошибок шифрова ...