ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

Контроль срока действия SSL: проверки, алерты и автообновление без простоев

Слетевший SSL за ночь — не шутка: браузеры режут трафик, платежи встают. Разбираемся, как контролировать срок действия сертификатов, строить алерты и организовать автоматическое продление с нулевым даунтаймом — от cron до Prometheus.
Контроль срока действия SSL: проверки, алерты и автообновление без простоев

Зачем вообще контролировать срок действия SSL

Истекший SSL — это мгновенная потеря доверия и конверсии: браузеры показывают красные экраны, API-клиенты роняют соединения, платёжные виджеты прекращают работу. При этом проблема полностью предсказуема: у каждого сертификата есть срок действия, а даты выпуска и продления — под вашим контролем. Ключ к надёжности — инвентаризация всех имен, мониторинг срока действия, своевременные алерты и отработанные процедуры автообновления с безостановочной перезагрузкой веб- и балансирующих сервисов.

Зрелая схема выглядит так: вы заранее видите, что истекает, автоматом продлеваете в удобное окно, атомарно перегружаете процессы и проверяете факт раздачи нового сертификата. Без сюрпризов и ночных дежурств.

Быстрые проверки вручную

Когда нужно «прямо сейчас» понять, что у хоста за сертификат и когда он истекает, используйте openssl:

# Сводка по удалённому хосту (лист, issuer, subject, даты)
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -subject -issuer -dates

# Сколько секунд осталось до истечения (0 — уже истёк)
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate | awk -F= '{print $2}' | xargs -I{} date -d "{}" +%s | awk -v now=$(date +%s) '{print $1-now}'

# Проверка «истечёт ли в ближайшие 30 дней» (число секунд: 30*24*3600 = 2592000)
echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -checkend 2592000 -noout

Если инфраструктура фронтируется балансировщиком, он и определяет цепочку, которую видит клиент. Проверяйте именно внешнюю точку входа, а не внутренние бэкенды.

Инвентаризация доменов и точек входа

Главная причина внезапных истечений — забытые домены, поддомены и альтернативные имена (SAN), которые живут на отдельных виртуальных хостах, CDN, API-шлюзах или почтовых фронтах. Сделайте реестр: домен, роль, где и как выпускается сертификат, кто владелец, способ валидации (HTTP-01/DNS-01), способ деплоя и перезагрузки, где мониторится. При добавлении имен сразу оформляйте и продляйте их через регистрацию доменов.

  • Соберите список с помощью конфигураций веб-серверов, Ingress-манифестов, Terraform/Ansible и DNS-зон.
  • Убедитесь, что wildcard-домены дополняются SAN-записями для «голого» домена при необходимости.
  • Проверьте, что все внешние endpoints покрыты мониторингом (включая API и мобильные бэкенды).

Автоматизированный мониторинг срока действия

Prometheus + Blackbox Exporter

Для наблюдаемости на уровне инфраструктуры используйте blackbox-зонд TLS. Он экспортирует метрику времени до истечения цепочки. Конфигурация модуля и таргетов в blackbox:

# blackbox.yml (фрагмент)
modules:
  tls_expiry:
    prober: tcp
    tcp:
      tls: true
      tls_config:
        insecure_skip_verify: false
      preferred_ip_protocol: ip4

# prometheus.yml (jobs фрагмент)
scrape_configs:
  - job_name: ssl_expiry
    metrics_path: /probe
    params:
      module: [tls_expiry]
    static_configs:
      - targets:
        - example.com:443
        - api.example.com:443
    relabel_configs:
      - source_labels: [__address__]
        target_label: __param_target
      - source_labels: [__param_target]
        target_label: instance
      - target_label: __address__
        replacement: blackbox-exporter:9115

Правило алерта (измеряем, сколько осталось до конца цепочки):

# alerting rule (фрагмент)
- alert: SSLCertExpiresSoon
  expr: probe_ssl_last_chain_expiry_timestamp_seconds - time() < 86400 * 14
  for: 15m
  labels:
    severity: warning
  annotations:
    summary: "SSL истекает менее чем через 14 дней"
    description: "{{ $labels.instance }}: осталось {{ printf "%.0f" ((probe_ssl_last_chain_expiry_timestamp_seconds - time()) / 86400) }} дн."

