Почтовый сервер надо было поднять в своей инфраструктуре, на Hyper-V. Установка как таковая прошла ровно и заняла меньше всего времени за весь проект.
Интереснее не она, а то, что делается до неё. У почты есть несколько условий работы, которые от вас не зависят и выясняются дорого — уже после того, как всё настроено.
Коротко
- Gen 2, Ubuntu 22.04 LTS, 4 vCPU, 8 ГБ памяти.
- Dynamic Memory отключил сразу: с докерной нагрузкой она даёт нестабильность.
- До установки — внешний IP по чёрным спискам, открытый 25-й порт, PTR.
- Все три чинятся не вашими руками, поэтому выясняются первыми.
Конфигурация
Виртуалка второго поколения, Ubuntu 22.04 LTS, 4 виртуальных ядра, 8 гигабайт памяти. Для ста сорока ящиков этого достаточно с запасом.
Динамическую память я отключил сразу, не пробуя. Причина простая: под докерной нагрузкой она даёт нестабильность, и выяснять это в бою, когда почта уже живая, — плохая идея. Память здесь дешевле, чем разбирательство «почему сервис иногда ведёт себя странно».
Это тот случай, когда лучше зафиксировать ресурс, чем экономить его динамически. Экономия была бы небольшой, а цена ошибки — доверие к системе, которую только что развернули.
Делается это на хосте, при выключенной виртуалке:
Set-VMMemory -VMName "mail" -DynamicMemoryEnabled $false -StartupBytes 8GB
Set-VMProcessor -VMName "mail" -Count 4
Что проверить до установки
Внешний IP по чёрным спискам. Адрес мог быть использован до вас кем угодно. Если он в списках, письма будут отвергаться, и вы будете искать причину в SPF, DKIM и настройках Postfix — то есть везде, кроме нужного места. Проверил заранее: чистый.
Проверяется запросом к списку, причём адрес записывается задом наперёд — здесь для примера 203.0.113.25:
dig +short 25.113.0.203.zen.spamhaus.org
# пустой ответ — в списке нет
И вот тут важная оговорка, которая относится не только к этой команде. Пустой ответ означает «в списке нет» только при условии, что запрос вообще дошёл. Та же пустота получится, если резолвер недоступен или имя набрано с опечаткой. Прежде чем радоваться чистому результату, стоит для сверки запросить адрес, который заведомо в списке, — и убедиться, что проверка умеет отвечать «да».
Порт 25. Многие провайдеры закрывают его по умолчанию и не сообщают об этом. Без него исходящая почта не уйдёт. Проверил: открыт.
nc -vz -w5 gmail-smtp-in.l.google.com 25
PTR-запись. Обратная зона почти всегда не в вашей власти — её заказывают у провайдера, и делается это столько, сколько делается у них. Поэтому шаг отдельный и планируется заранее, а не в день переключения.
dig +short -x 203.0.113.25 # должен вернуть mail.example.com.
Общий принцип: сначала выясняется то, что нельзя починить своими руками. Если IP грязный, порт закрыт или PTR не получить — это меняет весь план, и узнавать об этом надо до, а не после.
Установка
Сама установка — три команды:
cd /opt/mailcow_data
git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized && ./generate_config.sh
generate_config.sh спросит имя почтового сервера и часовой пояс и соберёт конфигурацию. Дальше docker compose up -d поднимает набор контейнеров.
Каталог я выбрал свой, а не /opt/mailcow-dockerized из документации. Держите это в голове при чтении чужих инструкций: они все написаны под стандартный путь, и команду каждый раз придётся править под свой.
Итог
Виртуалка стабильна, mailcow установлен, дальше начиналось интересное — в частности, сертификат, который отказывался выпускаться по причине, не имеющей отношения ни к сертификатам, ни к DNS. Об этом отдельно.