MAATRIX / Блог / Listmonk на сервере: частые ошибки и решения

Listmonk на сервере: частые ошибки и решения

MAATRIX

Listmonk — редкий случай, когда self-hosted рассылки реально заменяют Mailchimp и SendGrid без ежемесячной платы за каждую тысячу подписчиков. Но именно потому, что вы сами отвечаете за SMTP, очередь и репутацию IP, ошибки здесь бьют больнее: письма молча уходят в спам, campaign зависает на "sending", а в логах — непонятный набор кодов. Разберём самые частые проблемы установки Listmonk на VPS и их решения — без теории, только то, что реально чинит.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Campaign застрял в статусе "sending" и не двигается

Самая частая жалоба: кампания создана, запущена, а счётчик отправленных писем не растёт или растёт на 2-3 письма и замирает.

Первая причина — исчерпан лимит соединений с SMTP-сервером. Listmonk по умолчанию открывает несколько параллельных соединений (max_conns), и если ваш почтовый провайдер (или свой Postfix) ограничивает одновременные подключения с одного IP, отправка встаёт колом без явной ошибки в UI.

Проверьте настройки в config.toml или через переменные окружения:

[smtp]
host = "smtp.example.com"
port = 587
max_conns = 2
max_msg_retries = 2
idle_timeout = "15s"
wait_timeout = "5s"

Снизьте max_conns до 2-3 и проверьте лог контейнера — там обычно видна реальная причина:

docker logs listmonk-listmonk-1 --tail 100 -f

Вторая причина — Listmonk ждёт ответа от SMTP дольше, чем разрешает idle_timeout, и соединение рвётся посередине пачки. Увеличьте таймаут до 30-60 секунд, если ваш SMTP (особенно внешний, вроде Amazon SES или Mailgun) отвечает медленно под нагрузкой.

Третья, менее очевидная причина — забита очередь campaign_views в PostgreSQL из-за большого числа подписчиков без индекса. Если база разрослась (от 50-100 тысяч контактов), проверьте план запроса:

EXPLAIN ANALYZE SELECT * FROM subscribers WHERE status = 'enabled' LIMIT 1000;

Если план показывает Seq Scan вместо Index Scan — пересоздайте индексы штатной командой Listmonk при апгрейде или вручную через listmonk --upgrade.

Письма уходят, но падают в спам

Технически кампания отправлена успешно, а получатели её просто не видят — Gmail и Яндекс.Почта режут письмо в папку "Спам" или "Промоакции".

Это на 90% вопрос репутации IP и настройки SPF/DKIM/DMARC, а не самого Listmonk. Если вы используете собственный Postfix как relay, обязательно настройте все три записи — без них крупные почтовики просто не станут доверять письмам с вашего сервера. Подробный разбор этой настройки есть в статье про SPF, DKIM и DMARC, а если письма и после этого не долетают — смотрите отдельный разбор почему письма уходят в спам.

Внутри Listmonk тоже есть на что повлиять:

  • В настройках кампании (Admin → Settings → SMTP) указывайте адрес отправителя с домена, на котором настроен SPF/DKIM, а не с общего домена хостера.
  • Включите track-открытий и кликов аккуратно — избыточные UTM-метки и трекинг-пиксели повышают спам-скор у некоторых фильтров.
  • Не начинайте рассылку сразу с 50 тысяч писем на новом домене. Прогревайте IP: первую неделю — по 200-500 писем в день, постепенно наращивая объём. Это ориентир, у разных почтовиков и репутации домена цифры будут отличаться.
  • Проверяйте spam-score перед массовой отправкой через spamassassin локально или mail-tester.com на тестовом адресе.

Если Listmonk настроен слать через внешний SMTP-relay (SendGrid, Mailgun, Postmark) — проблема со спамом обычно решается быстрее, поскольку репутация домена провайдера уже прогрета. Но это платный вариант, частично убивающий смысл self-hosted решения.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Ошибка "dial tcp: i/o timeout" при подключении к SMTP