- alert: SSLCertExpiresCritical
  expr: probe_ssl_last_chain_expiry_timestamp_seconds - time() < 86400 * 7
  for: 10m
  labels:
    severity: critical
  annotations:
    summary: "SSL истекает менее чем через 7 дней"
    description: "{{ $labels.instance }}: срочно продлить"

Преимущество такого подхода: вы ловите и истечение промежуточных сертификатов (chain), а не только листа, что критично при ротации корней.

Лёгкая проверка cron-скриптом

Если полноценного мониторинга нет, начните с простого bash-скрипта, который раз в день проверяет остаток дней и шлёт уведомление:

#!/usr/bin/env bash
set -euo pipefail
HOSTS=(example.com api.example.com)
THRESHOLD_DAYS=${THRESHOLD_DAYS:-30}
ALERT_EMAIL=${ALERT_EMAIL:-admin@example.com}

secs_left() {
  local host=$1
  echo | openssl s_client -servername "$host" -connect "$host":443 2>/dev/null | openssl x509 -noout -enddate | awk -F= '{print $2}' | xargs -I{} date -d "{}" +%s | awk -v now=$(date +%s) '{print $1-now}'
}

days_left() {
  local host=$1
  local s=$(secs_left "$host")
  if ; then echo -1; else echo $(( s / 86400 )); fi
}

ALERTS=()
for h in "${HOSTS[@]}"; do
  d=$(days_left "$h")
  if (( d < 0 )); then
    ALERTS+=("$h: ошибка проверки")
  elif (( d < THRESHOLD_DAYS )); then
    ALERTS+=("$h: осталось $d дн")
  fi
done

