← Back to Blog

Listmonk on a 1 GB VPS: Self-Hosted Newsletter Setup, Load Test and Cost vs Mailchimp

Published · by Leo Gashi, RS Computers

Newsletter Email Self-hosting

Listmonk is a free, open-source newsletter and mailing list manager that you host yourself, and it needs far less server than most people expect. In our lab on 18 October 2026, listmonk 6.2.0 and its PostgreSQL database used about 70 MB of RAM at idle, then sent 100,000 emails into a local test mail catcher in under two minutes on 2 vCPUs, or under three minutes on 1 vCPU with 1 GB of RAM.

The catch is delivery. Listmonk hands every message to an SMTP server (a server that passes mail on toward the inbox), so you relay through a service such as Amazon SES or run your own mail server. For a newsletter sent 4 times a month to 10,000 readers, that means a small server from our VPS hosting plans plus $4 to $7 of SES fees a month, against $110 a month for Mailchimp Essentials at list price.

Key facts, checked on 18 October 2026:

What is listmonk, and what does it do?

Listmonk is a web app for one-way mailing lists. You collect subscribers, write a campaign (one newsletter issue sent to one or more lists), and listmonk queues it and hands each copy to your mail server or relay. It ships as a 32 MB Docker image next to a 297 MB PostgreSQL 17 image, with a web admin on port 9000. For two-way conversations with customers, see our guide to self-hosted Chatwoot.

How much RAM and CPU does listmonk need? Our test on 1 GB and 2 GB

We installed listmonk with its official Docker Compose file in a Debian 13 container on our Amsterdam test server, sized like a VPS Micro (2 vCPU, 2 GB) and then a VPS Nano (1 vCPU, 1 GB), with swap off. The software was listmonk 6.2.0, PostgreSQL 17 and Docker 26.1.5.

All mail went to Mailpit 1.31.6, a mail catcher on the same machine, and the subscribers were fake addresses at example.com, a domain reserved for documentation. Not one email left the lab.

TestNano size: 1 vCPU, 1 GBMicro size: 2 vCPU, 2 GB
10,000 emails, default settings (10 workers x 10 per second)1 min 49 s, 92 per second1 min 45 s, 95 per second
100,000 emails, 20 workers x 100 per second2 min 53 s, 579 per second1 min 51 s, 904 per second
Peak RAM of listmonk and Postgres, 100,000 run85 MiB and 55 MiB88 MiB and 57 MiB
Peak RAM of the whole server, Docker and Mailpit included292 MB285 MB

In this test on 18 October 2026, listmonk used 31 MiB and Postgres 38 MiB at idle. A CSV file of 10,000 subscribers imported in 3.7 seconds, and 100,002 subscribers made a database of 56 MB.

At the default 100 per second, 10,000 readers get their copy in under two minutes. Above that, our test rig was the bottleneck: Mailpit used up to 143% of CPU on the 2 vCPU size, listmonk only 38%. With a real relay, its rate limit or your IP's reputation sets the pace. VPS vCPUs are shared and other labs ran on the host, so allow a few percent of variation.

Does listmonk send email itself? A relay or your own IP

No. Listmonk hands each message to an SMTP server and never delivers to your readers' mail servers itself. A relay or a mail server you run does that last step.

QuestionSMTP relay such as Amazon SESStraight from your VPS
Port 25Not needed; listmonk's SES preset connects on port 465Must be open outbound
Extra softwareNone on the serverA mail server that signs with DKIM, such as Postfix, mailcow or Stalwart
ReputationThe relay's IPs, with years of historyYour own IPv4, which starts with no history
Running cost$0.10 per 1,000 emails at SES (a la carte)Nothing beyond the server
BouncesReported to listmonk by webhooklistmonk reads a bounce mailbox over POP3

Relay through Amazon SES

A relay is a service that delivers your mail from its own servers and IP addresses. SES charges $0.10 per 1,000 emails a la carte plus $0.12 per GB of attachments; new accounts since 21 July 2026 start on the Essentials plan at $0.16 per 1,000 and may switch (SES pricing). They also start in the SES sandbox, limited to 200 messages a day to verified addresses, until AWS grants production access, with a first answer promised within 96 hours.

