listmonk/listmonk_create.sh
#!/bin/bash
# =============================================================================
# Script Name: listmonk_create.sh
# Version: 1.1
# Author: Andreas Fleckl
# Description: This script sets up a new Listmonk instance with a unique
# configuration, database, and nginx setup. It handles error
# checking and logs important steps.
# =============================================================================
set -e
export LANG=C
# Prompt for new Listmonk instance details
read -e -p "Name: " NAME
read -e -p "URL: " URL
echo
# Generate passwords
PASS=$(pwgen -1cns 16)
PASS2=$(pwgen -1cns 16)
# Find the next free port for Listmonk
TOPPORT=$(lsof -wPni | grep listmonk | cut -d":" -f2 | cut -d" " -f1 | sort | tail -n1)
if [ -z "$TOPPORT" ]; then
FREEPORT=9000
else
FREEPORT=$((TOPPORT + 1))
fi
# Setup PostgreSQL database and user
USER=$NAME
DB=$NAME
RESULT=$(psql -U postgres -tc "SELECT 1 FROM pg_database WHERE datname='$DB'")
if [ "$RESULT" == '1' ]; then
echo "Database $DB already exists. Exiting script."
exit 1
else
psql -U postgres -c "CREATE DATABASE $DB;"
psql -U postgres -c "CREATE USER $USER WITH PASSWORD '$PASS';"
psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE $DB TO $USER;"
psql -U postgres -c "ALTER DATABASE $DB OWNER TO $USER;"
echo "Database $DB and user $USER created successfully."
fi
echo "DB Password: $PASS"
echo
# Create Listmonk configuration
echo "Creating config.toml..."
sed -e "s/PORT/$FREEPORT/g" -e "s/NAME/$NAME/g" -e "s/PASS2/$PASS2/g" -e "s/USER/$USER/g" -e "s/PASS/$PASS/g" -e "s/DB/$DB/g" /root/listmonk/config-TEMPLATE.toml > /etc/listmonk/config-$NAME.toml
# Create systemd service for Listmonk
echo "Creating systemd service..."
sed -e "s/NAME/$NAME/g" /root/listmonk/listmonk-TEMPLATE.service > /etc/systemd/system/listmonk-$NAME.service
sed -i 's|WorkingDirectory=.*|WorkingDirectory=/var/lib/private/listmonk-'$NAME'|' /etc/systemd/system/listmonk-$NAME.service
# Create Listmonk data directory and set permissions
echo "Setting up Listmonk data directory..."
mkdir -p /var/lib/private/listmonk-$NAME/uploads
chown -R listmonk-$NAME:listmonk-$NAME /var/lib/private/listmonk-$NAME
chmod -R 750 /var/lib/private/listmonk-$NAME
# Install Listmonk database
echo "Installing Listmonk database..."
/usr/bin/listmonk --install --config /etc/listmonk/config-$NAME.toml
# Start Listmonk service
echo "Starting Listmonk service..."
systemctl daemon-reload
systemctl enable listmonk-$NAME.service
systemctl start listmonk-$NAME.service
echo "Listmonk admin username: admin-$NAME"
echo "Listmonk admin password: $PASS2"
echo
# Send credentials securely
sendstring=$'Achtung: Seite wird in UTF-8 dargestellt!\nDas Passwort hat immer eine Länge von 16 Zeichen!\n\nuser: '"admin-$NAME"$'\npass: '$PASS2$'\n\n'
echo "Sending credentials..."
curl --data $"plaintext=$sendstring" --data "only_url" https://sekurator.servus.at/transfer/store
echo
# Configure nginx
echo "Creating nginx configuration..."
sed -e "s/URL/$URL/g" -e "s/FREEPORT/$FREEPORT/g" /root/listmonk/URL.conf > /etc/nginx/sites-available/$URL.conf
ln -s /etc/nginx/sites-available/$URL.conf /etc/nginx/sites-enabled
# Test and reload nginx
if nginx -t 2>&1 | grep -q "test is successful"; then
echo "Nginx configuration is correct. Reloading nginx."
nginx -s reload
certbot --nginx --expand --redirect --cert-name $NAME -d $URL
else
echo "Nginx configuration test failed."
exit 1
fi
echo "Listmonk instance setup completed successfully."
listmonk/config-TEMPLATE.toml
# =============================================================================
# Listmonk Configuration Template
# Version: 1.0
# Description: This template is used to generate specific configurations for
# Listmonk instances. Variables like PORT, NAME, USER, PASS, DB,
# and PASS2 will be replaced by actual values during instance
# creation.
# =============================================================================
[app]
# Bind address for the HTTP server.
address = "localhost:PORT"
# Admin user credentials for logging into the Listmonk admin UI.
admin_username = "admin-NAME"
admin_password = "PASS2"
# Database.
[db]
# Hostname of the PostgreSQL server.
host = "localhost"
# Port number where PostgreSQL is listening.
port = 5432
# Database user name.
user = "USER"
# Database user password.
password = "PASS"
# Ensure that this database has been created in Postgres.
database = "DB"
# SSL mode to connect to the database (disable, require, verify-ca, verify-full).
ssl_mode = "disable"
# Maximum open connections to the database.
max_open = 25
# Maximum idle connections to the database.
max_idle = 25
# Maximum lifetime of database connections.
max_lifetime = "300s"
# Optional space separated Postgres DSN params. eg: "application_name=listmonk gssencmode=disable"
params = ""
listmonk/listmonk-TEMPLATE.service
# =============================================================================
# Listmonk Systemd Service Template
# Version: 1.0
# Description: This template is used to generate specific systemd service files
# for Listmonk instances. Variables like NAME will be replaced by
# actual values during instance creation.
# =============================================================================
[Unit]
Description=Listmonk mailing list and newsletter manager (%I)
ConditionPathExists=/etc/listmonk/config-NAME.toml
Wants=network.target
After=postgresql.service
[Service]
Type=simple
EnvironmentFile=-/etc/default/listmonk
EnvironmentFile=-/etc/default/listmonk-NAME
ExecStartPre=/usr/bin/mkdir -p "${HOME}/uploads"
ExecStartPre=/usr/bin/listmonk --config /etc/listmonk/config-NAME.toml --upgrade --yes
ExecStart=/usr/bin/listmonk --config /etc/listmonk/config-NAME.toml $SYSTEMD_LISTMONK_ARGS
Restart=on-failure
DynamicUser=true
StateDirectory=listmonk-NAME
Environment=HOME=%S/listmonk-NAME
WorkingDirectory=%S/listmonk-NAME
NoNewPrivileges=true
CapabilityBoundingSet=
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged
PrivateDevices=true
ProtectControlGroups=true
ProtectKernelTunables=true
ProtectHome=true
RestrictNamespaces=true
RestrictRealtime=true
UMask=0027
MemoryDenyWriteExecute=true
LockPersonality=true
RestrictAddressFamilies=AF_INET AF_INET6
ProtectKernelModules=true
PrivateUsers=true
[Install]
WantedBy=multi-user.target
listmonk/URL.conf
# =============================================================================
# Nginx Configuration Template for Listmonk
# Version: 1.1
# Description: This template is used to generate specific nginx configuration
# files for Listmonk instances that initially only listen on port 80.
# Certbot will modify the configuration for SSL.
# =============================================================================
server {
listen 80;
server_name URL;
location / {
proxy_pass http://localhost:FREEPORT;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
include proxy_params;
}
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location /uploads/ {
alias /var/lib/private/listmonk-NAME/uploads/;
autoindex on;
}
access_log /var/log/nginx/URL.access.log;
error_log /var/log/nginx/URL.error.log;
}