listmonk is a standalone, self-hosted, newsletter and mailing list manager. It is fast, feature-rich, and packed into a single binary. It uses a PostgreSQL database as its data store. Visit [listmonk.app](https://listmonk.app) ## Installation ### Docker The latest image is available on DockerHub at `listmonk/listmonk:latest`. Use the sample [docker-compose.yml](https://github.com/knadh/listmonk/blob/master/docker-compose.yml) to run listmonk and Postgres DB with docker-compose as follows: #### Demo ```bash mkdir listmonk-demo sh -c "$(curl -sSL https://raw.githubusercontent.com/knadh/listmonk/master/install-demo.sh)" ``` The demo does not persist Postgres after the containers are removed. DO NOT use this demo setup in production. #### Production - `docker-compose up db` to run the Postgres DB. - `docker-compose run --rm app ./listmonk --install` to setup the DB (or `--upgrade` to upgrade an existing DB) - Run `docker-compose up app` and visit `http://localhost:9000`. More information on [docs](https://listmonk.app/docs). __________________ ### Binary #### download an prepare config file - Download the [latest release](https://github.com/knadh/listmonk/releases) and extract the listmonk binary. - `./listmonk --new-config` to generate config.toml. Then, edit the file. #### prerequisites Debian: system user and PostgreSQL - install PostgreSQL `apt install postgresql` - create system user with config.toml data for the database: `adduser listmonk` - create the postgreSQL database, the user and grant permissions: `su - postgres` and then acces de PostgreSQL console `psql` ``` postgres=# CREATE DATABASE listmonk; postgres=# CREATE USER listmonk WITH PASSWORD 'listmonk'; postgres=# GRANT ALL PRIVILEGES ON DATABASE listmonk TO listmonk; ``` #### proceed to install - `./listmonk --install` to setup the Postgres DB (or `--upgrade` to upgrade an existing DB. Upgrades are idempotent and running them multiple times have no side effects). - Run `./listmonk` and visit `http://localhost:9000`. #### after install, fine tunning oncen checked it works, stop the process. - move the files to where you like most, usually `/opt/listmonk/` or inside `/var/www/html/` - change ownership of the files to `www-data` or whatever user you have assigned the webserver `chown -R www-data:www-data listmonk` - run listmonk as a service, create `/etc/systemd/system/listmonk.service` with: ``` [Unit] Description=Listmonk server After=syslog.target network.target postgressql.target [Service] Type=simple # the user and group executing the service User=www-data Group=www-data # the directory where you have listmonk WorkingDirectory=/var/www/html/listmonk # the file to execute ExecStart=/var/www/html/listmonk/listmonk Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` - enable and run the service `sudo systemctl enable listmonk.service` and then `sudo systemctl start listmonk.service` #### upgrade (the binary install) - Download the [latest release](https://github.com/knadh/listmonk/releases) and extract the listmonk binary. - stop `listmonk` or it's service if run as so `sudo systemctl stop listmonk.service` - move the binary to executing destination. - change ownership of the files to `www-data` or whatever user you have assigned the webserver `chown -R www-data:www-data listmonk` - `./listmonk --upgrade` to upgrade an existing DB. (Upgrades are idempotent and running them multiple times have no side effects). - start again the binary or the service `sudo systemctl start listmonk.service` __________________ ## Postgres ### connect to db ```bash su postres - ``` as user `postgres` execute ```bash psql ``` inside postgres use these commands - `\l` to list databases - `\c ` to use a database - `\dt` to list relations/tables ### See the lists ```postgres SELECT * from lists; ``` will show something like ```postgres id | uuid | name | type | optin | tags | created_at | updated_at ----+--------------------------------------+------------------------------------------------------------+---------+--------+--------+-------------------------------+------------------------------- 1 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Lista de prueba | private | single | {test} | 2021-05-19 15:33:08.503002+02 | 2021-05-27 12:05:28.201633+02 3 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Agendas | public | single | | 2021-06-03 17:18:58.398437+02 | 2021-06-03 17:42:13.446523+02 4 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Prensa | public | single | | 2021-06-03 17:19:11.233554+02 | 2021-07-13 18:04:58.078138+02 5 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Instituciones, Festivales, etc | public | single | | 2021-06-03 17:19:38.707663+02 | 2021-07-13 18:41:34.764095+02 6 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Newsletter | public | single | | 2021-06-03 17:19:51.514315+02 | 2021-07-13 18:44:15.855554+02 7 | xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | Antiguas socias y colaboradoras | public | single | | 2021-06-03 17:20:15.807685+02 | 2021-07-13 18:47:55.651608+02 (6 rows) ``` ### Manage subscribers list once connected to database with `\c ` and promt changes to `=#` select all users from subscribers lists ```postgres SELECT * subscriber_lists; ``` will show something like this ```postgres subscriber_id | list_id | status | created_at | updated_at ---------------+---------+-------------+-------------------------------+------------------------------- 646 | 7 | confirmed | 2021-07-13 18:47:55.616239+02 | 2021-07-13 18:47:55.616239+02 45 | 4 | confirmed | 2021-07-13 18:04:57.974174+02 | 2021-07-13 18:04:57.974174+02 9 | 3 | confirmed | 2021-06-03 17:34:34.714387+02 | 2021-06-03 17:42:13.431435+02 3148 | 7 | confirmed | 2021-07-13 18:47:55.616239+02 | 2021-07-13 18:47:55.616239+02 7 | 7 | unconfirmed | 2021-06-08 17:17:26.372759+02 | 2021-06-08 17:17:26.372759+02 1232 | 7 | confirmed | 2021-07-13 18:47:55.616239+02 | 2021-07-13 18:47:55.616239+02 7 | 5 | confirmed | 2021-06-08 17:17:26.372759+02 | 2021-06-08 17:17:26.372759+02 ``` #### confirm users modify the status from `unconfirmed` to `confirmed` ```postgres UPDATE subscriber_lists SET status='confirmed' WHERE list_id=; ``` change the `` for the one you see under `list_id` __________________ ### Heroku Using the [Nginx buildpack](https://github.com/heroku/heroku-buildpack-nginx) can be used to deploy listmonk on Heroku and use Nginx as a proxy to setup basicauth. [Heroku deploy button](https://github.com/bumi/listmonk-heroku) provides an automated default deployment. ### HOWTOS [HOWTO set up listmonk](https://yasoob.me/posts/setting-up-listmonk-opensource-newsletter-mailing/) [HOWTO import mailchimp subscribers](https://yasoob.me/posts/setting-up-listmonk-opensource-newsletter-mailing/#importing-old-subscribers) ## Developers listmonk is a free and open source software licensed under AGPLv3. If you are interested in contributing, refer to the [developer setup](https://listmonk.app/docs/developer-setup). The backend is written in Go and the frontend is Vue with Buefy for UI. ## License listmonk is licensed under the AGPL v3 license.