if (( ${#ALERTS[@]} > 0 )); then
  printf '%s\n' "${ALERTS[@]}" | mail -s "SSL expiry warnings" "$ALERT_EMAIL"
fi

Добавьте в crontab запуск раз в день, например в 09:00 локального времени.

Пороговые значения и эскалации

  • 30 дней — предупреждение владельцу сервиса, старт проверки автообновления.
  • 14 дней — эскалация в дежурную смену, проверка успешности автообновления на стенде.
  • 7 дней — критический алерт с подтверждением действий по продлению (ручной фолбэк).

Проверка срока действия SSL через openssl и дашборд мониторинга

Автообновление: Certbot и альтернативы

Certbot с systemd timers

В современных дистрибутивах certbot ставит таймер certbot.timer, который запускает обновление дважды в день и продлевает сертификаты при остатке срока менее 30 дней. Проверьте статус и сухой прогон. На собственном VDS вы полностью контролируете таймеры и хуки.

systemctl list-timers | grep certbot
sudo certbot renew --dry-run

Добавьте хук деплоя, который будет без простоев перегружать веб-сервер только при действительном обновлении:

# /etc/letsencrypt/cli.ini (фрагмент)
post_hook = /usr/local/bin/deploy-ssl-reload.sh
#!/usr/bin/env bash
set -euo pipefail
# deploy-ssl-reload.sh: вызывается certbot'ом, когда сертификат был обновлён
if nginx -t; then
  systemctl reload nginx
fi
# для Apache
# apachectl -t && apachectl graceful
# для HAProxy (master-worker)
# systemctl reload haproxy

Важно: используйте reload/graceful, а не restart, чтобы не ронять активные соединения. Подробный гайд по Certbot и безопасным редиректам — в статье «HTTPS, Certbot и HSTS: безопасная настройка».

acme.sh: минималистичная альтернатива

acme.sh — лёгкий клиент ACME на shell. Он удобен, когда нужна гибкость (например, DNS-01 с API провайдера). Базовый сценарий:

# установка в домашний каталог
curl https://get.acme.sh | sh
~/.acme.sh/acme.sh --issue -d example.com -d www.example.com --webroot /var/www/html
~/.acme.sh/acme.sh --install-cert -d example.com --key-file /etc/ssl/private/example.com.key --fullchain-file /etc/ssl/certs/example.com.fullchain.pem --reloadcmd "nginx -t && systemctl reload nginx"

Клиент сам создаст планировщик (cron) и будет вызывать --reloadcmd только при смене файлов сертификата.

HTTP-01 vs DNS-01 и zero-downtime

Для wildcard-нужд чаще востребован DNS-01. Следите, чтобы доступ к DNS API был ограничен и ключи не попадали в логи. Для HTTP-01 убедитесь, что /.well-known/acme-challenge не блокируется редиректами/авторизацией и отдается с фронтового хоста. Подробнее про выпуск wildcard через DNS-01 — в материале автоматизация wildcard-SSL по DNS-01. Если упираетесь в лимиты SAN/Let’s Encrypt, смотрите заметки про оптимизацию заявок и кэш — лимиты и автоматизация SAN.

Коммерческие и wildcard SSL-сертификаты помогут, когда нужен EV/OV, нестандартные алгоритмы или длительная валидация.

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

Zero-downtime перезагрузки: нюансы по софту

Nginx

  • nginx -t проверяет конфиг без перезапуска.
  • systemctl reload nginx посылает HUP: старые воркеры заканчивают сессии, новые стартуют с новым ключом и цепочкой.
  • Подтвердите, что пути к ssl_certificate и ssl_certificate_key одинаковы и читаемы пользователем Nginx; меняйте только содержимое файлов.

Apache

  • apachectl -t и apachectl graceful — безопасная перезагрузка.
  • Если используется mod_md, проверьте автопродление и события хука.

HAProxy

  • Режим master-worker позволяет делать systemctl reload haproxy без потери соединений.
  • Храните полный chain в PEM-файле фронтенда, чтобы клиенты всегда получали актуальную цепочку.

Контейнеры и оркестраторы

Docker Compose

Сертификаты монтируйте как тома только для чтения, а перезагрузку делайте командой внутри контейнера:

# пример релоуда Nginx в контейнере
docker compose exec nginx nginx -t
docker compose exec nginx nginx -s reload

Если certbot крутится в отдельном контейнере, используйте общий volume для /etc/letsencrypt и post-hook, который вызовет reload соседнего контейнера (через docker exec или сокет Docker).

Kubernetes

С cert-manager обновление секретов с сертификатами происходит автоматически. Убедитесь, что:

  • Ingress-контроллер отслеживает изменения секретов и пересобирает конфиг без рестартов.
  • На non-prod кластере заранее проверьте ротацию сертификата: клиенты должны видеть новый chain без потерь трафика.

Схема обновления сертификатов в Kubernetes с cert-manager

Проверка результата: что увидеть после релоуда

После продления проверьте, что наружу действительно отдаётся новый сертификат, а не кешированный старый:

  • openssl s_client -servername example.com -connect example.com:443 — смотрим notAfter.
  • curl -vkI https://example.com — убеждаемся, что TLS установился без ошибок, проверяем дату в выдаваемом листе.
  • Снимите с нескольких точек (например, из разных датацентров), чтобы исключить кэш CDN/edge.

OCSP, цепочки и «скрытые» причины сбоев

Падение TLS возможно даже с неистёкшим листом, если истёк промежуточный сертификат или если у клиента жёсткие требования к OCSP. Несколько практических правил:

  • Раздавайте полноценную цепочку (fullchain.pem), а не только лист.
  • Проверяйте метрику «время до истечения цепочки», а не только листа.
  • При включённом OCSP stapling после ротации сертификата делайте reload, чтобы процесс подтянул свежие ответы.

Системные хуки: reload по факту изменения файла

Помимо post-hook у клиента ACME, можно настроить systemd.path, чтобы отслеживать изменение файлов сертификата и автоматически делать безопасный reload:

# /etc/systemd/system/nginx-cert-reload.service
[Unit]
Description=Reload Nginx after certificate update

[Service]
Type=oneshot
ExecStart=/bin/sh -c 'nginx -t && systemctl reload nginx'
# /etc/systemd/system/nginx-cert-reload.path
[Unit]
Description=Watch cert changes

[Path]
PathChanged=/etc/letsencrypt/live/example.com/fullchain.pem
PathChanged=/etc/letsencrypt/live/example.com/privkey.pem

[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now nginx-cert-reload.path

Этот подход удобно масштабировать на множество доменов, создавая шаблонные юниты или используя маски на директории.

Алерты: каналы и шумоподавление

Полезные каналы: e-mail дежурным, webhook в командный чат, события в централизованный syslog/SIEM. Главное — эскалации и дедупликация, чтобы не утонуть в «шторме» однотипных сообщений.

# пример простого webhook-уведомления
WEBHOOK_URL="https://example.chat/api/hook/XYZ"
TEXT="[SSL] example.com expires in 5 days"
curl -X POST -H "Content-Type: application/json" -d "{\"text\":\"$TEXT\"}" "$WEBHOOK_URL"

Для e-mail используйте SMTP-агент, уже настроенный на хосте, и разные темы письма под warning/critical, чтобы MTA/фильтры раскладывали сообщения по нужным папкам.

Процесс и ответственность

Даже идеальная автоматизация ломается, если нет владельца. Назначьте ответственных за домены/сервисы и заведите регламент:

  • Как часто аудит доменов и тест автообновления.
  • Где хранится контакт на случай ручного продления.
  • Какой фолбэк, если ACME недоступен (например, запасной коммерческий сертификат).
  • Как оформляется Change и как проходит постфактум-проверка.

Типичные сбои и их устранение

  • «Сертификат обновился, но клиент видит старый» — забыли reload/ingress не пересобрал конфиг; проверьте хуки, права на файлы, тома в контейнере.
  • «Валидация HTTP-01 не проходит» — редирект на HTTPS с принудительной авторизацией, закрытые порты, кеш CDN; добавьте исключение для /.well-known/acme-challenge.
  • «Истёк промежуточный» — проверьте, что используете fullchain от CA, а не вручную собранную цепочку.
  • «Слетел CRON/systemd» — проверьте таймеры, логи journalctl -u certbot или логи cron, уведомляйте об ошибках.

Контроль качества: конечные проверки

Внедрите финальную проверку после каждого релоуда: синтетический тест из внешнего мониторинга, который устанавливает TLS, валидирует цепочку и сравнивает дату истечения с ожидаемым порогом. Успешный тест закрывает инцидент, неуспешный — эскалирует на дежурного.

Итоговая схема «без простоев»

  1. Инвентаризируйте все публичные имена и точки входа.
  2. Включите мониторинг срока действия (Prometheus/скрипт) по внешним endpoint.
  3. Настройте алерты с порогами 30/14/7 дней и эскалациями.
  4. Включите автообновление (certbot/acme.sh) и проверку --dry-run на стенде.
  5. Сделайте безопасные reload-хуки или systemd.path по факту смены файлов.
  6. Автоматизируйте валидацию результата и зафиксируйте процесс в регламенте.

Следуя этому плану, вы превратите риск «ночного» истечения SSL в рутинную и бесшовную процедуру, которую система делает за вас и прозрачно подсвечивает в мониторинге.

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

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

Fail2ban 2025: защита от SSH brute force и nginx basic auth, настройка bantime/ignoreip и отладка OpenAI Статья написана AI (GPT 5)

Fail2ban 2025: защита от SSH brute force и nginx basic auth, настройка bantime/ignoreip и отладка

Fail2ban в 2025 всё так же спасает от перебора паролей: читает логи, находит ошибки входа и банит IP через фаервол. В статье — нас ...
2FA для SSH и sudo на Linux: TOTP через pam_google_authenticator без лишней боли OpenAI Статья написана AI (GPT 5)

2FA для SSH и sudo на Linux: TOTP через pam_google_authenticator без лишней боли

Практический гайд по внедрению TOTP-2FA в Linux через pam_google_authenticator: установка, создание секрета, настройка PAM и OpenS ...
SLO-мониторинг с node_exporter и blackbox_exporter: latency, доступность и error budget OpenAI Статья написана AI (GPT 5)

SLO-мониторинг с node_exporter и blackbox_exporter: latency, доступность и error budget

Пошагово собираем SLO-мониторинг на Prometheus: node_exporter для диагностики хоста и blackbox_exporter для внешних проверок. Счит ...