Классическая почта на Linux десятилетиями собирается из конструктора: MTA Postfix принимает и маршрутизирует письма, Dovecot раскладывает их по ящикам по протоколам IMAP и POP3, OpenDKIM подписывает исходящий трафик, Rspamd и SpamAssassin фильтруют входящий спам, OpenLDAP или SQL хранят учётные записи, а связка из Certbot, Postfix-карт сертификатов и десятка конфигурационных файлов удерживает всё это вместе. Каждый демон обновляется отдельно, каждый имеет собственный синтаксис ошибок, и любое расхождение между ними превращается в письма, которые «уходят, но не доходят». Stalwart Mail Server предлагает иную инженерную модель: единый исполняемый файл, написанный на Rust, который одновременно является SMTP-, IMAP-, JMAP- и CalDAV/CardDAV-сервером, содержит встроенный веб-интерфейс администратора и автоматически управляет DKIM-ключами и TLS-сертификатами. В этом разборе мы развернём его на VDS в Docker Compose, разберём архитектурные изменения версии v0.16 и настроим защиту домена от подделки писем.
1. Почему связка Postfix и Dovecot требует слишком много внимания
Проблема классического почтового стека не в том, что он плохо работает: Postfix и Dovecot остаются промышленным стандартом и обслуживают миллионы доменов. Проблема в стоимости владения для команды из одного-двух человек:
- Шесть и более независимых демонов. Postfix, Dovecot, OpenDKIM, Rspamd, ClamAV, Redis и Certbot обновляются по отдельности. Обновление одного компонента ломает совместимость с другим, а откат требует помнить последовательность версий.
- Разрозненная конфигурация. Параметры ящиков живут в SQL или LDAP, параметры маршрутизации — в
main.cf, параметры хранения — вdovecot.conf, DKIM-ключи — в файлах на диске, а сертификаты — в третьем месте. Единой точки правды нет. - Ручная синхронизация DKIM и TLS. Ротация ключей подписи и продление сертификатов требуют перезапуска нескольких служб в правильном порядке, иначе часть писем уходит без подписи или с просроченным сертификатом.
- Отсутствие современного API. Управление ящиками возможно только через файлы или SQL-запросы. Автоматизировать выдачу почты новому сотруднику из CRM или панели поддержки без самописных скриптов практически невозможно.
| Критерий | Классический стек (Postfix + Dovecot + OpenDKIM) | Stalwart v0.16.27 |
|---|---|---|
| Компоненты | 6–8 демонов и пакетов | Один бинарник и один контейнер |
| Конфигурация | Файлы в разных каталогах + SQL/LDAP | Один config.json + настройки в БД как JMAP-объекты |
| Управление | Правка файлов и SQL-запросы | Веб-интерфейс, CLI и JMAP API |
| DKIM | Ручная генерация и ротация ключей | Автогенерация, ротация и публикация в DNS |
| TLS и ACME | Certbot + hooks перезапуска служб | Встроенный ACME: TLS-ALPN-01, HTTP-01, DNS-01 |
| Современные протоколы | IMAP4rev1, POP3, SMTP | JMAP, IMAP4rev2, POP3, ManageSieve, CalDAV, CardDAV, WebDAV |
2. Что представляет собой Stalwart и какие протоколы он закрывает
Проект stalwartlabs/stalwart распространяется по лицензии AGPL-3.0-only (расширенные корпоративные функции вынесены в отдельную коммерческую лицензию LicenseRef-SEL) и на момент публикации статьи имеет более 15 000 звёзд на GitHub. Сервер написан на Rust и собирается в один статически связанный исполняемый файл.
Поддерживаемый набор протоколов закрывает практически все задачи корпоративной почты и групповой работы:
- Почта и отправка: SMTP с поддержкой STARTTLS и implicit TLS, а также JMAP for Mail по спецификации RFC 8621 — современному JSON-протоколу, который заменяет IMAP в веб-клиентах.
- Доступ к ящикам: IMAP4rev2 (RFC 9051) и IMAP4rev1 (RFC 3501), POP3 (RFC 1939) с расширением STLS.
- Фильтрация на сервере: ManageSieve (RFC 5804) позволяет пользователю раскладывать письма по папкам правилами прямо на сервере, без клиента.
- Календари, контакты и файлы: CalDAV, CardDAV и WebDAV — то есть корпоративный календарь и адресная книга работают из коробки, без Nextcloud.
- Современные расширения JMAP: WebSocket-поток уведомлений (RFC 8887), управление вложениями Blob Management (RFC 9404) и квоты Quotas (RFC 9425).
💡 Совет инженера: зачем в почте JMAP
JMAP передаёт состояние ящика одним JSON-запросом вместо последовательности IMAP-команд и поддерживает push-уведомления через WebSocket. Для веб-клиента это означает мгновенное появление новых писем без опроса сервера каждые 30 секунд, а для мобильных приложений — заметно меньший расход трафика и батареи.
3. Архитектура версии v0.16: один файл конфигурации и JMAP-объекты в базе
Перед развертыванием необходимо понять главное архитектурное изменение, которое произошло в ветке v0.16. Оно ломает совместимость со всеми предыдущими версиями, и на нём спотыкаются администраторы, привыкшие к конфигурации v0.15.
В старых версиях сервер читал один или несколько TOML-файлов, причём часть настроек лежала на диске, а часть — в базе данных. Такая двойственность порождала реальные проблемы: в кластере каждый узел обязан был хранить собственную копию конфигурационного файла, и расхождение между копиями было легко внести, но почти невозможно отладить.
Начиная с v0.16 на диске лежит единственный компактный файл config.json, который описывает только хранилище данных (datastore) — то есть ту базу, в которой сервер держит всё остальное. Домены, учётные записи, правила маршрутизации, DKIM-подписи, бэкенды хранения, лимиты и антиспам-правила теперь хранятся внутри этого хранилища как JMAP-объекты. Управление ими идёт через JMAP management API, а веб-интерфейс и официальный CLI — это просто клиенты этого API.
| Область | Версии до v0.16 | Версия v0.16.x |
|---|---|---|
| Формат конфигурации | TOML, несколько файлов | Один config.json (только datastore) |
| Где живут настройки | Часть в файлах, часть в БД | Полностью в БД как JMAP-объекты |
| API управления | REST | JMAP management API |
| Данные пользователей | БД и блобы | Без изменений в раскладке БД |
| Кластер | Синхронизация файлов вручную | Единая конфигурация по определению |
⚠️ Важное предупреждение: миграция с v0.15 и ниже
Переход с v0.15.x на v0.16.x требует многошаговой процедуры: сначала сервер поднимают в режиме восстановления (recovery mode), затем официальным CLI проигрывают экспорт настроек и только после этого переключают службу на новый config.json. Данные пользователей — письма, календари, контакты и файлы — при этом остаются на месте, меняется только слой управления. Официальный порядок шагов описан в UPGRADING/v0_16.md репозитория, и пропускать их нельзя. В этой статье мы ставим сервер с нуля, поэтому процедура миграции не требуется.
4. Требования к VDS, порты и критичная проверка процессора
Почтовый сервер предъявляет к инфраструктуре требования, которых нет у обычного веб-проекта. Разберём их по порядку, начиная с самого коварного.
Проверка набора инструкций процессора (x86-64-v2)
Начиная с релиза v0.16.26 официальные x86_64-сборки и Docker-образы Stalwart требуют процессор с набором инструкций x86-64-v2, который включает SSE3, SSSE3, SSE4.1, SSE4.2 и POPCNT. На более старых процессорах сервер отказывается запускаться. Проблема в том, что виртуальные машины с обобщённой моделью процессора, например QEMU с типом «Common KVM processor», этот набор не предоставляют — контейнер запустится и сразу завершится с ошибкой.
Есть два способа решения. Первый — переключить тип процессора виртуальной машины на host или x86-64-v2-AES (в Proxmox это делается в настройках ВМ). Второй — использовать musl-сборку: Docker-теги с суффиксом -alpine, например stalwartlabs/stalwart:v0.16-alpine. Проверить поддерживаемые флаги на сервере можно одной командой:
# Проверка наличия инструкций x86-64-v2 (sse4_2 и popcnt обязательны)
grep -o -m1 -E 'sse4_2|ssse3|sse3' /proc/cpuinfo | sort -u
grep -m1 -o 'popcnt' /proc/cpuinfo
Если обе команды вернули значения — стандартный образ подойдёт. Если нет — берите -alpine, иначе контейнер будет перезапускаться по кругу без внятной ошибки в docker compose logs.
Сетевые порты почтового сервера
| Порт | Протокол | Назначение и доступ |
|---|---|---|
25 |
SMTP | Приём писем от других серверов. Обязателен публично |
465 |
SMTP over TLS | Отправка из почтовых клиентов (implicit TLS) |
587 |
SMTP Submission | Отправка с аутентификацией (STARTTLS) |
993 |
IMAPS | Чтение почты клиентами по TLS |
143 |
IMAP | Чтение с апгрейдом до TLS через STARTTLS |
4190 |
ManageSieve | Серверные правила фильтрации почты |
443 |
HTTPS / JMAP | Веб-клиент, JMAP и ACME TLS-ALPN-01 |
8080 |
HTTP (админка) | Первичная настройка. Только 127.0.0.1 |
Дополнительно нужны POP3-порты 110 и 995, если ящики читаются старыми клиентами. Все эти порты объявлены в EXPOSE официального Dockerfile, и ни один из них не следует держать закрытым, кроме административного 8080.
Существует ещё два требования, которые невозможно выполнить настройкой внутри сервера. Первое — обратная DNS-запись (PTR): она обязана указывать на то же имя, что и прямая A-запись почтового узла, иначе крупные провайдеры будут помечать письма как спам. Второе — разблокированный порт 25: многие российские хостеры по умолчанию его закрывают и открывают по обращению в поддержку, а некоторые запрещают исходящие соединения на 25 порт полностью. Перед оплатой тарифа уточните оба пункта.
5. Подготовка DNS, развертывание в Docker Compose и первый запуск
Начнём с DNS. Без корректных записей письма будут уходить в спам даже при идеально настроенном сервере, поэтому зафиксируем минимум до первого запуска контейнера.
; Основные записи для домена example.ru
mail.example.ru. IN A 203.0.113.10
example.ru. IN MX 10 mail.example.ru.
example.ru. IN TXT "v=spf1 mx -all"
_dmarc.example.ru. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.ru"
; CAA разрешает выпуск сертификатов только Let's Encrypt
example.ru. IN CAA 0 issue "letsencrypt.org"
Четыре момента, которые важно не перепутать. Запись MX указывает на имя узла, а не на IP-адрес. В SPF директива mx разрешает отправку со всех хостов, перечисленных в MX, а -all запрещает всё остальное — это строгий и правильный режим. Запись DMARC с политикой p=quarantine заставляет получателей отправлять неподписанные письма в спам. Запись CAA запрещает выпускать сертификаты на ваш домен любому удостоверяющему центру, кроме Let's Encrypt, что защищает от ошибочной или злонамеренной выдачи.
💡 Совет инженера: проверьте DNS до запуска
Убедитесь, что A-запись уже разошлась по резолверам, через DNS Lookup SysKit, а открытые порты после настройки файрвола проверьте сканером портов. Для обратной зоны PTR используйте определение IP и сверяйте результат с ответом провайдера.
Создание каталогов и прав доступа
Официальный образ работает не от root, а от непривилегированного пользователя stalwart с UID 2000. В Dockerfile за это отвечают директивы USER stalwart и VOLUME ["/etc/stalwart", "/var/lib/stalwart"], а право слушать привилегированные порты 25 и 443 выдано бинарнику через setcap cap_net_bind_service. Поэтому каталоги на хосте нужно заранее отдать этому UID, иначе контейнер не сможет записать базу:
# Каталоги для конфигурации и данных
mkdir -p /opt/stalwart/etc /opt/stalwart/data
# Владелец — UID/GID 2000, под которым работает процесс в контейнере
chown -R 2000:2000 /opt/stalwart
# Права: владелец читает и пишет, остальные не имеют доступа
chmod 750 /opt/stalwart /opt/stalwart/etc /opt/stalwart/data
Манифест Docker Compose
services:
stalwart:
image: stalwartlabs/stalwart:v0.16.27
container_name: stalwart
restart: unless-stopped
hostname: mail.example.ru
environment:
# Имя узла и публичный адрес веб-клиента
STALWART_HOSTNAME: mail.example.ru
STALWART_PUBLIC_URL: https://mail.example.ru
ports:
# SMTP: приём писем из интернета
- "25:25"
# SMTP Submission: отправка из клиентов
- "465:465"
- "587:587"
# IMAP и ManageSieve
- "143:143"
- "993:993"
- "4190:4190"
# HTTPS для веб-клиента, JMAP и ACME TLS-ALPN-01
- "443:443"
# Админка только на локальной петле: доступ через SSH-туннель
- "127.0.0.1:8080:8080"
volumes:
# Конфигурация (config.json) и данные (база, блобы)
- ./etc:/etc/stalwart
- ./data:/var/lib/stalwart
mem_limit: 2g
cpus: 2.0
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Обратите внимание на три инженерных решения. Порт 8080 привязан к 127.0.0.1: панель первичной настройки не должна быть доступна из интернета ни при каких обстоятельствах, а работать с ней мы будем через SSH-туннель (механику обхода файрвола контейнерами мы разбирали в статье Docker обходит UFW на Linux). Лимиты mem_limit и cpus заданы на верхнем уровне сервиса, без режима Swarm, поэтому действуют в обычном docker compose. Логи ограничены по размеру, иначе журнал контейнера способен занять весь диск при интенсивном почтовом потоке.
Отдельно про порт 443. Stalwart занимает его сам, потому что встроенный ACME-клиент поддерживает проверку TLS-ALPN-01, которая проходит именно на 443 порту. Если на этом же сервере уже работает Nginx или Caddy на 443, порт нужно освободить либо переключить ACME на проверку DNS-01 — об этом ниже.
Первый запуск и вход в панель настройки
# Запуск контейнера
cd /opt/stalwart
docker compose up -d
# Ожидание инициализации хранилища
docker compose ps
docker compose logs -f stalwart
При первом старте сервер поднимается в bootstrap-режиме: он создаёт хранилище и генерирует временный пароль администратора, который выводится в лог. Официальный установщик Stalwart прямо указывает, что забрать его нужно из журнала службы, а завершить настройку — в браузере на порту 8080. Для Docker команда поиска пароля выглядит так:
# Извлечение временного пароля администратора из логов контейнера
docker compose logs stalwart | grep -A8 'bootstrap mode'
Панель слушает только локальную петлю, поэтому открываем к ней SSH-туннель со своей рабочей машины:
# Проброс 8080 порта сервера на локальный компьютер
ssh -L 8080:127.0.0.1:8080 root@203.0.113.10
После этого в браузере открываем http://127.0.0.1:8080/admin, вводим логин admin и пароль из логов. Мастер настройки предложит указать имя домена, создать первую учётную запись и задать постоянный пароль администратора. Вместо поиска пароля в журнале можно сразу зафиксировать его переменной окружения STALWART_RECOVERY_ADMIN=admin:ВашПароль — она поддерживается официальным установщиком и удобна при автоматизированном развертывании.
⚠️ Важное предупреждение: смените временный пароль сразу
Пароль из bootstrap-режима действует до первой смены и записан в журнал контейнера открытым текстом. Если журнал успел уйти в систему централизованного сбора логов, пароль считается скомпрометированным. Смените его в первый же вход в панель, а старые записи журнала удалите.
Рекомендуемые VDS-провайдеры
Отказоустойчивые сервера с быстрыми NVMe и каналом до 1 Гбит/с
Timeweb Cloud — Быстрые NVMe VDS
Быстрые NVMe-накопители для базы почты и вложений, безлимитный трафик и понятная процедура открытия порта 25 по запросу в поддержку.
Selectel — Инфраструктура Tier III
Отказоустойчивые дата-центры в РФ, приватные сети и прогнозируемая задержка диска — важно для почтовой базы под нагрузкой.
Beget — Простой старт для домена
Готовые шаблоны Ubuntu 24.04, оплата для юридических лиц с полным пакетом закрывающих документов и настройка PTR через панель.
6. TLS-сертификаты через встроенный ACME без Certbot
Классический путь получения сертификата на почтовом сервере выглядит так: Certbot выпускает файлы, затем Postfix и Dovecot перезапускаются, чтобы подхватить их, а задача продления через deploy-hook должна сработать в правильном порядке. Любой сбой в этой цепочке даёт просроченный сертификат и отказ клиентов подключаться.
Stalwart решает задачу иначе: ACME-клиент встроен в сам сервер, а поддерживаемые типы проверки владения доменом реализованы непосредственно в коде — TLS-ALPN-01, HTTP-01, DNS-01 и DNS-PERSIST-01. Сервер сам обновляет сертификаты по запросу и показывает их детали в панели.
| Тип проверки | Что требуется | Когда выбирать |
|---|---|---|
TLS-ALPN-01 |
Свободный порт 443 | Выделенный почтовый VDS без веб-сервера |
HTTP-01 |
Свободный порт 80 | Порт 443 занят, а 80 свободен |
DNS-01 |
API DNS-провайдера | Порты 80 и 443 заняты или закрыты |
DNS-PERSIST-01 |
Долгоживущая TXT-запись | Провайдер без API, ручное управление зоной |
Ветка DNS-01 работает не только вручную: сервер умеет сам управлять записями MX, TXT, CNAME, SRV, CAA и TLSA в зоне. Из поддерживаемых провайдеров в актуальном релизе заявлены Route53, Google Cloud DNS, Bunny, Porkbun и DNSimple, а для собственных DNS-серверов есть динамическое обновление зоны по RFC 2136 с подписью SIG(0). Дополнительно поддерживаются записи CAA с параметром accounturi и публикация TLSA — что закрывает тему DANE для тех, кто её использует.
💡 Совет инженера: проверьте цепочку сертификата после выпуска
Убедитесь, что сервер отдаёт полную цепочку и корректные сроки, через проверку SSL-сертификата. Если сайт и почта живут на одном VDS, почтовый сервер должен занимать отдельный поддомен, иначе TLS-ALPN-01 не сможет ответить на проверку.
7. Подпись домена: DKIM, SPF и DMARC под контролем
Три механизма отвечают за то, поверит ли почтовый сервер получателя письму с вашего домена. SPF перечисляет IP-адреса, которым разрешено отправлять почту. DKIM подтверждает целостность письма криптографической подписью. DMARC сообщает, что делать с письмами, не прошедшими обе проверки, и является главным сигналом для борьбы с подделкой домена.
В старом стеке DKIM-ключ генерируют утилитой opendkim-genkey, публикуют TXT-запись вручную, а при ротации повторяют процедуру и не забывают перезапустить фильтр. Stalwart закрывает этот цикл автоматически: ключи генерируются при подключении домена, хранятся в базе данных, ротируются по расписанию, а публикация записи выполняется через тот же DNS-провайдер, что настроен для ACME. Дополнительно сервер умеет игнорировать небезопасные подписи при проверке DKIM, что снижает число ложных срабатываний на письмах отправителей с устаревшим 512-битным ключом.
Порядок настройки домена в панели
- Добавьте домен в разделе управления доменами и укажите имя вида
example.ru. - Создайте DKIM-подпись: селектор, размер ключа и алгоритм. Панель сразу покажет готовую запись
TXT. - Опубликуйте запись в DNS: вручную, либо подключив провайдера и включив автоматическое управление.
- Проверьте результат отправкой тестового письма на сервис проверки спама и убедитесь, что подпись проходит и SPF выравнивается.
- Ужесточите DMARC: начните с политики
p=none, соберите отчёты о неполадках, и только потом переключитесь наquarantineилиreject.
⚠️ Важное предупреждение: не включайте reject сразу
Политика p=reject, включённая в первый же день, отрезает легитимные рассылки: каталоги почтовых адресов, сервисы уведомлений и CRM отправляют письма через собственные серверы, и без собранных отчётов вы не узнаете, какие из них сломались. Начните с none и подождите две недели реальных отчётов.
Что проверить после настройки
- Отсутствие в блок-листах. Проверьте IP через проверку URI в чёрных списках: попадание в SPI, Spamhaus или Barracuda означает, что письма будут отклоняться до попытки доставки.
- Корректность PTR. Обратная запись должна совпадать с прямым именем узла, а не просто существовать.
- Непустые записи SPF и DMARC. Частая ошибка — опечатка в имени
_dmarcили использование дефиса вместо подчёркивания. - Прохождение подписи. В тестовом письме заголовок
Authentication-Resultsдолжен содержатьdkim=passиspf=pass. - Отсутствие открытого релея. Проверьте, что отправка без аутентификации через 25 порт запрещена, иначе сервер за считанные часы попадёт в рассылочные базы.
8. Резервное копирование, обновления и мониторинг
Почтовый сервер — это данные, которые невозможно восстановить из репозитория. Письма, календари и контакты существуют только в двух каталогах, объявленных как тома официального образа: /etc/stalwart с файлом config.json и /var/lib/stalwart с базой данных и вложениями. Копировать их «на горячую» из работающего контейнера нельзя: база данных в момент записи находится в промежуточном состоянии, и архив получится неконсистентным.
#!/usr/bin/env bash
set -euo pipefail
BACKUP_DIR="/var/backups/stalwart"
STAMP="$(date +%Y%m%d-%H%M%S)"
ARCHIVE="${BACKUP_DIR}/stalwart-${STAMP}.tar.gz"
mkdir -p "${BACKUP_DIR}"
# Гарантированно возвращаем контейнер в строй при любом исходе
cleanup() {
docker compose -f /opt/stalwart/docker-compose.yml unpause \
>/dev/null 2>&1 || true
}
trap cleanup EXIT
# Замираем контейнер: файлы на диске становятся консистентными
docker compose -f /opt/stalwart/docker-compose.yml pause
tar -czf "${ARCHIVE}" \
-C /opt/stalwart etc data
# Проверяем читаемость архива до отправки в хранилище
tar -tzf "${ARCHIVE}" >/dev/null
echo "Создан архив: ${ARCHIVE}"
# Хранение локальных копий: 14 дней
find "${BACKUP_DIR}" -name 'stalwart-*.tar.gz' -mtime +14 -delete
Скрипт замораживает контейнер на время чтения файлов, а конструкция trap ... EXIT гарантирует, что при любой ошибке — включая падение tar — сервер будет разморожен. Без этой страховки прерванный бэкап оставит почту недоступной до ручного вмешательства.
Готовый архив отправляйте в объектное хранилище, а не на тот же диск: выгрузку в S3 удобно собрать по рецепту из нашего материала о шифрованных бэкапах VDS и Docker в S3. Отдельно проверяйте, что архив действительно разворачивается на тестовой машине — непроверенный бэкап не считается бэкапом.
Проверка работоспособности и мониторинг
Образ содержит встроенный HEALTHCHECK, который обращается к эндпоинту /healthz/live с заголовком X-Forwarded-For, поэтому состояние контейнера сразу видно в docker compose ps. Проверить службу снаружи можно той же командой, что использует сам образ:
# Проверка живости сервера с локальной петли
curl -fsS -H "X-Forwarded-For: 127.0.0.1" http://127.0.0.1:8080/healthz/live
# Альтернатива по HTTPS, если веб-клиент уже настроен
curl -fsSk https://127.0.0.1:443/healthz/live
Эндпоинт /healthz/live отвечает, если процесс жив, — этого достаточно для внешнего мониторинга доступности. Полноценный контроль почтового трафика строится иначе: настройте внешний чекер, который раз в несколько минут подключается по IMAPS к тестовому ящику, и отдельный чекер, отправляющий письмо на внешний адрес и проверяющий его приход. Мониторинг одного лишь порта не увидит ситуацию, когда сервер принимает соединения, но не может доставить письмо из-за проблем с DNS-резолвером или блокировки на стороне получателя.
Обновление версии
# Загрузка нового образа и перезапуск с сохранением томов
cd /opt/stalwart
docker compose pull
docker compose up -d
# Проверка, что контейнер не ушёл в цикл перезапуска
docker compose ps
docker compose logs --tail=50 stalwart
Порядок обновления прост, но требует осторожности в двух местах. Первое: перед сменой тега образа сделайте бэкап и проверьте, что новая версия не находится в мажорной ветке с ломающими изменениями — переход между семействами версий Stalwart требует отдельной процедуры. Второе: помните о требовании x86-64-v2. Если сервер работает на musl-сборке -alpine, обновляйтесь строго на теги с тем же суффиксом, иначе после docker compose pull контейнер перестанет стартовать на старом процессоре.
⚠️ Важное предупреждение: сначала бэкап, потом pull
docker compose pull необратимо заменяет локальный образ, и откатиться на предыдущую версию можно только повторной загрузкой конкретного тега. Зафиксируйте текущую версию в переменной STALWART_VERSION в .env и подставляйте её в манифест — тогда откат сводится к смене одной строки.
9. Чек-лист подготовки почтового сервера к промышленной эксплуатации
| Параметр | Требование | Зачем |
|---|---|---|
| Процессор | x86-64-v2 или тег -alpine |
Иначе контейнер не стартует с v0.16.26 |
| Админка 8080 | 127.0.0.1:8080:8080 + SSH-туннель |
Защита от обхода UFW через iptables Docker |
| Bootstrap-пароль | Сменён при первом входе | Он записан в журнал открытым текстом |
| PTR | Совпадает с A-записью | Без него крупные провайдеры режут почту |
| SPF, DKIM, DMARC | Все три опубликованы | Защита домена от подделки писем |
| Открытый релей | Отправка только после аутентификации | Иначе сервер попадает в блок-листы за сутки |
| Бэкап | pause → tar → unpause → S3 | Консистентность базы и вложений |
Stalwart убирает главную причину, из-за которой компании годами не решаются держать собственный почтовый сервер: необходимость поддерживать полдесятка независимых демонов и вручную синхронизировать DKIM-ключи с TLS-сертификатами. Один процесс, одна база настроек и встроенный ACME-клиент превращают эту задачу из постоянного сопровождения в разовое развертывание. Остаётся то, что не решается никакой автоматизацией: корректная обратная DNS-запись, разблокированный порт 25 и дисциплина резервного копирования.
🎯 Разверните почтовый сервер на подготовленной инфраструктуре
Для Stalwart достаточно компактного VDS с быстрым NVMe-диском: база почты чувствительна к задержкам записи, а вложения занимают основную часть дискового пространства. Выбирайте провайдера, который открывает порт 25 и настраивает PTR по обращению в поддержку.