Listmonk в Docker Compose: готовый файл
Mailchimp и его аналоги упираются в тариф уже на паре тысяч подписчиков, а данные о вашей аудитории лежат на чужих серверах. Listmonk — open-source платформа для email-рассылок, которая разворачивается на своём VPS за 10 минут через Docker Compose и не берёт денег за количество контактов. Ниже — рабочий compose-файл, настройка SMTP и типичные грабли при первом запуске.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что такое Listmonk и кому он подходит
Listmonk написан на Go и распространяется одним бинарником плюс база PostgreSQL — никакого PHP-зоопарка и лишних зависимостей. Из коробки есть: сегментация подписчиков по спискам и полям, конструктор кампаний с HTML-шаблонами, статистика открытий и кликов, публичные формы подписки, поддержка double opt-in, импорт CSV, API.
Кому это реально подходит:
- у вас своя база подписчиков (интернет-магазин, SaaS, медиа) и вы платите Mailchimp/SendGrid/Unisender за каждую тысячу контактов;
- вам нужна полная видимость данных — экспорт, SQL-запросы к своей же базе, никакой блокировки аккаунта по решению чужой поддержки;
- вы готовы отдельно настроить доставляемость (SPF/DKIM/DMARC, репутация домена) — Listmonk формирует и отправляет письма, но саму доставку делает внешний SMTP-релей.
Это не «поставил и забыл» решение: Listmonk — инструмент рассылки, а не служба доставки с готовой репутацией IP, как у крупных ESP. Если у вас разовая рассылка на 500 адресов раз в квартал — возможно, проще и дешевле остаться на бесплатном тарифе стороннего сервиса. Если рассылка — часть регулярного процесса (дайджест, транзакционные письма, апдейты для клиентов), self-hosted вариант окупается быстро.
Готовый docker-compose.yml
Минимальная рабочая связка — контейнер приложения и PostgreSQL с healthcheck, чтобы app не стартовал раньше готовности базы:
services:
db:
image: postgres:16-alpine
container_name: listmonk-db
restart: unless-stopped
environment:
POSTGRES_USER: listmonk
POSTGRES_PASSWORD: change_me_strong_password
POSTGRES_DB: listmonk
volumes:
- listmonk-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U listmonk -d listmonk"]
interval: 10s
timeout: 5s
retries: 6
app:
image: listmonk/listmonk:latest
container_name: listmonk-app
restart: unless-stopped
ports:
- "127.0.0.1:9000:9000"
environment:
LISTMONK_APP__ADDRESS: 0.0.0.0:9000
LISTMONK_DB__HOST: db
LISTMONK_DB__PORT: 5432
LISTMONK_DB__USER: listmonk
LISTMONK_DB__PASSWORD: change_me_strong_password
LISTMONK_DB__DATABASE: listmonk
LISTMONK_DB__SSL_MODE: disable
TZ: Europe/Moscow
depends_on:
db:
condition: service_healthy
volumes:
- listmonk-uploads:/listmonk/uploads
volumes:
listmonk-db-data:
listmonk-uploads:
Обратите внимание на две вещи. Во-первых, порт 9000 привязан только к 127.0.0.1 — наружу приложение смотреть не должно, доступ будет через reverse-proxy с HTTPS (раздел ниже). Во-вторых, пароль change_me_strong_password нужно заменить в обоих местах (у сервиса db и у app) на реальный — используйте openssl rand -base64 24, чтобы сгенерировать случайный.
Каталог с файлом создайте отдельно, например /opt/listmonk/, и положите compose-файл туда же — так проще управлять бэкапами и обновлениями.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПервый запуск и создание администратора
Поднимайте сервисы по очереди, чтобы база успела инициализироваться:
docker compose up -d db
docker compose ps # дождитесь статуса healthy у db
docker compose up -d app
docker compose logs -f app
В логах Listmonk сообщит, что схема базы применена и сервер слушает 0.0.0.0:9000. В актуальных версиях (3.x) первый заход в веб-интерфейс автоматически предлагает мастер настройки: там вы задаёте email и пароль супер-администратора прямо в браузере. Если вместо мастера видите ошибку про отсутствующую схему — накатите её вручную:
docker compose run --rm app ./listmonk --install --yes
Флаг --yes пропускает интерактивные вопросы и применяет схему без подтверждений — используйте его только при первой установке на пустую базу, не на боевых данных. После установки зайдите на http://127.0.0.1:9000 (через SSH-туннель, пока нет домена) или на адрес, который вы настроите через reverse-proxy.
Проверить версию образа, если что-то работает не так, как описано в документации:
docker compose exec app ./listmonk --version
SMTP: как подключить отправку писем
Сам Listmonk писем не «доставляет» — он формирует их и передаёт через SMTP-сервер, который вы укажете в админке: Settings → SMTP. Понадобится:
- хост и порт (587 со STARTTLS — самый совместимый вариант, 465 — SMTPS);
- логин и пароль (или app-пароль, если провайдер требует отдельный для SMTP);
- отправитель — email в домене, для которого вы настроили SPF, DKIM и DMARC.
Если письма планируются в заметном объёме, лучше не использовать основной корпоративный домен напрямую — заведите поддомен вида mail.example.com специально под рассылки, чтобы проблемы с репутацией не задели основную почту компании. Настройке самого сервера под такие задачи посвящена отдельная статья — пошаговая настройка VPS под почтовую рассылку с нуля.
Listmonk умеет работать сразу с несколькими исходящими SMTP-серверами и распределять нагрузку между ними — это полезно, когда у одного релея есть суточный лимit писем. Настраивается в том же разделе кнопкой «Add SMTP» — добавьте второй сервер, и приложение будет чередовать отправку.
Обязательно отправьте тестовое письмо кнопкой «Send test email» прямо из настроек SMTP до того, как запускать кампанию на всю базу — так вы поймаете опечатку в пароле или неверный порт, а не после отправки 5000 писем с ошибкой.
Домен, HTTPS и reverse-proxy
Открывать порт 9000 наружу без TLS — плохая идея: в админку заходят с паролем, а по HTTP он уйдёт в открытом виде. Проще всего поставить перед Listmonk Caddy — он сам получит сертификат Let's Encrypt:
listmonk.example.com {
reverse_proxy 127.0.0.1:9000
}
Один файл Caddyfile с этим блоком и команда docker compose up -d (если Caddy тоже в контейнере) — сертификат появится автоматически при первом запросе. Подробный разбор установки — в статье Caddy с авто-SSL на Ubuntu 24.04: пошаговая установка.
Что нужно сделать до этого шага:
- Создать A-запись домена (или поддомена) на IP сервера.
- Открыть 80 и 443 порты в firewall (
ufw allow 80,443/tcp), сам Listmonk на 9000 наружу не открывать. - Проверить, что DNS уже разрешился (
dig +short listmonk.example.com), иначе Let's Encrypt не выдаст сертификат.
Если вы поднимаете Listmonk не в одиночку, а в составе более крупного стека сервисов на том же сервере, пригодится общий подход к продакшен-конфигурации Docker Compose — он разобран в статье Docker Compose для продакшена на Ubuntu 24.04.
Списки, импорт подписчиков и обслуживание
Работа с базой в Listmonk строится вокруг списков (lists) — у каждого подписчика может быть несколько списков и статус подписки (unconfirmed / confirmed / unsubscribed). Импорт CSV делается через Subscribers → Import: файл с колонками email,name,attributes заливается напрямую, дубликаты по email обновляются, а не дублируются.
Если аудитория перенесена из другого сервиса (Mailchimp, Unisender), обратите внимание на согласие на рассылку — при self-hosted решении никто не проверяет это за вас, и ответственность за спам-жалобы и соблюдение 152-ФЗ/GDPR целиком на вас. Практичный вариант — включить double opt-in для новых форм подписки и не заливать «холодные» базы без явного согласия.
Кампания создаётся в разделе Campaigns: выбираете список, шаблон (HTML или простой текст с переменными вида {{ .Subscriber.Name }}), тестируете на своём адресе и запускаете либо сразу, либо по расписанию.
Регулярное обслуживание — два пункта, которые легко забыть:
Бэкап базы — вся ценность в PostgreSQL, бэкапить нужно именно её:
docker compose exec db pg_dump -U listmonk listmonk | gzip > listmonk_$(date +%F).sql.gz
Вынесите команду в cron и храните копии вне сервера (S3-совместимое хранилище или другой сервер). Подробнее о самой базе — в статье как установить и настроить PostgreSQL на VPS.
Обновление — перед апдейтом обязательно снимите бэкап, только потом:
docker compose pull app
docker compose up -d app
При смене мажорной версии Listmonk сам применяет миграции схемы при старте и подробно пишет об этом в логах — следите за docker compose logs -f app во время первого запуска после апдейта.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли использовать Яндекс.Почту или Mail.ru как SMTP-релей для Listmonk?
Технически да — оба провайдера дают SMTP с логином и паролем приложения, но у них жёсткие суточные лимиты на исходящие письма (рассчитаны на личную переписку, не на рассылки), и при превышении аккаунт может получить блок. Для регулярных кампаний нужен отдельный транзакционный SMTP-провайдер или собственный настроенный сервер.
Сколько ресурсов сервера нужно под Listmonk?
Само приложение лёгкое — на 1 vCPU / 1-2 ГБ RAM оно спокойно тянет базу в десятки тысяч подписчиков. Основной расход ресурсов при скачках нагрузки — PostgreSQL во время массовой отправки и генерации отчётов; для баз в сотни тысяч контактов стоит взять 2 vCPU / 4 ГБ с запасом.
Чем это отличается от рассылки напрямую через свой Postfix без панели?
Postfix — это только транспорт. Listmonk добавляет над ним управление списками, сегментацию, шаблоны, статистику открытий/кликов, отписку по ссылке (обязательное требование антиспам-политик) и веб-интерфейс для не-технических сотрудников — Postfix или другой SMTP-релей при этом всё равно нужен как исполнитель отправки.
Как перенести подписчиков и историю кампаний с Mailchimp?
Экспортируйте подписчиков в CSV из Mailchimp (Audience → Export) и импортируйте тем же файлом в Listmonk через Subscribers → Import. Историю писем и статистику старых кампаний перенести нельзя — Mailchimp не отдаёт эти данные в машиночитаемом виде, только новые кампании будут считаться в Listmonk.
Нужен ли отдельный домен под рассылки или можно использовать основной?
Использовать можно, но рискованно: если получатели начнут массово жаловаться на спам или письма попадут в блэклист, репутация основного домена (и, соответственно, вся остальная корпоративная почта) пострадает вместе с рассылкой. Поддомен изолирует этот риск.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →