What is Listmonk and who is it for ?

Listmonk is a small-ish project that provides a tool quick & easy to setup and manage for those who want to do mailing on a large scale and need go get it done today:

  • the container is ready in 2 seconds when deploying from scratch

  • the UI is as simple and direct as it gets

  • it comes with ready to use templates out of the box

    In this article, we will cover an alternative to the setup suggested by the official documentation and have a look at the different functionnalities available.

  • Official website: Listmonk

  • Documentation: Listmonk documentation

  • Docker images: Listmonk images

  • Git repository: Listmon's Github repository

    Deploying a container-based Listmonk instance

    Why not follow the official documentation ?

    On both the official website and the Listmonk image repository, the instructions are to use a ready-made docker-compose.yml file in conjunction with an accompanying shell script depending on wether you want to deploy a demo or a production site.

    This docker-compose.yml deploys both the Listmonk app and a PostgreSQL database: it's actually one off the selling arguments that Listmonk is "self-hosted".

    I didn't want to have an extra container for DB hosting considering I've already set up a dedicated DB server and Listmonk will actually be off most of the time as I only need to send a newsletter once a month. So I really wanted to minimise the ressource usage to a minimu.

    When deploying in a more professional environment with a more robust infrastructure, I would recommend following the official instructions

    Pre-requisite for this deployment method

  • A PostgreSQL dedicated database and user

    CREATE USER listmonkadmin with password 'Averypassword4Listmonk!';
    CREATE DATABASE listmonk with owner listmonkadmin ;
    GRANT ALL PRIVILEGES ON DATABASE listmonk TO listmonkadmin;
  • Ubuntu 22.04 server up to date with docker-compose installed

    sudo apt update -y
    sudo apt upgrade -y
    sudo apt install -y docker-compose
  • Ubuntu 22.04 server must be able to connect to the dedicated database:

    psql -h <DBHOSTIP> -U keycloakadmin -p 5432 dbserver
  • Ubuntu 22.04 server must be able to pull docker images from Listmonk Docker image registry

  • Set up a dedicated sub-domain.
    For our example listmonk.nicksopenworld.com

  • Optional: a Traefik service to manage HTTPS certificates
    Keycloak can manage HTTPS if provided with certificate files but having Traefik or an equivalent makes it so much easier.

  • the listmonk setup shell script, available on my fork of the project

    Files and folders configuration & setup

For this demonstration, a sub-directory "listmonk" has been created in /opt containing:

File docker-compose.yml File at the root of the directory containing our running image configuration (see below)
File config.toml File containing the basic Listmonk parameters
File listmonksetup.sh File containing the basic Listmonk parameters


version: "3.9"
    image: listmonk/listmonk:v2.5.1
    container_name: listmonk
    command: [sh, -c, "yes | ./listmonk --install"]
    restart: unless-stopped
      - "9050:9050"
      - TZ=Etc/UTC
      - LISTMONK_db__database=listmonkdb
      - LISTMONK_db__user=listmonkdbadmin
      - LISTMONK_db__password='Pas$word4ListmonkDB'
      - /opt/listmonk/config.toml:/listmonk/config.toml
      - /opt/listmonk/uploads:/listmonk/uploads:rw


As can be seen in the docker-compose.yml file, this file is on the container host.
It defines some of the parameters for Listmonk such as Admin UI credentials and database connection.

# Interface and port where the app will run its webserver.  The default value
# of localhost will only listen to connections from the current machine. To
# listen on all interfaces use ''. To listen on the default web address
# port, use port 80 (this will require running with elevated permissions).
address = ""

# BasicAuth authentication for the admin dashboard. This will eventually
# be replaced with a better multi-user, role-based authentication system.
# IMPORTANT: Leave both values empty to disable authentication on admin
# only where an external authentication is already setup.
admin_username = "papaemeritus"
admin_password = "IfUhaveg0hst$"

# Database.
host = ""
port = 5432
user = "listmonkdbadmin"
password = "Pas$word4ListmonkDB"
database = "listmonkdb"
ssl_mode = "disable"
max_open = 25
max_idle = 25
max_lifetime = "300s"

A few values must be matched between docker-compose.yml and config.toml:

docker-compose.yml config.toml
ports port
LISTMONK_db__database database
LISTMONK_db__user user
LISTMONK_db__password password


As explained, the standard deployment didn't match my usage.

This script will:

  • deploy a Listmonk Docker container with the "--install" command
  • wait 2 seconds for the DB configuration finish
  • check for specific strings in the Listmonk Docker container logs
  • if the logs are as expected, the running container will be forcefully deleted
  • a backup copye of the docker-compose.yml file will be done
  • the command instruction will be commented out of the docker-compose.yml file
  • a new Listmonk Docker container will be relaunched

    The script can be found on my fork of the Git repository.


sudo docker-compose up -d
sleep 2

# counts occurences of specific strings in log 
IntallLaunched=$(sudo docker logs listmonk | grep 'config' | wc -l)
IntallFinished=$(sudo docker logs listmonk | grep 'run the program and access the dashboard' | wc -l)


echo IntallLaunched: $IntallLaunched
echo IntallFinished: $IntallFinished

while [ $CleanUp -eq 0 ]; do
        IntallLaunchedretest=$(sudo docker logs listmonk | grep 'config' | wc -l)
        IntallFinishedretest=$(sudo docker logs listmonk | grep 'run the program and access the dashboard' | wc -l)

        sleep 2
        echo IntallLaunched: $IntallLaunched
        echo IntallFinished: $IntallFinished

        if [ "$IntallLaunchedretest" -gt 1 ] || [ "$IntallFinishedretest" -gt 1 ]; then
                sudo rm -f listmonk

                        # update docker-compose.yml to not force install
                        sudo cp docker-compose.yml /home/ubuntu/
                        echo "Backup copy of docker compose file to /home/ubuntu/"

                        sudo cp docker-compose.yml /tmp/dc.yml
                # Comment out install command
                        sudo sed -i 's/command:/#command:/g' /tmp/dc.yml
                        sudo mv /tmp/dc.yml $DOCKERCOMPOSEDIRECTORY/docker-compose.yml
                        echo "Docker compose file updated"

                        # Relaunch Listmonk
                        sudo docker-compose up -d

                        # Increment cleanup value to get out of loop

Actual deployment

Simply execute the listmonksetup.sh script:

bash listmonksetup.sh

A working & funcional Listmonk instance will be made available after a few seconds:

If the command line is not commented out in the docker-compose.yml, the DB setup will loop as can be seen in the Listmonk container logs:

The error message:
first time installation
IMPORTANT: This will wipe existing listmonk tables and types in the DB 'listmonk'
continue (y/N)? 2023/11/23 21:47:39 install.go:179: setup complete
2023/11/23 21:47:39 install.go:180: run the program and access the dashboard at
2023/11/23 21:47:41 main.go:102: v2.5.1 (a6a2b69 2023-08-15T15:49:28Z, linux/amd64)
2023/11/23 21:47:41 init.go:145: reading config: config.toml
2023/11/23 21:47:41 init.go:273: connecting to db:

First connection to your Listmonk instance

Go to the URL for your Listmonk instance and log-in using the credentials set in the config.toml file:

Unfortunately, there can only be 1 access account.
There are ideas to improve on this situation as can be seen in open issues such as Multi User support #543 or even in the config.toml.sample
provided in the Github repo:

# BasicAuth authentication for the admin dashboard. This will eventually
# be replaced with a better multi-user, role-based authentication system.
# IMPORTANT: Leave both values empty to disable authentication on admin
# only where an external authentication is already setup.

On a more positive note, the login page can be customized as we will see below.

Essential configuration

General settings

In this tab, you must set the root URL for your instance: although it is not needed to access the platform once deployed, it will be used to build URLs for login pages or to redirect users for opt-in/out actions.
Leaving the values to the default "localhost:9000" will only create errors later.

Similarly, this is where you set the default "FROM" email and set the recipient(s) for Admin-level notifications such as the end of a campaign:

You can also set your own images for favicons and logo.

Media management

Using local storage

It requires your docker-compose.yml file to have in the volumes declarations:

  - /opt/listmonk/uploads:/listmonk/uploads:rw

It means that any media (image, attachment, ...) uploaded to Listmonk will be saved on the Docker container's host in the folder you have set ("/opt/listmonk/uploads" in our example).

Using Amazon S3

If you use Amazon AWS services and you want to separate media storage from the container host or you are uploading a very large number of media files requiring a larger storage space, S3 can be an interresting alternative.

The files uploaded through Listmonk can then be accessed through the AWS S3 portal or CLI:

File filtering

A filter is available to set a white liste of file extensions to allow.
Note that a filter * is set allowing all formats.


This is a standard configuration pannel but critical to Listmonk as it allows emails to be sent from multiple sources:

  • Amazon SES
  • Gmail
  • Mailgun
  • Mailjet
  • Postmark
  • Sendgrid
  • Standard SMTP server

    Selecting one of the option will pre-fill some of the fields and change available options but the configuration is basically always the same.

    Note: you can add multiple SMTP configurations but only 1 can be used at a time.

    This essentially allows you to quickly switch between SMTP providers if you need to.
    Switching between providers can be done due to the "FROM" email you want to use, to be updated in the general settings, or simply due to the volume of emails to be sent in which case you might also want to check the Performance tab:

    This menu allows you to manage concurrent sending threads and batch sizes to avoid application overload.


    If you want to push your message through a messaging system or using SMS instead of emails, you can configure the endpoing connexions that can then be selected when configuring a campaign.

    Only 1 messenger can be used per campaign so if you want to push the same message through multiple communication channels, you will have to clone the campain.

    Logs & maintenance

    Useful in the initial setup, logs are accessible in the dedicated menu and you can

    You will be able to find information regarding configuration errors but also campaign status.

    And of course, if after doing some debugging you want to clean up your platform, go to Maintenance:


    With this short article you should now have a working platform that can send emails or messages with nice logos and/or attachments.

    Email lists, campaigns and user management will be detailed separately in articles published in the Listmonk category.

0 0 votes
Article Rating
Notify of
Inline Feedbacks
View all comments
Would love your thoughts, please comment.x