Классическая ошибка в логах Listmonk при попытке отправки:

error sending message: dial tcp 111.222.33.44:587: i/o timeout

Причина почти всегда одна из трёх:

  1. Хостер блокирует исходящий 25/465/587 порт. Многие облачные провайдеры по умолчанию режут SMTP-трафик для борьбы со спамом с новых VPS. Проверьте доступность порта вручную:
telnet smtp.example.com 587
# или
nc -zv smtp.example.com 587

Если соединение не устанавливается — порт заблокирован на уровне сети хостера, и никакие настройки Listmonk это не исправят. Нужен провайдер, который явно не блокирует исходящий SMTP, либо запрос на разблокировку у поддержки.

  1. Неверный firewall на самом сервере. Проверьте исходящие правила:
sudo ufw status verbose
# разрешить исходящий SMTP, если правила слишком строгие
sudo ufw allow out 587/tcp
  1. Docker-сеть не пропускает трафик наружу. Если Listmonk запущен в Docker Compose, а SMTP-relay указан по внутреннему hostname вместо реального адреса — контейнер физически не может его разрезолвить. Проверьте DNS изнутри контейнера:
docker exec -it listmonk-listmonk-1 nslookup smtp.example.com

База PostgreSQL не поднимается после рестарта

После docker compose restart или перезагрузки сервера Listmonk падает с ошибкой подключения к базе:

pq: password authentication failed for user "listmonk"

или контейнер listmonk-db-1 вовсе не стартует. Чаще всего дело в несовпадении переменных окружения между первым запуском (когда база инициализировалась с одними credentials) и текущим docker-compose.yml, где их поменяли.

PostgreSQL сохраняет пользователя и пароль в volume при первой инициализации и дальше их не обновляет, даже если вы поменяли POSTGRES_PASSWORD в compose-файле. Решение — либо вернуть старый пароль в переменные, либо (если данные не жалко) снести volume и поднять базу заново:

docker compose down
docker volume rm listmonk_listmonk-data
docker compose up -d

Важно: это удалит все подписки и историю кампаний. Перед любыми манипуляциями с volume делайте дамп:

docker exec listmonk-db-1 pg_dump -U listmonk listmonk > listmonk_backup_$(date +%F).sql

Восстановление из дампа:

cat listmonk_backup_2026-08-20.sql | docker exec -i listmonk-db-1 psql -U listmonk -d listmonk

Настройте регулярный бэкап через cron сразу после установки — база с подписчиками восстанавливается только из дампа, повторно собрать список контактов вы не сможете.

Веб-интерфейс отдаёт 502 Bad Gateway через nginx

Listmonk поднят, контейнер работает, но обратный прокси (nginx или Caddy) отдаёт 502 при заходе в админку.

Проверьте порядок запуска сервисов — если nginx стартует раньше, чем контейнер Listmonk успевает поднять внутренний веб-сервер (обычно на 9000 порту), первые несколько запросов будут падать. В systemd-юните или docker-compose добавьте depends_on с healthcheck:

services:
  listmonk:
    image: listmonk/listmonk:latest
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:9000/api/health"]
      interval: 10s
      timeout: 5s
      retries: 5
  nginx:
    depends_on:
      listmonk:
        condition: service_healthy

Проверьте также, что nginx проксирует на правильный порт и адрес — при работе через Docker-сеть это имя сервиса, а не localhost:

