Почему у почтового сервера постоянно меняется SSL‑сертификат?

На сервере MailCow я обновил сертификат, но он периодически показывает то просроченный сертификат, то обновлённый — в чём может быть причина и как это диагностировать?
  • 27 февраля 2026 г. 6:01
Ответы на вопрос 1
Короткий ответ: потому что разные конечные точки (IP/контейнеры/процессы/порт‑службы) сервера могут использовать разные файлы сертификатов или старые копии сертификата остаются в памяти/в контейнерах и не перезагружаются. Чтобы понять, почему у вас иногда показывается просроченный, а иногда — свежий — нужно диагностировать, какие именно хосты/порты/контейнеры отдают какой сертификат.

Что типично вызывает такую «переменную» картину
- В DNS у хоста есть несколько A/AAAA записей (round‑robin) и на разных IP стоят разные машины с разными сертификатами.  
- Есть и IPv4, и IPv6, и на них — разные certs (клиенты иногда выбирают IPv6).  
- Несколько MX/backup‑MX с разными сертификатами.  
- TLS терминируется на балансировщике/провайдере (или Cloudflare) и там другой cert.  
- Cert обновлён на диск, но процессы (nginx, postfix, dovecot и т. п.) или контейнеры не перезагружены — они продолжают отдавать старый cert из памяти.  
- В Docker/ Mailcow сертификат лежит в том месте, куда копируется/монтируется, и не все контейнеры читают одни и те же файлы (копии vs symlink).  
- Сценарии восстановления из бэкапа/планировщик задач периодически откатывают старые файлы.

Как диагностировать — шаги и команды
1) Узнайте, на каких IP/записях работает имя:
   - dig +short A mail.example.com
   - dig +short AAAA mail.example.com
   - dig +short MX example.com

2) Для каждого IP/порта проверьте реальный сертификат (пример для IMAPs, SMTP и HTTPS):
   - IMAPs (993): 
     openssl s_client -connect mail.example.com:993 -servername mail.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer
   - SMTP with STARTTLS (25): 
     openssl s_client -connect mail.example.com:25 -starttls smtp -servername mail.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer
   - HTTPS (443): 
     openssl s_client -connect mail.example.com:443 -servername mail.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer
   - Проверьте каждый IP явно (вместо имени подставьте IP и обязательно указывайте -servername имя), чтобы увидеть, какой cert отдаёт конкретный адрес:
     openssl s_client -connect 1.2.3.4:993 -servername mail.example.com ...

3) Если результаты разные в зависимости от IP — проблема в DNS/несинхронных серверах. Если разные в зависимости от порта — разные службы используют разные certs.

4) На хосте Mailcow — посмотрите контейнеры и где лежат сертификаты:
   - В директории с mailcow: docker-compose ps
   - Найдите контейнеры nginx, postfix, dovecot и acme (имена могут быть nginx-mailcow, postfix-mailcow, dovecot-mailcow, acme-mailcow и т. п.)
   - В каждом контейнере можно посмотреть файлы сертификата:
     docker exec -it <container> ls -l /etc/letsencrypt/live/<yourdomain> 
     docker exec -it <container> openssl x509 -in /path/to/cert.pem -noout -dates -subject
   - Посмотрите время изменения файла на хосте (где находятся данные mailcow, обычно data/assets/ssl или data/conf/letsencrypt и т.д.)

5) Проверьте логи ACME/renewal:
   - docker logs <acme‑container>  (посмотрите, успешно ли обновляется cert и когда)

6) Проверьте, перезагружаются ли сервисы после обновления:
   - Частая причина — cert обновлён на диск, но контейнер/процесс не перезагружен и продолжает отдавать старую копию.
   - В Docker проще перезапустить соответствующие контейнеры. В директории mailcow:
     docker-compose restart nginx-mailcow postfix-mailcow dovecot-mailcow rspamd
     (или просто docker-compose restart, если не уверены)
   - Можно также внутри контейнера сделать nginx -s reload, dovecot reload и т.д., но в docker‑обстановке перезапуск контейнера надёжнее.

7) Доп. проверки
   - Убедитесь, что сертификаты везде одинаковые (сравните fingerprint):
     openssl x509 -in cert.pem -noout -fingerprint
   - Проверьте, не стоит ли между клиентом и сервером TLS-терминатор (LB, CDN). Если есть, то обновлять нужно там.
   - Проверьте cron/скрипты, не откатывают ли старую копию cert по расписанию.

Что делать, когда найдете источник
- Если дело в DNS (несколько IP): синхронизировать сертификаты на всех серверов/балансировщиках; обновить записи/TTL если нужно.
- Если дело в контейнерах, которые не видят новые файлы: обеспечить, чтобы контейнеры монтировали актуальные файлы (symlink на /etc/letsencrypt/live) и/или добавить post‑renew hook, который выполняет docker‑compose restart нужных контейнеров.
- Если cert обновляется, но не перезагружается nginx/postfix/dovecot — настроить postrenew скрипт (letsencrypt hook) для автоматической перезагрузки нужных сервисов/контейнеров.
- Если обнаружите старый backup: удалить/исключить его из использования.

Если хотите, могу:
- Сформировать для вас конкретный набор команд для вашей установки (напишите домен, какие IP показывает dig и список контейнеров docker ps), или
- Подготовить пример post‑renew hook для Mailcow (docker-compose restart нужных контейнеров).
Похожие вопросы