platform independence

Self-Hosted Email Newsletters with Listmonk

Listmonk is an open-source newsletter and mailing list manager — a self-hosted alternative to Mailchimp, ConvertKit, and similar services. It is written in Go, runs as a single binary backed by a PostgreSQL database, and handles subscriber management, campaign creation, list segmentation, and send scheduling. For publishers committed to owning their infrastructure, Listmonk is the most capable self-hosted option in the category.

What Listmonk Provides

Listmonk handles the management and orchestration layer of email newsletters: subscriber lists, subscriber data, campaign drafting, template management, tracking, and scheduling. It does not handle email delivery directly — it connects to a transactional email provider (Amazon SES, Mailgun, Postmark, SendGrid) and routes outgoing mail through that service.

This architecture means you own everything except the final-mile email delivery, and you choose and pay for that delivery separately. At any meaningful sending volume, this is significantly cheaper than SaaS newsletter platforms priced on subscriber count.

Hosting Requirements

Listmonk requires:

  • A Linux server (VPS from Hetzner, DigitalOcean, Vultr, etc.) — a $5/month instance handles most small to mid-size lists
  • PostgreSQL 9.6 or newer
  • A transactional email provider with SMTP access

Installation

The fastest path is Docker Compose. Create a docker-compose.yml:

version: "3.7"
services:
  db:
    image: postgres:15-alpine
    ports:
      - "9432:5432"
    environment:
      POSTGRES_PASSWORD: listmonk
      POSTGRES_USER: listmonk
      POSTGRES_DB: listmonk
    volumes:
      - ./data/postgres:/var/lib/postgresql/data

  app:
    image: listmonk/listmonk:latest
    ports:
      - "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: listmonk
      LISTMONK_db__database: listmonk
    depends_on:
      - db
    command: [sh, -c, "yes | ./listmonk --install && ./listmonk"]

Start the stack:

docker compose up -d

Listmonk is available at http://your-server-ip:9000. The default login is admin / listmonk — change the password immediately.

For a production deployment, put Nginx in front of Listmonk and terminate SSL there. An example Nginx configuration:

server {
    listen 443 ssl;
    server_name mail.yoursite.com;
    
    ssl_certificate /etc/letsencrypt/live/mail.yoursite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mail.yoursite.com/privkey.pem;

    location / {
        proxy_pass http://localhost:9000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Use Certbot with Let’s Encrypt for the SSL certificate.

Configuring an SMTP Provider

Navigate to Settings → SMTP in the Listmonk admin. Configure with your transactional email provider credentials.

Amazon SES (lowest cost at scale):

  • Host: email-smtp.us-east-1.amazonaws.com (region-specific)
  • Port: 587
  • Username/Password: SES SMTP credentials (created separately from IAM credentials in the SES console)
  • From address: a verified SES identity

Mailgun (simpler setup, higher per-email cost):

  • Host: smtp.mailgun.org
  • Port: 587
  • Username: your Mailgun SMTP username
  • Password: your Mailgun SMTP password

At low volumes (under 10,000 emails/month), Mailgun’s free tier and SendGrid’s free tier both work well. At higher volumes, Amazon SES at $0.10 per 1,000 emails is hard to beat on cost.

Managing Subscribers

Listmonk supports multiple lists — segment subscribers by interest, by publication, by tier, or by any other dimension. Subscribers can belong to multiple lists simultaneously.

Import subscribers via CSV under Subscribers → Import. The CSV requires an email column; name and attributes are optional. Listmonk handles deduplication.

Subscription forms can be embedded on your site or pointed to Listmonk’s subscription API. The API endpoint for adding a subscriber:

POST https://mail.yoursite.com/subscription
Content-Type: application/x-www-form-urlencoded

[email protected]&l[]=LIST_UUID&name=Reader+Name

For a static site (Hugo, Eleventy), use a form pointing at this endpoint or wrap it in a Netlify Form or Cloudflare Worker that validates input before forwarding to Listmonk.

Double opt-in is configurable per list. When enabled, new subscribers receive a confirmation email and are added to the list only after confirming. Required for GDPR compliance in most European jurisdictions.

Creating and Sending Campaigns

Campaigns are email sends to one or more lists. Create a campaign under Campaigns → New Campaign:

  • Name: Internal reference label
  • Subject: The email subject line
  • From: The sender name and address
  • Lists: Which subscriber lists receive this campaign
  • Template: The HTML template the campaign body is inserted into
  • Content: The campaign body, writeable in Markdown or raw HTML

Listmonk provides a basic default template. Create custom templates under Templates that include your publication’s header, footer, and branding.

Campaigns can be sent immediately or scheduled for a future date and time. The scheduler handles queuing and throttling — important for maintaining sender reputation with large lists.

Tracking

Listmonk tracks open rates (via a tracking pixel) and click rates (by rewriting links to route through Listmonk’s tracking proxy). Both tracking types are configurable and can be disabled for privacy-respecting sending.

The dashboard displays per-campaign open and click statistics. Subscriber-level engagement data is accessible in the subscriber detail view.

Transactional Email

Beyond broadcast newsletters, Listmonk can send transactional messages — confirmation emails, subscription acknowledgements, custom triggered messages — through its API:

curl -X POST 'https://mail.yoursite.com/api/tx' \
  -H 'Content-Type: application/json' \
  -u 'api_user:api_password' \
  -d '{
    "subscriber_email": "[email protected]",
    "template_id": 2,
    "data": { "name": "Jane" }
  }'

This covers the confirmation and welcome email use cases that a newsletter workflow requires.

The Cost Picture

Running Listmonk on a $5/month VPS with Amazon SES for delivery costs approximately $5 (server) + $1 (SES for 10,000 emails) = $6/month for a list of 10,000 subscribers with monthly sends. Mailchimp’s equivalent plan runs $100–150/month. The savings at scale are substantial.

The tradeoff is operational responsibility: you manage the server, the database, software updates, and backup schedules. For publishers with the technical capacity to handle this, Listmonk is a compelling option. For those who prefer not to manage infrastructure, a commercial provider is the right call despite the cost difference.