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.