In listmonk, the Amazon SES link under Settings, SMTP fills in email-smtp.YOUR-REGION.amazonaws.com, port 465 and TLS; the EU SMTP endpoints include Frankfurt, Ireland, Paris and Stockholm. Keep workers times messages per second below your SES rate, and send bounces to /webhooks/service/ses through SNS as the bounce docs describe. We had no AWS account for this test, so these steps come from the documentation.

Send straight from your own VPS

Your own IP is cheaper per email, but a new IP starts with no reputation. You need:

On RS Computers servers, outbound port 25 is blocked on a new server and opened on request through Telegram; you set the PTR in the client area, or ask us there. Our guide to running a self-hosted mail server covers the DNS records, and the Stalwart vs mailcow comparison helps you pick the server.

Then warm up slowly with listmonk's sliding window (Settings, Performance), a cap on messages per period. Set to 1,000 per minute on our 100,000 list, the counter read 1,000 after 10, 30 and 55 seconds, 2,000 after 70 and 3,000 after 125, while the log said messages exceeded (1000) for the window. Mail your most engaged readers first, widen the window while bounces and complaints stay low, and keep the spam rate in Google Postmaster Tools under 0.3%, ideally under 0.1%.

One-click unsubscribe in listmonk: what Gmail and Yahoo ask for

One-click unsubscribe is the Unsubscribe button a mail app shows at the top of a message. Gmail asks bulk senders for it as defined in RFC 8058, and Yahoo recommends the same method: a List-Unsubscribe header with an HTTPS link, plus List-Unsubscribe-Post: List-Unsubscribe=One-Click. A click then sends a POST request to that link, with no login and no cookies. Listmonk adds both headers by default. This is a test message as Mailpit showed it:

# what Mailpit showed in the message headers (lab, Root URL set to http://127.0.0.1:9000)
List-Unsubscribe: <http://127.0.0.1:9000/subscription/29969b2b-e67a-4dcf-969e-fe2d85ebedf5/a7644723-b47c-410d-bc03-5598c31a2033>
List-Unsubscribe-Post: List-Unsubscribe=One-Click

Then we did what Gmail does when someone clicks the button:

# as root on the server: paste the address from your own List-Unsubscribe header
curl -s -o /dev/null -w "%{http_code}\n" -X POST -d "List-Unsubscribe=One-Click" "http://127.0.0.1:9000/subscription/CAMPAIGN-UUID/SUBSCRIBER-UUID"

It printed 200, and the reader's status on that list changed to unsubscribed at once. Two things are on you. Root URL under Settings, General must be your HTTPS address (the default is http://localhost:9000). And RFC 8058 requires a DKIM signature over both headers, so your relay or mail server must sign the message.

Listmonk vs Mailchimp vs Brevo: what a newsletter costs

As a self-hosted Mailchimp alternative, listmonk wins on price for plain newsletters. Example: a newsletter sent 4 times a month to 10,000 readers (40,000 emails), then to 50,000 (200,000 emails). Prices in US dollars are from the official pages of Mailchimp, Brevo and Amazon SES on 18 October 2026. Mailchimp charges by contacts, Brevo by emails sent.

Service10,000 readers, 40,000 emails a month50,000 readers, 200,000 emails a month
Mailchimp Essentials$110 a month list price, $55 for the first 12 months on the current 50% offer$385 a month list price, $192.50 for the first 12 months
Mailchimp Standard$135 a month list price, $67.50 for the first 12 months$450 a month list price, $225 for the first 12 months
BrevoStarter $46 a month, Standard $89 a month, billed monthlyStandard, 250,000 email tier: $249 a month (the calculator offers Starter only up to 100,000)
listmonk + Amazon SES$4.00 a la carte or $6.40 on SES Essentials, plus a VPS Nano$20 a la carte or $32 on SES Essentials, plus a VPS Nano or Micro
listmonk, sending from your own IPThe VPS onlyThe VPS only

The hosted tools give something for the money. Mailchimp's paid plans include automation flows, templates and 24/7 email and chat support, and both services look after delivery reputation. With listmonk, updates, SMTP and bounces are your job. Our server prices are on the VPS plans page.

