Как настроить mailcow на VPS для доставки писем в Gmail
Перед установкой mailcow проверьте доступность порта 25 на VPS. Если провайдер блокирует его, почта не уйдет. Настройте PTR и DNS, чтобы избежать ошибки 550 5.7.25 от Gmail.
Что вы создаете
Полноценный почтовый сервер на собственном оборудовании: SMTP для отправки и получения, IMAP для синхронизации между телефоном и ноутбуком, веб-клиент для почты и спам-фильтр, оценивающий каждое сообщение в обоих направлениях. mailcow-dockerized объединяет Postfix, Dovecot, Rspamd, SOGo webmail, MariaDB, Redis и ACME-клиент в единый стек Docker Compose, поэтому установка ПО не вызовет затруднений. Вы запустите его за полчаса.
Сложность заключается в сопутствующих аспектах. Электронная почта — это сервис, к которому остальной интернет относится с недоверием, если сервер новый. Разница между состоянием «работает» и ситуацией, когда «Gmail молча удаляет все письма», сводится к четырем DNS-записям и одной настройке репутации IP-адреса, которую вы можете не полностью контролировать. Ознакомьтесь с предварительными требованиями ниже, прежде чем арендовать сервер. Если после прочтения вы решите, что борьба за репутацию того не стоит, это вполне разумное решение; в нашем обзоре того, что действительно стоит размещать самостоятельно в 2026 году, электронная почта отнесена в категорию «только если вы серьезно настроены» именно по этим причинам.
Предварительные требования — это и есть проект
Если пропустить хотя бы один из этих пунктов, почта не будет доставлена. Ниже приведен список в порядке убывания частоты возникновения проблем:
Исходящий порт 25 должен быть открыт. Ваш сервер доставляет почту в Gmail и Microsoft по протоколу TCP через порт 25. Большинство VPS и облачных провайдеров блокируют исходящий 25 порт по умолчанию для борьбы со спамом. Эта блокировка происходит без уведомлений: при загрузке нет ошибок, всё выглядит исправно, а письма просто бесконечно висят в очереди. Проверьте порт до начала установки. Если он заблокирован, единственный способ решения — создать тикет в поддержку с просьбой открыть его. Некоторые провайдеры делают это для старых аккаунтов, другие — никогда.
Чистый IP-адрес с хорошей репутацией. Повторно используемые IP-адреса VPS часто уже находятся в черных списках из-за спама предыдущего владельца. Проверьте свой адрес в таких сервисах, как Spamhaus или mxtoolbox, прежде чем приступать к работе. Нахождение IP в списке означает отклонение писем, которое невозможно исправить программными методами.
Контроль над DNS и корректная PTR-запись. Вам потребуется добавлять записи в зону вашего домена, а также настроить обратную DNS-запись (PTR) для IP-адреса сервера, указывающую на ваше почтовое доменное имя. PTR-запись почти никогда не настраивается в панели управления DNS; она управляется владельцем IP-адреса, поэтому её нужно устанавливать в панели управления вашего VPS-провайдера или через тикет в поддержку.
6 GiB RAM и 2 vCPU — комфортный минимум. Минимальные требования mailcow составляют 6 GiB RAM плюс 1 GiB swap для частной установки; рекомендуется 8 GiB, если системой пользуется несколько человек. При объеме менее 2.5 GiB generate_config.sh предложит отключить антивирусный сканер ClamAV, чтобы ядро не начало принудительно завершать контейнеры. Для начала выделите 20 GB SSD.
DNS-имя, а не просто IP-адрес. Выберите имя хоста, например mail.example.com. Это имя станет вашим MAILCOW_HOSTNAME, субъектом TLS-сертификата, целью для PTR-записи и SMTP-баннером. Соблюдайте единообразие во всех настройках.
Шаг 1, Проверка доступности исходящего порта 25
Выполните это в первую очередь. Если проверка не пройдена, остальные действия будут бесполезны. С нового VPS попробуйте инициировать SMTP-сессию с реальным почтовым сервером:
sudo apt update && sudo apt install -y netcat-openbsd
nc -vz -w 5 gmail-smtp-in.l.google.com 25Успешный результат выглядит так:
Connection to gmail-smtp-in.l.google.com (142.250.x.x) 25 port [tcp/smtp] succeeded!Заблокированный порт будет ожидать ответа в течение 5 секунд, после чего выдаст ошибку:
nc: connect to gmail-smtp-in.l.google.com port 25 (tcp) timed out: Operation now in progressЭтот таймаут означает блокировку. Фильтрация выполняется на стороне провайдера, а не вашим локальным файрволом, поэтому локальные настройки не помогут. Откройте тикет в поддержку: "Please enable outbound TCP port 25 for my VPS at <IP>; I am running a legitimate mail server." Не устанавливайте mailcow, пока не получите ответ "succeeded". Учтите, что входящий порт 25 (соединения от других серверов к вам) — это отдельный канал, который обычно открыт; провайдеры ограничивают именно исходящий трафик.
Шаг 2, настройка DNS-записей
Распространение DNS-записей занимает время, поэтому опубликуйте все необходимые данные до начала установки. Предположим, что ваш домен — example.com, почтовый хост — mail.example.com, а IP-адрес — 10.0.0.10. Создайте в своей зоне следующие записи:
mail.example.com. A 10.0.0.10
mail.example.com. AAAA 2001:db8::10 ; only if you have IPv6
example.com. MX 10 mail.example.com.
example.com. TXT "v=spf1 mx -all"
_dmarc.example.com. TXT "v=DMARC1; p=none; rua=mailto:postmaster@example.com"SPF-запись указывает: «только мой MX-сервер может отправлять почту от имени этого домена, остальные отклонять». Начните использование DMARC с p=none, чтобы отслеживать отчеты, не блокируя при этом собственную почту; после подтверждения корректности настроек ужесточите политику до p=quarantine, а затем до p=reject. Две записи намеренно пропущены: DKIM, которую mailcow сгенерирует для вас на шаге 6, и PTR, которую нужно настроить сейчас в панели управления вашего хостинг-провайдера.
Установите PTR-запись (обратный DNS) для 10.0.0.10 в значение mail.example.com, которое в точности соответствует MAILCOW_HOSTNAME. Это единственная запись, о которой чаще всего забывают, и крупные почтовые провайдеры отклоняют письма именно из-за её отсутствия. Если в вашей панели управления нет поля для rDNS, обратитесь в службу поддержки.
Шаг 3, установка Docker
mailcow требует Docker Engine с плагином Compose v2. Используйте официальный скрипт установки от Docker, а не пакет из репозитория Ubuntu docker.io, в котором отсутствует плагин Compose:
curl -fsSL https://get.docker.com | sudo sh
sudo docker compose versionВы должны увидеть строку Docker Compose version v2.x. Если docker compose version выводит docker: 'compose' is not a docker command, значит Docker Engine установлен, но плагин Compose отсутствует. Установите плагин из репозитория Docker, повторно запустите указанный выше скрипт или воспользуйтесь нашим руководством по основам Docker Compose, где описана установка обоих компонентов из официального apt-репозитория Docker.
Шаг 4, клонирование mailcow и генерация конфигурации
cd /opt
sudo git clone https://github.com/mailcow/mailcow-dockerized
cd mailcow-dockerized
umask
sudo ./generate_config.shУбедитесь, что umask выводит 0022. mailcow не выполнит сборку при некорректной маске файлов, а свежая оболочка root в Ubuntu 24.04 уже выдает 0022. Затем скрипт запросит самое важное: полное доменное имя хоста (FQDN). Введите mail.example.com, значение должно в точности совпадать с вашей A-записью и PTR-записью. Скрипт создаст mailcow.conf — единственный файл окружения, который считывает весь стек. Откройте его, если нужно изменить веб-порты (HTTP_PORT, HTTPS_PORT) или отключить ClamAV на сервере с малым объемом ресурсов:
MAILCOW_HOSTNAME=mail.example.com
HTTP_PORT=80
HTTPS_PORT=443
SKIP_CLAMD=n # set to y to drop the virus scanner on a <2.5 GiB boxSKIP_FTS=y — еще один рычаг для систем с малым объемом ОЗУ. Полнотекстовый поиск является вторым по потреблению памяти компонентом согласно документации mailcow, а его отключение лишит вас только возможности поиска по телу писем в веб-интерфейсе.
Оставьте HTTP_PORT=80 и HTTPS_PORT=443 без изменений, если только их не занимают другие службы на хосте. Встроенному ACME-клиенту mailcow необходим доступ к 80 порту из интернета для получения сертификата. Именно поэтому не следует настраивать отдельную связку nginx-plus-Certbot на том же сервере; mailcow выпускает и обновляет собственные TLS-сертификаты внутри системы, и любая другая служба, занимающая порты 80/443, нарушит этот процесс. Это же касается любого другого сервиса, требующего публичный веб-интерфейс. Поэтому проект вроде Halcyon, стилизующий библиотеку Jellyfin под видеопрокат 90-х, который ожидает собственный reverse proxy на 443 порту, должен размещаться на другом хосте. Исключение составляют службы, не требующие публичного веб-порта: самохостируемый ретранслятор RustDesk слушает только свой диапазон портов с 21115 по 21119, поэтому он может сосуществовать на одном сервере, если у вас достаточно свободной пропускной способности сети.
Шаг 5, запуск стека и вход в систему
sudo docker compose pull
sudo docker compose up -d
sudo docker compose psПроцесс pull загружает около двух десятков образов; подождите несколько минут. Когда docker compose ps покажет, что каждый контейнер находится в состоянии running (или healthy), откройте https://mail.example.com в браузере. Имя пользователя для входа администратора по умолчанию — admin, пароль — moohoo. Сразу измените этот пароль в интерфейсе администратора в разделе Access → Administrators. Если браузер выдает предупреждение NET::ERR_CERT_AUTHORITY_INVALID, значит, сертификат ACME еще не был выпущен. Ознакомьтесь с разделом об ошибках ACME ниже, прежде чем считать, что система неисправна; наличие самоподписанного временного сертификата в первые пару минут — это нормальное поведение.
Шаг 6. Добавление домена, почтового ящика и публикация DKIM
В панели администратора откройте страницу настройки почты (Configuration → Mail Setup), перейдите на вкладку Domains, нажмите Add domain и введите example.com. Затем в разделе Mailboxes нажмите Add mailbox, чтобы создать you@example.com с паролем. Это полноценный почтовый ящик, доступный по протоколу IMAP.
Теперь настроим ключ DKIM. Перейдите в Configuration → ARC/DKIM keys. Возможно, mailcow уже сгенерировал ключ при добавлении домена. Если нет, создайте его здесь: выберите домен, оставьте селектор dkim, выберите длину 2048-bit и нажмите Add. Скопируйте длинное значение TXT-записи, которое отобразится на экране, и опубликуйте его следующим образом:
dkim._domainkey.example.com. TXT "v=DKIM1;k=rsa;t=s;s=email;p=MIIBIjANBgkqh...long-key...QAB"На странице Domains в mailcow есть кнопка DNS. Она отображает все ожидаемые записи и отмечает зеленым или красным цветом статус их публикации. Используйте этот список как контрольный: до начала тестирования доставки все строки должны быть отмечены зеленым. Если после публикации строка DKIM остается красной, это обычно означает, что ключ был некорректно разделен на части TXT. Ключ длиной 2048-bit превышает лимит в 255 символов для одной строки TXT, поэтому вставляйте его как единое логическое значение, а разделение на части доверьте вашему DNS-провайдеру.
Шаг 7, проверка доставляемости и получение оценки 10/10
Перейдите на сайт mail-tester.com, скопируйте предложенный случайный адрес и отправьте на него письмо с вашего нового почтового ящика. Войдите в веб-интерфейс SOGo по адресу https://mail.example.com/SOGo и отправьте письмо оттуда. Затем нажмите кнопку "Then check your score".
Ваша цель — оценка 10/10. Распространенные причины снижения баллов:
- SPF not aligned: отсутствует запись
MX/SPF или IP-адрес отправителя не включен в нее. Перепроверьте TXT-запись SPF. - DKIM signature does not verify: отсутствует TXT-запись
dkim._domainkey, она еще не успела распространиться по DNS или содержит ошибки. Это самая частая проблема. - No PTR / PTR mismatch: обратная DNS-запись (PTR) не указывает на
mail.example.com. Исправьте это в панели управления вашего хостинг-провайдера. - Listed on a blocklist: плохая репутация вашего IP-адреса. Подайте запрос на исключение из черного списка или запросите у провайдера другой IP-адрес.
Не отправляйте реальные письма на Gmail или Outlook, пока не получите оценку 10/10. Низкий рейтинг в сочетании с новым IP-адресом — прямой путь к попаданию вашего домена в спам-фильтры в первый же день.
Шаг 8, подключение почтового клиента
Настройте Thunderbird, Apple Mail или мобильное устройство для работы с сервером, используя следующие параметры. В качестве хоста сервера для всех настроек укажите mail.example.com:
- IMAP: порт 993, SSL/TLS (или 143 с использованием STARTTLS)
- SMTP submission: порт 465, SSL/TLS (или 587 с использованием STARTTLS)
- Имя пользователя: полный адрес электронной почты,
you@example.com - Пароль: пароль почтового ящика, который вы задали
Никогда не отправляйте почту через порт 25. Этот порт предназначен только для взаимодействия между серверами. mailcow не поддерживает аутентифицированную отправку на этом порту, и попытка подключения клиента будет отклонена. Если клиент сообщает об ошибке Relay access denied, значит, он пытается отправить почту через порт 25 или без аутентификации. Переключите его на порт 465 или 587 и используйте учетные данные вашего почтового ящика.
Шаг 9, резервное копирование действительно важных данных
mailcow поставляется со скриптом резервного копирования, который создает снимки всех томов с состоянием. Запускайте его на внешний диск или смонтированный удаленный ресурс:
sudo MAILCOW_BACKUP_LOCATION=/opt/mailcow-backups \
./helper-scripts/backup_and_restore.sh backup allall захватывает шесть компонентов, потеря любого из которых ведет к потере данных: vmail (сами почтовые ящики), crypt (ключи для расшифровки vmail, бесполезные без самих данных), mysql (база данных MariaDB, содержащая домены, пользователей, псевдонимы и настройки), redis (очереди и состояние кэша), rspamd (обученные фильтры спама/хам-писем) и postfix (почтовая очередь). Скрипт выполняется внутри вспомогательного контейнера и создает сжатые архивы, поэтому резервные копии остаются консистентными, даже если стек запущен. Автоматизируйте процесс с помощью ночного задания cron и добавьте --delete-days 14 для удаления старых наборов данных. Задание cron, которое перестало работать, не выдает уведомлений об ошибках, поэтому отправляйте код завершения скрипта туда, где вы его гарантированно заметите; собственный сервер ntfy позволяет выполнить одну команду curl в той же записи cron, чтобы получить уведомление о сбое на телефон в ту же ночь. Восстановление выполняется тем же скриптом с флагом restore, который выводит список снимков и позволяет выбрать нужный для восстановления. Резервная копия, которую вы никогда не пробовали восстанавливать — это лишь надежда, а не копия; проведите тестовое восстановление на временном VPS.
Шаг 10, Обновление по расписанию
mailcow обновляется через собственный скрипт, который загружает новый код, выполняет миграции mailcow.conf, предварительно скачивает образы и перезапускает контейнеры в нужном порядке:
cd /opt/mailcow-dockerized
sudo ./update.sh --check # reports whether an update exists, changes nothing
sudo ./update.sh # applies itСначала выполните резервное копирование (Шаг 9), так как миграцию схемы базы данных сложно отменить. Обновления выходят часто и включают исправления безопасности для демонов, доступных из Интернета, поэтому не допускайте длительного отставания почтового сервера от актуальной версии. Если после обновления какой-либо контейнер переходит в состояние unhealthy, команда sudo docker compose logs --tail=50 <service>-mailcow покажет имя демона, который не смог запуститься.
Замечание по обеспечению безопасности
mailcow использует собственный сервис netfilter (netfilter-mailcow), который блокирует IP-адреса, осуществляющие перебор паролей к портам почтового сервера и веб-интерфейса, поэтому почтовая часть защищена «из коробки». Это не распространяется на SSH самого хоста, который остается открытым и подвергается попыткам брутфорса. Используйте данную сборку в сочетании с мониторингом логов авторизации SSH через Fail2ban и входом только по ключам. Защитите административный интерфейс mailcow надежным паролем и, по возможности, ограничьте к нему доступ из публичной сети или используйте VPN.
Режимы сбоев и соответствующие им сообщения
Почта находится в очереди и не доставляется. Выполните sudo docker compose exec postfix-mailcow postqueue -p или просмотрите очередь почты в панели администратора; записи остаются в состоянии deferred с сообщением:
status=deferred (connect to gmail-smtp-in.l.google.com[142.250.x.x]:25: Connection timed out)Это означает, что исходящий порт 25 заблокирован вашим провайдером (шаг 1). Никакие изменения конфигурации не помогут, создайте тикет в поддержку. Проблема не в DNS и не в TLS; признаком является слово timed out при попытке соединения с удаленным MX-сервером по порту 25.
Gmail помечает все письма как спам или отклоняет их. Откройте сообщение в Gmail, выберите «Показать оригинал» и прочитайте результаты проверки подлинности. Ошибки dkim=fail или dkim=none означают, что ваша TXT-запись dkim._domainkey отсутствует, повреждена или еще не распространилась; опубликуйте запись в точности так, как указано на странице ARC/DKIM, и дождитесь истечения TTL. Ошибка spf=fail означает, что ваши SPF/MX-записи не включают ваш IP-адрес. Соответствие записей критически важно; одного непройденного теста достаточно, чтобы письмо попало в спам.
Отклонение крупными провайдерами при попытке соединения. В отчетах о недоставке или логах Postfix содержится сообщение Gmail об ошибке PTR:
550-5.7.25 [10.0.0.10] The IP address sending this message does not have a PTR
550-5.7.25 record setup, or the corresponding forward DNS entry does not match
550 5.7.25 the sending IP. As a policy, Gmail does not accept messages from IPs
550 5.7.25 with missing PTR records.Код 550 5.7.25 означает отсутствие или несоответствие обратной DNS-записи. Установите PTR-запись для вашего IP-адреса на mail.example.com в панели управления провайдера (шаг 2). Прямая (A) и обратная (PTR) записи должны совпадать, и обе должны указывать на то же имя хоста, которое mailcow использует при представлении другим серверам.
Браузер показывает предупреждение о сертификате, которое не исчезает. Контейнер acme-mailcow не смог получить реальный сертификат. Проверьте его лог:
sudo docker compose logs acme-mailcow | tail -n 40Строка вида Cannot validate any hostnames, skipping Let's Encrypt for 1 hour. или ошибка проверки challenge означают, что порт 80 недоступен из интернета или A-запись не указывает на этот сервер. Убедитесь, что mail.example.com разрешается в IP-адрес вашего сервера, откройте порты 80 и 443 в файрволе хоста и убедитесь, что никакой другой процесс не занимает эти порты. После устранения причины перезапустите клиент командой sudo docker compose restart acme-mailcow, не дожидаясь окончания часового интервала ожидания.
FAQ
Стоит ли вообще заниматься self-hosting для почты?
Если вам важен контроль над данными, неограниченное количество алиасов и полная независимость, то да: mailcow предоставляет профессиональный стек по цене VPS. Однако обеспечение доставляемости — это постоянная работа: репутация IP-адреса, корректность DNS-записей и мониторинг черных списков требуют регулярного внимания. Для критически важных бизнес-адресов, где один день в папке «Спам» у получателя может стоить вам денег, использование облачного провайдера — более прагматичное решение. Занимайтесь self-hosting, если вы цените контроль выше удобства и готовы обслуживать сервер. Если же ваша цель — просто хранить данные на своих мощностях, а не обязательно почту, начните с сервисов, где нет проблем с доставкой: например, фотоархив не требует настройки репутации, а в нашем сравнении PhotoPrism и Immich описаны требования к оперативной памяти и команды для резервного копирования на аналогичном VPS.
Как узнать, заблокирован ли исходящий 25 порт?
Выполните nc -vz -w 5 gmail-smtp-in.l.google.com 25 на сервере. Сообщение «succeeded!» означает, что порт открыт; timed out после паузы подтверждает, что провайдер блокирует его. Это самая частая причина, по которой self-hosted сервер может принимать почту, но не отправлять её. Единственный способ решения — запрос к провайдеру на открытие порта; локальные настройки здесь не помогут.
Почему моя почта всё равно попадает в папку «Спам» в Gmail?
Почти всегда проблема в нарушенной цепочке аутентификации. Используйте функцию «Показать оригинал» (Show original) в Gmail и проверьте статусы spf=pass, dkim=pass и dmarc=pass. Ошибка dkim=fail указывает на отсутствие или некорректную запись dkim._domainkey TXT; также на репутацию влияют несовпадение PTR-записи или использование нового IP-адреса без истории отправки. Сначала добейтесь оценки 10/10 на mail-tester.com, затем постепенно прогревайте IP, увеличивая количество отправляемых писем день за днем, вместо массовой рассылки в первый же день.
Что именно нужно копировать при бэкапе?
Выполните backup_and_restore.sh backup all и храните полученный архив вне сервера. Он включает vmail (почтовые ящики), crypt (ключи для их расшифровки), базу данных MariaDB (домены, пользователи, алиасы, настройки), Redis, данные обучения Rspamd и очередь Postfix. Том crypt — это то, что часто забывают; без него бэкап vmail представляет собой нечитаемый зашифрованный текст. Хотя бы раз протестируйте восстановление на тестовой машине.
Можно ли запустить mailcow на VPS с 2 ГБ ОЗУ?
Не рекомендуется. Скрипт generate_config.sh предлагает отключить ClamAV, если объем памяти менее 2.5 ГБ, но даже в этом случае Rspamd, ClamAV, Dovecot и MariaDB будут конкурировать за ресурсы. При любой реальной нагрузке вы столкнетесь с использованием swap и завершением процессов по OOM-killer. Считайте 6 ГБ ОЗУ плюс 1 ГБ swap минимальным порогом для стабильной работы одного пользователя, а при добавлении новых пользователей сразу переходите на 8 ГБ.