Бэкап и восстановление почты: Maildir, конфиги и БД без потери писем
Бэкап почтового сервера имеет ценность ровно до момента, когда вы докажете восстановление конкретного ящика на конкретную дату. Разбираем три независимых слоя бэкапа, почему rsync по живому Maildir врёт, строгий порядок restore и ежемесячный drill, который единственный говорит правду о вашей защите.
EvilMail Team27 июля 2026 г.13 мин чтения
Что именно мы восстанавливаем и за какое время
Разговор про бэкап почты почти всегда начинается не с той стороны. Спрашивают «каким инструментом бэкапить», а правильный первый вопрос — «сможем ли мы поднять ящик [email protected] в том состоянии, в котором он был 3 марта в 09:00, за два часа, не задев остальные 4000 ящиков». Если на это нет уверенного ответа с командой наготове, бэкапа у вас нет. Есть папка, которая создаёт ощущение защищённости.
Разведём данные по классам — у них разная цена потери и разный ритм изменения:
Данные ящиков (Maildir). Меняются постоянно, письма приходят каждую секунду. Потеря последних часов почты неприятна, но переживаема. Целевой RPO — 24 часа, реально стремимся к 1–4 часам за счёт инкрементов.
Конфиги и секреты. Меняются редко, иногда раз в месяц. Но без них сервер не поднимется вообще: приватный DKIM-ключ, dovecot.conf, карты Postfix, TLS-сертификаты. Их потеря — это не «откатились на день», это «домен в спаме и клиенты не логинятся».
Бэкап и восстановление Maildir, конфигов и БД почтового сервера — EvilMail Blog
Базы данных.mailserver (виртуальные домены и пользователи), powerdns (зоны), БД приложения. Единая точка отказа: без virtual_users Dovecot не знает, какие ящики вообще существуют.
Отсюда целевые числа, которые стоит зафиксировать письменно и защищать: RPO 24 часа для почты, RTO 2 часа на восстановление одного ящика и 8 часов на полный сервер. Для temp-email доменов (в нашем случае evilmail.pro и evilmail.cloud, domain ID 53 и 54 в mailserver) политика отдельная — там короткий retention осмыслен, письма живут минутами и хранить их месяцами бессмысленно. Не тащите одноразовые ящики в ту же схему, что и боевую переписку клиентов.
Три слоя бэкапа и почему их нельзя мешать
Ключевая ошибка — снять всё одним tar или одним заданием restic по /. Каждый слой требует своего инструмента и своего ритма, а вот восстанавливаются они в строго обратном порядке. Поднимете Maildir раньше, чем БД и конфиг, — Dovecot при первом обращении создаст пустые ящики поверх ваших данных и перезапишет индексы.
Держите это правило как аксиому: слои бэкапятся независимо, но при восстановлении сначала поднимается инфраструктура (конфиг, БД), и только потом на неё «наливаются» данные ящиков.
Maildir на горячую — почему rsync врёт
Это тот раздел, из-за которого статья вообще написана. Самый частый и самый дорогой провал — rsync -a /var/mail/vhosts/ backup:/vault/ по крону в три ночи, потому что «в три ночи никто не пишет». Пишут. И даже если бы не писали, проблема не в объёме трафика, а в консистентности.
Внутри каждого ящика Dovecot держит служебные файлы: dovecot.index, dovecot.index.log, dovecot.uidlist и dovecot-uidvalidity. В uidlist лежит соответствие «имя файла в cur/ → UID письма». Флаги закодированы прямо в имени файла (:2,S — прочитано, :2,RS — отвечено и прочитано). Пока rsync минуту ползёт по ящику, приходит новое письмо, MDA дописывает его в new/, обновляет dovecot.index.log и uidlist. rsync снимает эти файлы в разные моменты времени — и вы получаете набор, которого никогда не существовало как единое состояние.
При восстановлении такого снимка возможны два исхода, оба плохие. Либо клиент видит рассинхрон uidlist и файлов и передёргивает весь ящик заново (десятки гигабайт по IMAP), либо, если не совпал dovecot-uidvalidity, вообще считает ящик новым и перекачивает всё с нуля, теряя локальные флаги прочитанного. Для клиента с 60 000 писем это часы простоя и гнев.
Правильных путей два, и оба сводятся к «сначала зафиксируй состояние, потом копируй».
Путь А — снапшот файловой системы. Атомарно замораживаем момент на уровне ФС, монтируем снапшот только для чтения и копируем уже с него. Ящики продолжают жить, а мы работаем с застывшей копией.
Обратите внимание на --numeric-ids. Без него rsync мапит владельца по именам, а на backup-хосте пользователя vmail с UID 5000 может не быть — и права слетят на восстановлении. Работаем с числовыми ID, потому что 5000:5000 должно остаться 5000:5000 где угодно.
Путь Б — `doveadm backup`. Dovecot умеет копировать почту с пониманием её семантики: переносит UID, флаги и структуру папок корректно, потому что читает не файлы, а mailbox через свой storage-слой. Для гранулярного восстановления одного ящика это надёжнее снапшота.
bash
# бэкап одного ящика в отдельный maildir (сохраняет UID и флаги)
doveadm backup -u [email protected] maildir:/backup/ivan
# бэкап всех пользователей циклом
doveadm user '*' | while read u; do
doveadm backup -u "$u" "maildir:/backup/${u}"
done
Флаг -R здесь ставить нельзя. Он разворачивает направление — тянет почту ИЗ /backup в живой ящик, то есть это уже restore, и командой бэкапа вы затрёте рабочую почту. При копировании на бэкап направление всегда прямое, без -R.
И отдельно про инкременты: никогда не ставьте `--delete` на зеркалирующий rsync как единственную копию. Ransomware или ошибочный rm на проде мгновенно распространится на бэкап. Держите поколения — за это отвечает off-site слой.
Дампы БД и секреты, которые нельзя потерять вместе с сервером
БД mailserver — это то, без чего Maildir на диске превращается в набор бесхозных папок. Postfix и Dovecot спрашивают у неё, какие домены обслуживать и у каких пользователей какие пароли. Снимаем в custom-формате — он позволяет восстанавливать выборочно.
bash
# полный дамп с виртуальными доменами и пользователями
pg_dump -Fc -U mailuser mailserver > mailserver_$(date +%F).dump
pg_dump -Fc -U powerdns powerdns > powerdns_$(date +%F).dump
pg_dump -Fc maildb > app_$(date +%F).dump
# восстановить ТОЛЬКО одну таблицу, не трогая остальное
pg_restore -t virtual_users -d mailserver mailserver_2026-07-04.dump
Для MySQL-инсталляций логика та же, но обязателен --single-transaction, иначе дамп InnoDB на живой БД получится несогласованным:
Теперь про то, что убивает домены. Приватный DKIM-ключ (`mail.private`) и `dovecot-uidvalidity` — это критические секреты, а не «просто файлы». Потеряете DKIM-ключ — придётся генерировать новый и обновлять DNS, а пока TTL расходится, часть исходящей почты уходит с невалидной подписью и падает в спам у получателей. Потеряете uidvalidity — все клиенты пересинхронизируют ящики целиком. Поэтому конфиги и секреты идут в бэкап зашифрованными и хранятся отдельно от основного дампа данных:
bash
tar czf - /etc/dovecot /etc/postfix /etc/opendkim/keys /etc/letsencrypt \
| age -r age1qz...pubkey > secrets_$(date +%F).tar.gz.age
Ключ расшифровки (age identity или GPG private key) не хранится на бэкапируемом сервере. Иначе компрометация одного хоста означает разом и утечку данных, и потерю возможности их восстановить.
Off-site, шифрование и retention — 3-2-1 предметно
Локальная копия защищает от rm -rf и сбойного диска, но не от пожара в ЦОД и не от ransomware, который целенаправленно ищет и шифрует бэкапы. Нужна вторая копия в другом месте, зашифрованная на клиенте. restic или borg дают дедупликацию и клиентское шифрование из коробки.
bash
# бэкап в S3-совместимое хранилище, шифрование на стороне клиента
restic -r s3:s3.provider.com/mail-vault backup /vault --tag mail
# retention: 7 дневных, 4 недельных, 6 месячных, остальное удалить
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
# проверка целостности с реальным чтением 10% данных
restic check --read-data-subset=10%
Три вещи превращают это из «галочки» в реальную защиту. Первое — immutable-бакет с object lock: даже с валидными ключами ransomware не удалит и не перезапишет снапшоты в течение retention-периода. Второе — второй провайдер или хотя бы второй регион, потому что «одна компания» — это один инцидент с блокировкой аккаунта. Третье — restic check --read-data-subset в расписании: без реального чтения данных вы знаете лишь, что метаданные на месте, а не что снапшоты вообще читаются.
Тест восстановления — единственная метрика, которой можно верить
Всё вышенаписанное бессмысленно, если restore ни разу не проверялся на настоящих данных. «Задание завершилось без ошибок» не значит «данные восстановимы» — это значит, что процесс записи не упал. Единственный честный сигнал — регулярный drill.
Схема на крон раз в месяц: развернуть последний снапшот в изолированный Dovecot (отдельный контейнер, порт 10143, свой конфиг), восстановить один случайный ящик, залогиниться по IMAP, сверить число писем и контрольную сумму выборки.
Что ломается на восстановлении чаще всего, по опыту разгребания «письма пропали»:
Права слетели — забыли --numeric-ids, UID vmail на restore-хосте другой, Dovecot не может читать cur/. Лечится chown -R 5000:5000, но лучше не допускать.
`dovecot-uidvalidity` и `.dovecot.sieve` не попали в копию — фильтры пропали, клиенты пересинхронизировались.
Снапшот был не атомарным — индексы битые; спасает doveadm force-resync -u user '*', который пересобирает их из файлов.
Drill либо проходит целиком и пишет зелёный статус с датой, либо шлёт алерт. Третьего состояния — «наверное, работает» — быть не должно.
Чек-лист и что мониторить
Снапшот Maildir атомарен — снимается с LVM/ZFS/Btrfs или через doveadm backup, а не rsync по живым файлам.
rsync идёт с -aH --numeric-ids; на инкрементах держим поколения, а не зеркало с --delete.
Дампы БД в -Fc (или --single-transaction для MySQL), проверена выборочная восстановимость таблицы.
DKIM приватные ключи, TLS-серты и конфиги зашифрованы и лежат off-site отдельно от ключа расшифровки.
Off-site в immutable-бакет, второй регион/провайдер, restic check --read-data-subset в расписании.
Строгий порядок restore: конфиг → БД → данные → chown 5000:5000 → force-resync.
Последний успешный drill не старше 30 дней, восстанавливался случайный ящик с проверкой числа писем.
Отдельный алерт на сам факт: если бэкап не выполнялся более 2 суток — сигнал, потому что молчание задания и его успех — разные вещи.
Мониторьте не наличие файлов в хранилище, а два независимых сигнала: успешность выполнения задания и успешность последнего drill. Первое говорит, что данные пишутся. Второе — единственное, что говорит, что они восстановимы. Всё остальное — вера.