Which plan and which city for listmonk

Your situationPlanCityWhy
Newsletter only, sent through a relay, readers across EuropeVPS Nano: 1 vCPU, 1 GB, 20 GB NVMe, 1 Gb/sAmsterdamIn our test, 100,000 emails in under 3 minutes below 300 MB of RAM; about 7 ms from Frankfurt and London
Newsletter plus a website, readers in Kosovo and the BalkansVPS Micro: 2 vCPU, 2 GB, 40 GB NVMe, 1 Gb/sPrishtinaRoom for a second app and its database; Skopje is about 3 ms away on our own network
Readers in Ireland and the UKVPS Nano, or VPS Micro with a website next to itDublinAn EU country near Irish and British readers
listmonk plus your own Stalwart mail serverVPS Micro, or VPS Mini: 4 vCPU, 4 GB, 80 GB NVMe, 1 Gb/sNearest your readersStalwart's docs size it at about 1 GB for 5 to 10 users
listmonk plus mailcow on one serverVDS Small: 4 dedicated vCPU, 8 GB, 240 GB NVMe, 10 Gb/sNearest your readersmailcow's docs ask for at least 6 GiB of RAM plus 1 GiB of swap

Disk is rarely the limit: the two images take about 330 MB, and our 100,002-subscriber database was 56 MB. Every plan has NVMe storage, unmetered traffic and its own IPv4 and IPv6 address. VPS plans have shared vCPUs, VDS plans dedicated ones, and you can upgrade later from the client area with a short reboot.

All three cities run our KVM servers. Amsterdam and Dublin keep data inside the EU. Prishtina suits a list aimed at Kosovo and the Balkans, under Kosovo's Law No. 06/L-082, which follows the GDPR. Kosovo has no EU adequacy decision, so for EU readers' data there, our Data Processing Agreement names standard contractual clauses.

The city barely changes delivery, but the sign-up page loads faster near your readers: in our ping.pe measurement of 6 October 2026, Frankfurt and London reached our Amsterdam server in about 7 ms, and Vienna reached our Prishtina server in 18.6 ms. See the Amsterdam VPS, VPS Ireland and VPS Kosovo pages for each city; availability by city is on the plans page.

How to install listmonk with Docker Compose on Debian 13

You need a fresh Debian 13 server with root access over SSH, a domain such as newsletter.example.com whose A record points at the server, and your relay's SMTP details. New to servers? Read our Debian 13 hardening guide first.

Step 1: Firewall and Docker

# as root
apt update && apt install -y docker.io docker-compose curl openssl ufw
ufw allow 22/tcp
ufw allow 80,443/tcp
ufw --force enable
ufw status
docker compose version

The rules come before enable, so your SSH session stays open. ufw status lists 22/tcp and 80,443/tcp as ALLOW, and the last line prints Docker Compose version 2.26.1-4.

Step 2: The official compose file, with three changes

# as root
mkdir -p /opt/listmonk && cd /opt/listmonk
curl -LO https://github.com/knadh/listmonk/raw/v6.2.0/docker-compose.yml
sed -i "s#listmonk/listmonk:latest#listmonk/listmonk:v6.2.0#; s#\"9000:9000\"#\"127.0.0.1:9000:9000\"#; s#&db-password listmonk#\&db-password $(openssl rand -hex 16)#" docker-compose.yml
chmod 600 docker-compose.yml
grep -n "image:\|9000:9000\|db-password" docker-compose.yml

The sed line pins the version, publishes the admin on 127.0.0.1 only and swaps the database password listmonk for a random one. The port matters most: Docker's firewall documentation warns that ports Docker publishes skip ufw rules, so "9000:9000" would put your login page online whatever ufw says. The grep shows listmonk/listmonk:v6.2.0, "127.0.0.1:9000:9000" and a 32-character password.

Step 3: Start listmonk and create the admin

