Listmonk on Ubuntu 24.04 on Azure User Guide
Overview
Listmonk is the popular open source, self-hosted newsletter and mailing-list manager — manage subscribers and lists, design and send campaigns and transactional email through your own SMTP at high throughput, and track opens and clicks — a privacy-respecting alternative to hosted email platforms, deployable in your own virtual network. The cloudimg image runs the Listmonk server (a single Go binary serving both the admin app and public pages) behind nginx as a reverse proxy, with PostgreSQL as 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 deployed VM, a one-shot service recreates an empty database, rotates the PostgreSQL password, initialises the Listmonk schema, and creates a single super-administrator account with a per-VM password. The login is written to /root/listmonk-credentials.txt with mode 0600. No shared or default credentials ship in the image. Backed by 24/7 cloudimg support.
What is included:
- Listmonk 6.1 server binary at
/opt/listmonk/listmonk(admin app + public pages in one) - nginx reverse proxy on
:80in front of the Listmonk server (bound to loopback:9000) - PostgreSQL datastore (subscribers, lists, campaigns, analytics), bound to loopback
- Two dedicated Azure data disks, re-provisioned with every VM: the PostgreSQL data tier at
/var/lib/postgresqland the Listmonk binary, config and uploaded media at/opt/listmonk - Per-VM super-administrator login generated at first boot, in a root-only file; per-VM database password
listmonk.service,postgresql.service+nginx.serviceas systemd units, enabled and active- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + 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. NSG inbound: allow 22/tcp from your management network and 80/tcp (plus 443/tcp once you enable HTTPS) from the networks your team and subscribers will reach Listmonk on.
Step 1 — Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Listmonk by cloudimg, and select Create. On Basics 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 Review + create → Create.
Step 2 — Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name listmonk \
--image <marketplace-image-urn> \
--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
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
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} — proof the full stack (nginx, the Listmonk server and PostgreSQL) is serving. Both data tiers live on their own Azure data disks:
findmnt -no SOURCE,SIZE,FSTYPE,TARGET /var/lib/postgresql
findmnt -no SOURCE,SIZE,FSTYPE,TARGET /opt/listmonk

Service status, the open /health endpoint, and the two dedicated data disks.
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:
sudo cat /root/listmonk-credentials.txt
The file contains the Listmonk admin URL, the administrator username (admin) and the password, plus the PostgreSQL login for the local database. You can confirm the admin API authenticates end to end 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 and the same request with a session signed in using the per-VM password returns HTTP 200.

The root-only credentials file and an admin API round-trip — rejected without a session, HTTP 200 with the per-VM password.
Step 6 — First sign-in
Open a web browser and navigate to http://<vm-public-ip>/admin. Listmonk presents its sign-in page. Enter the username admin and the password from /root/listmonk-credentials.txt, then select Login.

The Listmonk admin sign-in, served on first boot with a per-VM super-administrator login.
After signing in you land on the dashboard — subscribers, lists, campaign views and click analytics at a glance.

The Listmonk dashboard.
Step 7 — Configure your SMTP server (bring your own)
The image ships no email-sending credentials. Open Settings → SMTP, enable a server, and enter the host, port and credentials of your provider — Azure Communication Services, Amazon SES, SendGrid, Mailgun, a corporate relay, or any SMTP endpoint. Use Test connection to verify, then Save. Until SMTP is configured, campaigns will not send.
Step 8 — Create lists, import subscribers and send a campaign
Open Lists to create your first mailing list (public or private, single or double opt-in). Import subscribers under Subscribers → Import (CSV), or let people subscribe through the public form pages Listmonk serves on the same port.

Mailing lists in Listmonk — opt-in type, subscriber counts and tags.
Then open Campaigns → New campaign, pick the list, write your content (rich text, Markdown, raw HTML or a saved template), send yourself a test from the Preview pane, and Start 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 are installed 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.

Automatic security updates enabled, and the application tiers bound to loopback only.
Enabling HTTPS
For any production deployment serve Listmonk over HTTPS so logins and subscriber data cannot be intercepted. The image ships with nginx, which certbot can configure automatically. The following assumes a DNS record pointing 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 so links in your emails (unsubscribe, tracking, archive) use the HTTPS address.
Backup and maintenance
Listmonk keeps all of its state — subscribers, lists, campaigns, templates, settings and analytics — in PostgreSQL, and any uploaded media under /opt/listmonk/uploads. Back both up 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
Because the database (/var/lib/postgresql) and the application directory (/opt/listmonk) are each on their own Azure data disk, 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 cloudimg support. Guaranteed response within 24 hours, one hour average for critical issues. Contact support@cloudimg.co.uk 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.