Tags

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;
}