# as root, in /opt/listmonk
ADMINPASS=$(openssl rand -base64 18); echo "admin password: $ADMINPASS"
LISTMONK_ADMIN_USER=admin LISTMONK_ADMIN_PASSWORD="$ADMINPASS" docker compose up -d
sleep 15
docker compose ps
docker compose logs app | grep -E "superadmin|http server"

Write the password down. The two variables create the first admin account and only count on the first start, which took 8 seconds in our lab. docker compose ps shows listmonk_app as Up on 127.0.0.1:9000->9000/tcp and listmonk_db as Up and (healthy), and the log lines read creating superadmin user 'admin' and http server started on [::]:9000.

Step 4: HTTPS with Caddy

# as root
apt install -y caddy
cat > /etc/caddy/Caddyfile <<'EOF'
newsletter.example.com {
	reverse_proxy 127.0.0.1:9000
}
EOF
caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
systemctl reload caddy

Use your own domain. caddy validate ends with Valid configuration. On reload, Caddy requests a free certificate from Let's Encrypt for that name, as long as the A record points at the server and ports 80 and 443 are open (Caddy automatic HTTPS docs). We had no public domain in the lab, so that certificate step is from the docs; we tested the proxy itself with an http:// site address, and the login page and the subscription form both answered 200. Prefer Nginx or Traefik? Our reverse proxy comparison covers both.

Step 5: Settings and your first list

Log in at https://newsletter.example.com/admin. Under Settings, General, set Root URL to your HTTPS address and the From address; under Settings, SMTP, add your relay or mail server. To import readers, open Subscribers, Import, pick a list and upload a CSV whose first line is email,name,attributes (attributes is optional JSON). Mark people as confirmed only if they really opted in.

Dry run: send the first campaign to Mailpit, not to people

Before the first real send, catch everything locally. This override file adds Mailpit next to listmonk:

# as root: create /opt/listmonk/docker-compose.override.yml with this content
services:
  mailpit:
    image: axllent/mailpit:v1.31.6
    container_name: mailpit
    restart: unless-stopped
    ports:
      - "127.0.0.1:8025:8025"
    networks:
      - listmonk

Run docker compose up -d in /opt/listmonk, then point Settings, SMTP at host mailpit, port 1025, auth protocol none and TLS none. Make a test list of fake readers:

# as root: 10,000 test subscribers at the reserved example.com domain
awk 'BEGIN{print "email,name"; for(i=1;i<=10000;i++) printf "test%05d@example.com,Test User %d\n", i, i}' > test-subscribers.csv
head -3 test-subscribers.csv

It prints the header and test00001@example.com,Test User 1. Import the file into a new private list, then create and start a campaign for it.

To see the result, open an SSH tunnel from your computer with ssh -L 8025:127.0.0.1:8025 root@YOUR_SERVER_IP, browse to http://localhost:8025 and check names, links and the List-Unsubscribe-Post header. Then delete the test list and remove Mailpit:

# as root, in /opt/listmonk
rm docker-compose.override.yml
docker compose up -d --remove-orphans
docker compose ps

Only listmonk_app and listmonk_db are left. Switch Settings, SMTP back to your real relay or mail server.

Listmonk Docker problems we hit, and the fixes

What you seeWhyFix
The docker compose logs check prints nothing right after up -dThe containers are still starting (on a first start, Postgres reports "health: starting"), so listmonk has not logged yetWait; that is why step 3 has sleep 15 and the upgrade block sleep 10
services.db.ports must be a listDeleting only the port line under the db service leaves an empty ports: keyLeave it as shipped: the official file already binds Postgres to 127.0.0.1:5432, out of reach from outside
Unsubscribe and "view in browser" links point to localhost or 127.0.0.1listmonk builds its unsubscribe and view links from Root URLSet Root URL to your HTTPS address under Settings, General before the first send

Listmonk and GDPR: what changes when the list lives on your server

Every address, consent record and click count sits in your own PostgreSQL database, in the city you picked, and no newsletter company keeps a copy. Listmonk 6.2.0's privacy defaults help: individual tracking is off, so opens and clicks are counted without tying them to a person; subscribers may export and wipe their own data; and the opt-in IP is not recorded unless you turn that on.

In our lab, a sign-up on the public form for the default double opt-in list triggered a "Confirm subscription" email, and the address stayed unconfirmed until that link was clicked.

A relay adds one party. With SES that is Amazon, a US company, even in an EU region; our CLOUD Act checklist explains why that can matter. Either way you remain the controller of the list, with a privacy notice to write.

How to back up and upgrade listmonk

Listmonk ships security fixes in normal releases; v6.0.0, v6.1.0 and v6.2.0 each carried some. Dump the database before every upgrade:

# as root, in /opt/listmonk
docker compose exec -T db pg_dump -U listmonk listmonk | gzip > /root/listmonk-$(date +%F).sql.gz
ls -lh /root/listmonk-*.sql.gz

Our 100,000-subscriber database came to 3.4 MB compressed, in 2 seconds. Copy the file off the server. To upgrade, read the release notes, change the tag and pull; the official compose file runs listmonk's database upgrade on every start.

# as root, in /opt/listmonk: put the new release tag in place of vX.Y.Z
sed -i "s#listmonk/listmonk:v6.2.0#listmonk/listmonk:vX.Y.Z#" docker-compose.yml
docker compose pull
docker compose up -d
sleep 10
docker compose logs app | grep -i "upgrade\|migration"

We tested this path from 6.1.0 to 6.2.0: the log said running migration v6.2.0, then upgrade complete.

When listmonk is the wrong tool

Listmonk has no visual automation flows, so welcome series or abandoned-cart emails need another tool or your own code calling its API; Mailchimp's Standard plan includes up to 200 flows. Bloggers who want paid members should look at Ghost, which has newsletters built in (see our Ghost on a VPS vs Ghost(Pro) comparison).

And if nobody on your team will update a Linux server, a hosted service is the honest answer, unless we set listmonk up for you, quoted per job on Telegram or by email.

Frequently asked questions

Is listmonk free?

Yes. Listmonk is open-source software under the AGPL-3.0 licence, with no fee per subscriber or per email. You pay for the server and, if you use one, the relay: on 18 October 2026, Amazon SES listed $0.10 per 1,000 emails a la carte.

How much RAM does listmonk need?

Very little. In our test on 18 October 2026, listmonk 6.2.0 used 31 MiB and PostgreSQL 38 MiB at idle, and the whole server stayed under 300 MB while sending 100,000 emails. A 1 vCPU, 1 GB VPS is enough for listmonk alone.

Can listmonk send email without an SMTP server?

No. Listmonk hands every message to an SMTP server and never delivers to recipients' mail servers itself. Use a relay such as Amazon SES, or your own Postfix, Stalwart or mailcow server with outbound port 25, a PTR record, and SPF, DKIM and DMARC.

Is listmonk a good Mailchimp alternative?

For newsletters and broadcast campaigns, yes. On 18 October 2026, Mailchimp Essentials for 10,000 contacts listed at $110 a month, while listmonk plus Amazon SES for 40,000 emails costs $4 to $7 a month plus a small VPS. Listmonk has no automation flows, and you look after updates and delivery yourself.

How fast can listmonk send?

The default settings allow up to 100 emails per second; our 10,000-email test ran at 95. With 20 workers at 100 per second each, listmonk 6.2.0 sent 100,000 emails into a local test server at about 900 per second on 2 vCPUs and 580 on 1 vCPU. Real speed depends on your relay or your IP's reputation.

Does listmonk support double opt-in and one-click unsubscribe?

Yes. Lists can be single or double opt-in, and a double opt-in sign-up gets a confirmation email first. Listmonk adds the List-Unsubscribe and List-Unsubscribe-Post headers by default; in our test, a one-click POST to that link unsubscribed the reader at once.

Start small, test with Mailpit, then send

For most newsletters, listmonk on a VPS Nano (1 vCPU, 1 GB) with a relay is the cheapest setup that still looks professional, and a VPS Micro (2 vCPU, 2 GB) leaves room for your website next to it. Do the Mailpit dry run, set Root URL to HTTPS, and mail only people who asked for it. Pick a size and a city on our VPS plans page, and if you want port 25 opened, a PTR set or listmonk installed for you, message us on Telegram.

← All articles

Chat on Telegram