Deployment guide

Listmonk

Overview

Listmonk is a popular open-source, self-hosted newsletter and mailing-list manager. You manage subscribers and lists, design and send campaigns and transactional email through your own SMTP server at high throughput, and track opens and clicks. It is a privacy-respecting alternative to hosted email platforms, and you can deploy it in your own virtual network.

This SecureAnyCloud image runs the Listmonk server, a single Go binary that serves both the admin app and the public pages, behind nginx as a reverse proxy. PostgreSQL is the datastore. The server listens on 127.0.0.1:9000 and is reached through nginx on port 80. The server and the database bind to the loopback interface only.

On the first boot of every VM, a one-shot service recreates an empty database, rotates the PostgreSQL password and initialises the Listmonk schema. It then creates a single super-administrator account with a per-VM password and writes the login to /root/listmonk-credentials.txt with mode 0600. No shared or default credentials ship in the image.

What you get:

  • Listmonk 6.1 server binary at /opt/listmonk/listmonk, with the admin app and public pages in one
  • nginx reverse proxy on :80 in front of the Listmonk server (bound to loopback :9000)
  • PostgreSQL datastore for subscribers, lists, campaigns and analytics, bound to loopback
  • Two dedicated Azure data disks, re-provisioned with every VM: the PostgreSQL data tier at /var/lib/postgresql, and the Listmonk binary, config and uploaded media at /opt/listmonk
  • A per-VM super-administrator login generated at first boot and kept in a root-only file, plus a per-VM database password
  • listmonk.service, postgresql.service and nginx.service as systemd units, enabled and active
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. Scale up for very large subscriber bases or high-throughput sending.

Configure the network security group (NSG) to allow inbound 22/tcp from your management network. Also allow 80/tcp (plus 443/tcp once you enable HTTPS) from the networks your team and subscribers use to reach Listmonk.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Listmonk by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Review the two dedicated data disks on the Disks tab, then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

Accept the Marketplace terms, create the VM and open port 80:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:listmonk-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name listmonk \
  --image sac1647283583153:listmonk-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name listmonk --port 80 --priority 1010

Step 3 - Connect to your VM

Connect over SSH as azureuser:

ssh azureuser@<vm-public-ip>

First-boot initialisation completes in under a minute. The credentials file is in place by the time SSH is ready.

Step 4 - Confirm the services are running

Check the three services and the open /health endpoint:

systemctl is-active listmonk.service postgresql.service nginx.service curl -fsS http://127.0.0.1/health

All three services report active, and the open health endpoint returns {"data":true}. This confirms that the full stack (nginx, the Listmonk server and PostgreSQL) is serving.

Both data tiers live on their own Azure data disks. Confirm the mounts:

findmnt -no SOURCE,SIZE,FSTYPE,TARGET /var/lib/postgresql
findmnt -no SOURCE,SIZE,FSTYPE,TARGET /opt/listmonk

Step 5 - Retrieve your administrator login

The super-administrator password is generated uniquely on the first boot of your VM and written to a root-only file. Read it:

sudo cat /root/listmonk-credentials.txt

The file contains the Listmonk admin URL, the administrator username and the password, plus the PostgreSQL login for the local database. To confirm that the admin API authenticates end to end, run this from the same session:

PASS=$(sudo grep '^listmonk.admin.pass=' /root/listmonk-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'no session -> HTTP %{http_code}\n' http://127.0.0.1/api/settings
CJ=$(mktemp)
curl -s -o /dev/null -c "$CJ" --data-urlencode "username=admin" --data-urlencode "password=$PASS" http://127.0.0.1/admin/login
curl -s -o /dev/null -w 'signed in -> HTTP %{http_code}\n' -b "$CJ" http://127.0.0.1/api/settings rm -f "$CJ"

The unauthenticated request is rejected. The same request, with a session signed in using the per-VM password, returns HTTP 200.

Step 6 - First sign-in

Open http://<vm-public-ip>/admin in a web browser. Listmonk shows its sign-in page. Enter the username admin and the password from /root/listmonk-credentials.txt, then select Login.

After you sign in, the dashboard shows subscribers, lists, campaign views and click analytics at a glance.

Step 7 - Configure your SMTP server

The image ships no email-sending credentials, so you bring your own SMTP server. Open Settings > SMTP and enable a server. Enter the host, port and credentials of your provider, such as Azure Communication Services, Amazon SES, SendGrid, Mailgun, a corporate relay or any SMTP endpoint.

Select Test connection to verify, then select Save. Campaigns do not send until SMTP is configured.

Step 8 - Create lists, import subscribers and send a campaign

Open Lists to create your first mailing list. A list can be public or private, with single or double opt-in. Import subscribers under Subscribers > Import (CSV), or let people subscribe through the public form pages that Listmonk serves on the same port.

Next, open Campaigns > New campaign and pick the list. Write your content as rich text, Markdown, raw HTML or a saved template. Send yourself a test from the Preview pane, then select Start to run the campaign. Opens, clicks and bounces are tracked per campaign under Analytics.

Security baseline

The image ships fully patched at capture time and keeps patching itself. Ubuntu's unattended-upgrades service is enabled, so security updates install automatically on your running VM. Verify the state at any time:

systemctl is-enabled unattended-upgrades grep -h . /etc/apt/apt.conf.d/20auto-upgrades
sudo ss -tlnp | grep -E ':(9000|5432) ' || true

The Listmonk server (:9000) and PostgreSQL (:5432) are bound to the loopback interface only. nginx on :80 is the single network-facing entry point.

Enabling HTTPS

For any production deployment, serve Listmonk over HTTPS so that logins and subscriber data cannot be intercepted. The image ships with nginx, which certbot can configure automatically.

The commands below assume a DNS record that points your fully qualified domain name at the VM's public IP address, and 443/tcp open in the NSG:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d news.your-domain.example \
  --non-interactive --agree-tos -m you@your-domain.example \
  --redirect

After certbot finishes, sign in and set Settings > General > Root URL to https://news.your-domain.example. Links in your emails (unsubscribe, tracking, archive) then use the HTTPS address.

Backup and maintenance

Listmonk keeps all of its state in PostgreSQL: subscribers, lists, campaigns, templates, settings and analytics. Any uploaded media is under /opt/listmonk/uploads. Back up both regularly:

sudo -u postgres pg_dump listmonk > <backup-dir>/listmonk-db-$(date +%F).sql
sudo tar czf <backup-dir>/listmonk-uploads-$(date +%F).tgz -C /opt/listmonk uploads

The database (/var/lib/postgresql) and the application directory (/opt/listmonk) are each on their own Azure data disk, so you can also take coordinated disk snapshots in Azure.

Keep the OS patched with sudo apt update && sudo apt upgrade. To upgrade Listmonk, replace /opt/listmonk/listmonk with a newer release, run ./listmonk --upgrade, and restart the service. See https://listmonk.app/docs/.

Support

This image is backed by 24/7 SecureAnyCloud support. Guaranteed response within 24 hours, one hour average for critical issues. Contact sales@secureanycloud.com for help with deployment, SMTP and deliverability configuration, upgrades, TLS termination and database administration.

For general Listmonk questions, consult the documentation at https://listmonk.app/docs/. Listmonk is a trademark of its respective owner; use here is nominative and does not imply affiliation or endorsement. All product and company names are trademarks or registered trademarks of their respective holders.

Deploy on Azure

Launch Listmonk on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure