Skip to main content
Docs Apps Listmonk: Setup & Known Issues

Listmonk: Setup & Known Issues

Listmonk is a powerful self-hosted newsletter server. Deploying it via Coolify is straightforward, but a few things will catch you off guard.


API credentials — admin login does NOT work for REST API (v4+)

In Listmonk v4+, the admin UI credentials are separate from API auth. You must create a dedicated API user:

Settings → Users → New → API tab

This gives you a token to use as Bearer auth. Admin username/password return 403.


Opt-in confirmation email — customizing it

The opt-in email template is embedded in the binary, not on disk. To customize it, you must:

  1. Download the static files from the Listmonk GitHub release tarball
  2. Mount a custom static dir into the container
  3. Add --static-dir=/listmonk/static to the container command

In docker-compose.yml:

command: './listmonk --static-dir=/listmonk/static'
volumes:
  - '/data/coolify/listmonk-static/static:/listmonk/static:ro'

Template variable is {{ .OptinURL }} (with dot prefix).

⚠️ If you do this, do not redeploy Listmonk through the Coolify UI. Coolify will regenerate the compose file and overwrite your changes. To restart, SSH in and run:

cd /data/coolify/services/<SERVICE_UUID>/
docker compose up -d listmonk

Root URL and From address must be set manually

After first deploy, go to Settings → General:

  • Root URL: must be https://listmonk.yourdomain.com (not localhost:9000)
  • From address: Your Name <email@yourdomain.com>

Without this, opt-in emails won’t send and confirmation links will be broken.


SMTP test button is buggy

The built-in SMTP test button in Settings often fails even when SMTP is working fine. Test by sending a real campaign instead.


Bilingual campaigns

Store subscriber language as an attribute at signup time via the API:

{"attribs": {"lang": "de"}}

Use in templates:

{{ if eq .Subscriber.Attribs.lang "de" }}German content{{ else }}English content{{ end }}

Postgres healthcheck — variable substitution issue

If the healthcheck uses ${POSTGRES_DB}, it may fail because the variable is substituted as empty at the host level before being passed to Docker.

Safe version:

healthcheck:
  test: ["CMD-SHELL", "pg_isready"]

Zenith Stack

Want us to set up and manage your email infrastructure?

Learn more