Self-host Listmonk newsletter trên VPS thay Mailchimp

Chia sẻ bài viết

Mục lục
TL;DR
  • Listmonk = newsletter platform open source, single Go binary, UI sạch, đủ feature.
  • Self-host trên VPS 2-4 GB RAM, kết nối SMTP relay (SES, Postmark, Brevo, Mailcow) để gửi mail.
  • Subscriber list, segment SQL query, template HTML, campaign A/B test, analytics open/click.
  • Mailchimp 50k subscriber = 350 USD/tháng. Listmonk + SES = ~50 USD/tháng cho cùng volume.
  • Phù hợp newsletter B2C 1k-500k subscriber. Trên 1M cân nhắc Sendy, Mailwhale, hoặc enterprise.

Founder build SaaS có blog newsletter 30k subscriber, gửi 4 email/tháng. Mailchimp tier 30k là 230 USD/tháng = 2760 USD/năm. ConvertKit cũng tương đương. Trong khi đó SMTP cost gửi 120k email/tháng qua Amazon SES chỉ 12 USD/tháng. Tự host Listmonk trên VPS 2 GB là 5 USD/tháng. Tổng 17 USD/tháng cho cùng workload Mailchimp 230 USD. Tiết kiệm 13x.

Bài này hướng dẫn deploy Listmonk, kết nối SMTP relay (SES recommended), import subscriber từ Mailchimp, tạo template + campaign đầu tiên, set deliverability chuẩn. Bonus: cách scale lên 500k subscriber mà vẫn dưới 100 USD/tháng tổng cost.

Listmonk là gì? Khác Sendy / Mautic?

ToolCostStackPhù hợp
ListmonkFreeGo + PostgresNewsletter modern, 1k-500k sub
Sendy69 USD 1 lầnPHP + MySQLNewsletter cổ điển, hợp Amazon SES
MauticFreePHP + MySQLMarketing automation full, nặng
Mailcoach359 USD 1 lầnLaravelĐẹp, Laravel team

Listmonk nhẹ nhất (single binary Go), UI hiện đại, dev active. Sendy đáng đồng tiền 69 USD nếu thích PHP. Mautic mạnh automation nhưng học cong.

Yêu cầu VPS

SubscriberRAMvCPUSSD
< 10k2 GB1 vCPU20 GB
10k-100k4 GB2 vCPU40 GB
100k-500k8 GB4 vCPU80 GB

Listmonk + Postgres ăn ít RAM. Hot path gửi mail là CPU + network. Băng thông VPS tốt giúp gửi nhanh, nhưng quan trọng nhất là SMTP relay (SES) có concurrency cao.

Deploy Listmonk

curl -fsSL https://get.docker.com | sh

cd /srv
sudo mkdir listmonk && cd listmonk

# Tải compose mẫu chính thức
sudo curl -LO https://github.com/knadh/listmonk/raw/master/docker-compose.yml

# Sửa password Postgres trong file compose
sudo nano docker-compose.yml

# Init schema lần đầu
sudo docker compose run --rm app ./listmonk --install

# Start
sudo docker compose up -d

# Mặc định listen 9000
curl http://127.0.0.1:9000

Đặt Caddy reverse proxy:

news.your-domain.com {
  reverse_proxy 127.0.0.1:9000
  encode gzip
}

Vào news.your-domain.com, set admin password đầu tiên. Vào Settings -> General set "From Name" + "From Email".

Cấu hình SMTP relay (Amazon SES)

  1. Đăng ký AWS SES (cần verify domain + key, mất 1-2 ngày approve out-of-sandbox).
  2. Tạo SMTP credentials trong AWS Console -> SES -> SMTP Settings.
  3. Vào Listmonk -> Settings -> SMTP -> Add Server:
    • Host: email-smtp.us-east-1.amazonaws.com
    • Port: 587 (TLS)
    • Username: SES SMTP username
    • Password: SES SMTP password
    • Max connection: 10 (SES limit)
    • Max messages per connection: 100
  4. Save, click "Send test mail" để verify.

Tương tự với Postmark, Brevo, Mailgun, hoặc Mailcow self-host. Postmark nhỉnh hơn về deliverability cho transactional, SES rẻ nhất cho volume lớn.

Subscriber và List

  • List: nhóm subscriber. Vd "Newsletter weekly", "Product update", "Beta tester".
  • Public hoặc Private list. Public cho phép tự subscribe qua form.
  • Mỗi subscriber có thể vào nhiều list cùng lúc.
  • Subscriber có status: enabled, disabled, blocklisted.
  • Attribute custom: name, country, plan, signup_date.

Import từ Mailchimp

  1. Trên Mailchimp: Audience -> Export audience -> download CSV.
  2. Trên Listmonk: Subscribers -> Import -> upload CSV.
  3. Map column: email, name, attributes.
  4. Chọn list đích.
  5. Submit. Listmonk import 10k subscriber trong vài phút.

Bị bounce/spam complain trong Mailchimp được đánh dấu? Listmonk có cột "status" trong CSV, set "disabled" hoặc "blocklisted" để không gửi đến những subscriber problematic.

Template HTML

Listmonk dùng template Go text/template. Vào Templates -> New, paste HTML responsive. Variable: {{ .Subscriber.Name }}, {{ .Subscriber.Email }}, {{ TrackLink "https://..." .Campaign.UUID .Subscriber.UUID }} để track click.

Có thể dùng template MJML render ra HTML responsive đẹp cho mobile, rồi paste vào Listmonk. Một số cộng đồng share template miễn phí Github.

Tạo campaign đầu tiên

  1. Campaigns -> New.
  2. Subject: "Newsletter T5 - 5 update mới của sản phẩm".
  3. Content type: Rich (WYSIWYG) hoặc HTML, hoặc Markdown.
  4. Chọn template, edit nội dung.
  5. Chọn list target.
  6. Preview render với 1 subscriber mẫu.
  7. Send test mail tới mình + 2 đồng nghiệp duyệt.
  8. Schedule send: ngay hoặc giờ cụ thể.
  9. Submit. Listmonk queue và gửi từ từ theo concurrency setting.

Deliverability

  • SPF, DKIM, DMARC trên domain bạn. SES auto setup DKIM khi verify domain.
  • Dedicated IP nếu volume > 50k/tháng để bảo vệ reputation.
  • Warm up IP mới: gửi từ 100/ngày, 500/ngày, 1k/ngày, tăng dần qua 4 tuần.
  • Footer email phải có unsubscribe link (Listmonk auto inject).
  • Monitor bounce + complaint rate trong SES Console, dưới 5% bounce + 0.1% complaint.
  • Clean list định kỳ: remove subscriber không mở mail 6 tháng (sunset policy).

Analytics

Listmonk track:

  • Sent / Delivered / Bounced / Failed count.
  • Open rate: dùng 1x1 pixel tracking (có thể tắt vì privacy).
  • Click rate: link redirect qua Listmonk track.
  • Unsubscribe rate.
  • Per-link click count.

Dashboard hiện chart đẹp. Export CSV để phân tích deeper trong BigQuery / Metabase nếu cần.

Cost ước tính 30k subscriber, 4 email/tháng

MụcCost
VPS 2 GB~500k VND/tháng
SES gửi 120k email/tháng (0.10 USD/1k email)~12 USD/tháng
Domain~250k VND/năm
Tổng~17 USD/tháng (~400k VND)

So sánh: Mailchimp 30k tier 230 USD/tháng, ConvertKit ~199 USD/tháng. Tiết kiệm ~85% so với SaaS.

Bẫy thường gặp

Triệu chứngCách fix
SES trong sandbox chỉ gửi verified emailRequest out-of-sandbox, mất 1-2 ngày approve
Bounce rate caoValidate email format lúc subscribe, scrub list định kỳ
Email vào spam GmailCheck SPF/DKIM/DMARC chuẩn, warm IP đúng, content không spammy
Campaign gửi chậmTăng SMTP concurrency, parallel connection
Postgres connection pool fullTăng max_connections, hoặc dùng pgbouncer
Cloud VPS cho vibe coder

VPS chạy Listmonk + Postgres cho newsletter 50k subscriber

Cloud VPS TND sẵn AlmaLinux 9, Ubuntu 22/24, Debian 12/13. SSD CEPH, snapshot 1-click, backup hằng ngày, network 200Mbps trong nước. Gói 2-4GB RAM đủ cho Listmonk + DB, kết hợp SES/Postmark cho SMTP relay deliverability cao.

Xem 8 cấu hình Cloud VPS →

FAQ

Listmonk có gửi mail trực tiếp không hay phải qua SMTP relay?

Listmonk có thể gửi trực tiếp qua port 25, nhưng KHÔNG khuyến nghị: IP VPS thường bị blacklist, deliverability thấp. Bắt buộc dùng SMTP relay (SES, Postmark, Brevo, hoặc Mailcow self-host) để mail vào inbox Gmail. Listmonk hỗ trợ nhiều SMTP cùng lúc, round-robin.

Có thể tạo double opt-in confirmation không?

Có. Cấu hình List Type = "Double opt-in" thay vì Single. Khi user subscribe, Listmonk gửi mail confirm có link verify, chỉ khi click mới active vào list. Giảm spam complaint, tăng deliverability dài hạn. Bắt buộc nếu serve EU (GDPR).

Có hỗ trợ automation drip campaign không?

Có cơ bản. Campaign type "Optin" cho welcome series khi user mới subscribe. Tuy nhiên automation phức tạp (multi-step, condition branch, wait days) thì Listmonk yếu hơn Mautic/ActiveCampaign. Cho 90% case newsletter thuần thì đủ. Cần automation sâu thì cân nhắc Mautic.

Form subscribe nhúng vào website thế nào?

Listmonk có form public sẵn tại /subscription/form?l=LIST_UUID. Hoặc tạo form HTML custom POST đến endpoint API. Embed iframe hoặc copy snippet HTML vào WordPress/Next.js/landing page bằng đoạn JS nhỏ. Cấu hình CORS Listmonk để allow domain bạn.

So với Buttondown / Beehiiv khác gì?

Buttondown và Beehiiv là SaaS newsletter platform polished, có editorial features (web archive, subscription tier paid, AI assist viết). Đắt hơn Listmonk + SES (~30-50 USD/tháng cho 10k sub). Self-host Listmonk thiếu các tính năng editor đẹp, bù lại 100% control + rẻ. Chọn theo workflow: writer-focused thì Beehiiv, dev-focused thì Listmonk.