Если вы устали поддерживать внешние скрипты для выпуска и продления сертификатов, модуль 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_mdApache сам себе «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 под 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 «по событию» не всегда надёжен (нестандартные обвязки, контейнерные оркестраторы и т. п.).
Отладка: логи и диагностика
- Включите подробный лог для
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.

Мультидомены, SAN и wildcard
Для одного сертификата на несколько имён используйте одну директиву MDomain с перечислением всех SAN:
MDomain example.com www.example.com static.example.com
Wildcard (*.example.com) потребует dns-01. mod_md поддерживает DNS‑проверку через внешние хуки. Идея простая: вы настраиваете вызов скрипта, который умеет создавать и удалять TXT‑записи у вашего DNS‑провайдера. Общая схема:
- включаете DNS‑проверку в конфиге;
- пишете скрипт‑адаптер к API провайдера (или используете их консольную утилиту);
- скрипт читает переменные окружения, которые передаёт
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-сертификаты.
Безопасность: права и процессы
- Ограничьте доступ к каталогу
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.