location / {
    proxy_pass http://listmonk:9000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Если используете отдельный процесс nginx на хосте (не в Docker), а Listmonk в контейнере с проброшенным портом — убедитесь, что порт 9000 действительно опубликован в docker-compose.yml (ports: - "127.0.0.1:9000:9000"), иначе nginx достучаться не сможет вообще.

Импорт подписчиков зависает или падает на большом CSV

При загрузке базы на 50-100 тысяч email через Import в интерфейсе процесс либо висит бесконечно "в процессе", либо обрывается с ошибкой памяти.

Веб-интерфейс Listmonk не рассчитан на импорт огромных файлов одним куском — он читает CSV построчно, но при плохом соединении или ограничении по времени в браузере запрос может оборваться раньше, чем импорт завершится на бэкенде. Разбейте файл на части по 10-20 тысяч строк:

split -l 20000 subscribers.csv chunk_ --numeric-suffixes=1 --additional-suffix=.csv

И импортируйте по очереди, дожидаясь завершения каждого куска в разделе Subscribers → Import.

Более надёжный путь для больших баз — импорт напрямую в PostgreSQL, минуя веб-интерфейс:

docker exec -i listmonk-db-1 psql -U listmonk -d listmonk -c "\copy subscribers(uuid, email, name, attribs, status) FROM '/tmp/subscribers.csv' WITH CSV HEADER"

Файл нужно предварительно скопировать внутрь контейнера (docker cp subscribers.csv listmonk-db-1:/tmp/) и убедиться, что колонка uuid заполнена (генерируется через gen_random_uuid() в PostgreSQL, если не хотите готовить UUID заранее).

Медленный сервер и нехватка ресурсов под нагрузкой рассылки

Отдельная категория проблем — не ошибка конфигурации, а банальная нехватка ресурсов. Listmonk сам по себе лёгкий (написан на Go), но PostgreSQL под большой базой подписчиков и активной рассылкой требует памяти для кэша и индексов. На VPS с 1-2 ГБ RAM при рассылке кампании на 50+ тысяч адресов сервер может начать свопить, что и создаёт часть описанных выше симптомов — таймауты, зависшие campaign, деградация SMTP-соединений.

Ориентировочные требования для комфортной работы:

Размер базы подписчиковRAMvCPUДиск
до 10 0002 ГБ1-220 ГБ SSD
10 000 - 100 0004 ГБ240 ГБ SSD
100 000+8 ГБ+480 ГБ+ SSD, отдельный диск под PostgreSQL

Если рассылки не разовые, а регулярные (email-маркетинг на постоянной основе), лучше сразу закладывать запас, а не апгрейдить сервер в панике посреди прогрева новой базы подписчиков. Установку самого Docker, на котором обычно и разворачивают Listmonk, разбирали отдельно в статье про установку Docker на Ubuntu 24.04, а базовую настройку собственного почтового сервера для связки с Listmonk — в статье про Postfix на VPS.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Listmonk сам отправляет письма или нужен внешний SMTP?

Listmonk — это движок кампаний и база подписчиков, но отправку он делегирует SMTP-серверу: своему Postfix на том же VPS или внешнему сервису вроде SendGrid, Mailgun, Amazon SES. Выбор влияет на репутацию IP и доставляемость.

Можно ли использовать Gmail как SMTP-relay для Listmonk?

Технически да, через приложение-пароль, но Gmail жёстко ограничивает объём исходящих писем (обычно около 500 в сутки для обычного аккаунта) и не подходит для регулярных рассылок на тысячи адресов — используйте его только для тестов.

Почему после установки Listmonk отправляет только тестовые письма, а кампании не уходят?

Обычно причина в отдельных, не синхронизированных настройках: тестовое письмо в Listmonk может использовать SMTP-профиль из UI, а кампании — конфиг из config.toml, если он не был обновлён после первичной настройки через интерфейс.

Сколько подписчиков потянет Listmonk на одном VPS?

База до 100-200 тысяч контактов на сервере с 4 ГБ RAM и SSD работает без проблем при разумных настройках PostgreSQL; для больших объёмов нужен более мощный сервер и вынос базы данных на отдельный диск.

Как узнать, что письма реально долетают, а не просто "отправлены" по логам Listmonk?

Ориентируйтесь на open rate и bounce rate в разделе статистики кампании, а также периодически проверяйте доставляемость через тестовые ящики на разных почтовых провайдерах — Listmonk фиксирует факт отправки SMTP-серверу, а не факт доставки получателю.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →