← All articles
a computer screen with a program running on it

Self-Hosting Listmonk: A Newsletter and Mailing List Manager That Respects Your Budget

Communication 2026-02-14 · 8 min read email newsletter mailing-list marketing
By Selfhosted Guides Editorial TeamSelf-hosting practitioners covering open source software, home lab infrastructure, and data sovereignty.

Newsletter platforms have a pricing problem. Mailchimp charges per subscriber. ConvertKit charges per subscriber. Buttondown charges per subscriber. At 10,000 subscribers, you're paying $80-150/month for the privilege of sending emails — emails that cost fractions of a cent each to actually deliver.

Photo by Lukas on Unsplash

Listmonk is a self-hosted newsletter and mailing list manager that eliminates the per-subscriber tax. It's a single Go binary backed by PostgreSQL, and it handles everything: subscriber management, campaign creation, templating, analytics, bounce processing, and list segmentation. You pay for SMTP delivery (Amazon SES charges $0.10 per 1,000 emails) and your server. That's it.

Listmonk dashboard showing campaign analytics and subscriber statistics

Why Listmonk

The self-hosted newsletter space is surprisingly thin. Most options are either abandoned PHP projects from 2012 or overcomplicated enterprise solutions. Listmonk stands out because:

What Listmonk is not

Listmonk is a mailing list manager, not a marketing automation platform. It doesn't have:

If you need Mailchimp-level marketing automation, Listmonk isn't the right choice. But if you need to send newsletters to a list of subscribers reliably and cheaply, it's excellent.

Cost Comparison

The economics of self-hosted newsletters are compelling:

Subscribers Mailchimp ConvertKit Listmonk + SES
1,000 $30/mo $29/mo ~$1/mo
5,000 $75/mo $79/mo ~$2/mo
10,000 $115/mo $119/mo ~$4/mo
50,000 $350/mo $379/mo ~$15/mo
100,000 $700/mo Custom ~$25/mo

Listmonk costs assume Amazon SES at $0.10/1,000 emails, 4 campaigns/month, plus a $5/mo VPS. Actual costs vary based on sending volume and hosting.

The savings compound quickly. At 50,000 subscribers, you save over $4,000/year. That's real money.

Self-Hosting Listmonk: Setup

Server requirements

Listmonk is remarkably efficient:

For reference, Listmonk can manage 1 million subscribers on a $10/month VPS. The bottleneck is almost always your SMTP provider's sending rate, not Listmonk itself.

Docker Compose setup

version: "3.8"

services:
  listmonk:
    container_name: listmonk
    image: listmonk/listmonk:latest
    ports:
      - "9000:9000"
    environment:
      TZ: "America/Los_Angeles"
    volumes:
      - ./config.toml:/listmonk/config.toml
    depends_on:
      database:
        condition: service_healthy
    restart: always
    command: ["./listmonk", "--config", "/listmonk/config.toml"]

  database:
    container_name: listmonk_db
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: listmonk
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: listmonk
    volumes:
      - pgdata:/var/lib/postgresql/data
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U listmonk"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

Create config.toml:

[app]
address = "0.0.0.0:9000"
admin_username = "admin"
admin_password = "your-secure-admin-password"

[db]
host = "database"
port = 5432
user = "listmonk"
password = "your-database-password"
database = "listmonk"
ssl_mode = "disable"
max_open = 25
max_idle = 25
max_lifetime = "300s"

Initialize the database

Before starting Listmonk for the first time, run the database setup:

docker compose run --rm listmonk ./listmonk --install --config /listmonk/config.toml

Then start everything:

docker compose up -d

Access the admin panel at http://your-server:9000. Log in with the credentials from config.toml.

Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.

Configuring SMTP

Listmonk needs an SMTP provider to actually send emails. You have several options.

Amazon SES (recommended for volume)

SES is the cheapest option for high-volume sending. After setting up your SES account and verifying your domain:

In the Listmonk admin panel, go to Settings > SMTP and add:

Setting Value
Host email-smtp.us-east-1.amazonaws.com
Port 465
Auth protocol LOGIN
Username Your SES SMTP username
Password Your SES SMTP password
TLS SSL/TLS
Max connections 10
Max message retries 3
Idle timeout 15s
Wait timeout 5s

Fastmail / Mailgun / Postmark

Any SMTP provider works. Postmark and Mailgun are good choices if you want better deliverability tools than SES provides. They cost more ($1-1.50 per 1,000 emails) but include dedicated IPs and reputation monitoring.

Self-hosted SMTP

You can run your own mail server (Stalwart, Postfix, etc.), but email deliverability is hard. Unless you have experience with SPF, DKIM, DMARC, IP warm-up, and feedback loops, use a managed SMTP provider. Your newsletters will land in spam otherwise.

Setting Up Your First Newsletter

1. Configure your domain

Go to Settings > General and set:

2. Create a mailing list

Go to Lists and create your first list:

3. Build a subscription form

Listmonk generates embeddable HTML forms. Go to Lists > Your List > Subscription Form to get the HTML:

<form method="post" action="https://newsletter.yourdomain.com/subscription/form">
    <input type="hidden" name="nonce" />
    <input type="email" name="email" required placeholder="Your email" />
    <input type="hidden" name="l" value="YOUR_LIST_UUID" />
    <button type="submit">Subscribe</button>
</form>

Embed this on your website. Listmonk handles the confirmation email and unsubscribe links automatically.

4. Create an email template

Go to Campaigns > Templates. Listmonk uses Go templates. A basic responsive template:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        body { font-family: -apple-system, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { border-bottom: 2px solid #333; padding-bottom: 10px; margin-bottom: 20px; }
        .footer { border-top: 1px solid #ccc; padding-top: 10px; margin-top: 20px; font-size: 12px; color: #666; }
    </style>
</head>
<body>
    <div class="header">
        <h1>{{ .Campaign.Name }}</h1>
    </div>

    {{ .Body }}

    <div class="footer">
        <p>You're receiving this because you subscribed to our newsletter.</p>
        <p><a href="{{ .UnsubscribeURL }}">Unsubscribe</a></p>
    </div>
</body>
</html>

5. Send a campaign

Go to Campaigns > New:

  1. Enter a subject line
  2. Select the target list(s)
  3. Write your content (markdown or HTML)
  4. Preview and test (send a test email to yourself)
  5. Schedule or send immediately

Listmonk processes the queue and sends emails at your configured rate. You can watch progress in real time on the campaign page.

Analytics and Tracking

Listmonk tracks:

Go to Campaigns > [Your Campaign] to see analytics after sending. Listmonk also provides aggregate statistics across all campaigns.

Bounce processing

Configure bounce processing to automatically handle failed deliveries:

Set up a bounce mailbox or use SES/Mailgun's bounce webhook to feed bounce data back to Listmonk automatically.

Listmonk subscriber management interface with list segmentation

Subscriber Management

Importing subscribers

Listmonk accepts CSV imports with flexible field mapping:

email,name,attributes
[email protected],Alice Smith,"{""plan"": ""pro"", ""signup_date"": ""2024-01-15""}"
[email protected],Bob Jones,"{""plan"": ""free""}"

The attributes column accepts JSON, which you can use for segmentation later.

Segmentation with SQL

Listmonk's killer feature for power users: SQL-based subscriber queries. When creating a campaign, you can target subscribers with raw SQL:

-- Subscribers who signed up in the last 30 days
subscribers.created_at > NOW() - INTERVAL '30 days'

-- Subscribers with a specific attribute
subscribers.attribs->>'plan' = 'pro'

-- Subscribers on list A but not list B
subscribers.id IN (
    SELECT subscriber_id FROM subscriber_lists WHERE list_id = 1
) AND subscribers.id NOT IN (
    SELECT subscriber_id FROM subscriber_lists WHERE list_id = 2
)

This is more powerful than any tag-based segmentation system. If you're comfortable with SQL, you can slice your audience any way you want.

API Integration

Listmonk has a comprehensive REST API. Common use cases:

Add a subscriber programmatically

curl -u admin:password -X POST \
  'https://newsletter.yourdomain.com/api/subscribers' \
  -H 'Content-Type: application/json' \
  -d '{
    "email": "[email protected]",
    "name": "New User",
    "status": "enabled",
    "lists": [1],
    "attribs": {"source": "website-signup"}
  }'

Trigger a transactional email

curl -u admin:password -X POST \
  'https://newsletter.yourdomain.com/api/tx' \
  -H 'Content-Type: application/json' \
  -d '{
    "subscriber_email": "[email protected]",
    "template_id": 2,
    "data": {"order_id": "12345", "item": "Widget Pro"},
    "content_type": "html"
  }'

This makes Listmonk useful beyond newsletters — you can use it for transactional emails (order confirmations, password resets) if you don't want a separate service.

Reverse Proxy Setup

Caddy:

newsletter.yourdomain.com {
    reverse_proxy localhost:9000
}

Nginx:

server {
    server_name newsletter.yourdomain.com;

    location / {
        proxy_pass http://localhost: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;
    }
}

Backup Strategy

# Database backup (contains all subscribers, campaigns, templates)
docker exec -t listmonk_db pg_dumpall -c -U listmonk > listmonk-backup.sql

# Restore
cat listmonk-backup.sql | docker exec -i listmonk_db psql -U listmonk

The database is the only critical piece. There are no uploaded files to worry about (email images should be hosted externally or inline).

Deliverability Tips

Self-hosting email sending means you're responsible for deliverability. A few essentials:

  1. Set up SPF, DKIM, and DMARC for your sending domain. Without these, your emails land in spam.
  2. Warm up your sending IP — start by sending to small batches (100/day) and gradually increase over 2-4 weeks.
  3. Use double opt-in — this prevents spam complaints and ensures clean lists.
  4. Include an unsubscribe link — Listmonk does this automatically, but make sure it's visible.
  5. Monitor bounce rates — if your bounce rate exceeds 5%, SMTP providers will throttle or ban you.
  6. Don't buy email lists — this should be obvious, but sending to purchased lists will destroy your sender reputation.
  7. Use a dedicated subdomain — send from [email protected] rather than [email protected] to isolate your newsletter reputation from your primary domain.

Honest Trade-offs

Listmonk is great if you:

Consider Mailchimp/ConvertKit instead if you:

Consider Mailtrain or Mautic instead if you:

The bottom line: Listmonk is the best self-hosted newsletter tool for people who just want to send emails to a list of subscribers without paying per-subscriber fees. It's lean, fast, and does exactly what it says. If you outgrow Mailchimp's free tier and don't need its marketing automation features, Listmonk pays for itself in the first month.

Get free weekly tips in your inbox. Subscribe to Self-Hosted Weekly