add listmonk app

This commit is contained in:
2026-02-06 18:36:15 +01:00
parent 3d6793a843
commit 905cc8b43d
12 changed files with 351 additions and 2 deletions

28
main.tf
View File

@@ -23,6 +23,7 @@ locals {
bookshelf = module.bookshelf.traefik_service
gitea = module.gitea.traefik_service
fefan = module.fefan.traefik_service
listmonk = module.listmonk.traefik_service
}
}
@@ -153,16 +154,39 @@ module "fefan" {
proxmox_host_ip = var.proxmox_host_ip
}
module "listmonk" {
source = "./modules/apps/listmonk"
providers = {}
vm_ip_address = "192.168.1.93"
depends_on = []
name = "listmonk"
hostname = "listmonk"
domain = "fefan.fr"
vm_id = 214
node_name = "mop"
template_id = 103
cores = 1
memory = 2048
balloon = 1024
disk_size = 16
ssh_public_key = var.ssh_public_key
proxmox_host_ip = var.proxmox_host_ip
}
# module "keycloak" {
# source = "./modules/apps/keycloak"
# providers = {}
# vm_ip_address = "192.168.1.93"
# vm_ip_address = "192.168.1.94"
# depends_on = []
# name = "keycloak"
# hostname = "keycloak"
# domain = "aldon.fr"
# vm_id = 214
# vm_id = 215
# node_name = "mop"
# template_id = 103

View File

@@ -0,0 +1,20 @@
# Environment files
ENV_FILE_LOCATION=/opt/environment/.env
# Application specifics
LISTMONK_BINARY=/usr/local/bin/listmonk
LISTMONK_VERSION=6.0.0
LISTMONK_CONFIG=/home/listmonk/config.toml
DB_USER=listmonk
DB_PASS=
DB_NAME=listmonk
LISTMONK_ADMIN_PASSWORD=
LISTMONK_ADMIN_USER=admin
# VM
USERNAME=listmonk
# Backup specifics
SERVICE_BACKUPS_DIR=/backups/listmonk
SERVICE_BACKUPS_PREFIX=listmonk-dump
SERVICE_BACKUPS_EXTENSION=sql

View File

@@ -0,0 +1,78 @@
#cloud-config
hostname: ${hostname}
local-hostname: ${hostname}
fqdn: ${hostname}.${domain}
manage_etc_hosts: true
groups:
- git
users:
- default
- name: ${hostname}
groups: sudo,git
shell: /bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
ssh_authorized_keys:
- ${ssh_key}
disable_root: true
package_update: true
package_upgrade: false
packages:
- git
- nfs-common
- curl
- unzip
- postgresql
- postgresql-client
mounts:
- [ "192.168.1.12:/main/backups", "/backups", "nfs", "defaults,_netdev,x-systemd.requires=network-online.target", "0", "0" ]
write_files:
- path: /opt/environment/.env
permissions: "0644"
content: |
${env-file-content}
- path: /usr/local/bin/restore-backup.sh
permissions: "0755"
content: |
${restore-backup-script}
- path: /etc/systemd/system/restore-backup.service
permissions: "0644"
content: |
${restore-backup-service}
- path: /usr/local/bin/backup.sh
permissions: "0755"
content: |
${create-backup-script}
- path: /etc/systemd/system/create-backup.timer
permissions: "0644"
content: |
${create-backup-timer}
- path: /etc/systemd/system/create-backup.service
permissions: "0644"
content: |
${create-backup-service}
- path: /etc/systemd/system/listmonk.service
permissions: "0644"
content: |
${listmonk-service}
- path: /opt/listmonk/install-listmonk.sh
permissions: "0755"
content: |
${install-listmonk-script}
runcmd:
# Backup setup
- mkdir -p /backups
- mount -t nfs ${proxmox_host_ip}:/main/backups /backups
- systemctl enable --now create-backup.timer
# listmonk setup
- /opt/listmonk/install-listmonk.sh
final_message: |
Base system ready for ${hostname}

View File

@@ -0,0 +1,12 @@
#!/bin/bash
set -euo pipefail
source /opt/environment/.env
TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S')
systemctl stop listmonk
sudo -u $USERNAME pg_dump -Fc -U $DB_USER $DB_NAME > $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-$TIMESTAMP.$SERVICE_BACKUPS_EXTENSION
systemctl start listmonk
ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION | tail -n +5 | xargs -r rm -f

View File

@@ -0,0 +1,53 @@
#!/bin/bash
#LISTMONK_BINARY=/usr/local/bin/listmonk
#LISTMONK_VERSION=6.0.0
#LISTMONK_CONFIG=/home/listmonk/config.toml
#DB_USER
#DB_PASS
#DB_NAME
set -euo pipefail
source /opt/environment/.env
# Listmonk binary
if [ ! -f $LISTMONK_BINARY ]; then
wget -O /tmp/listmonk.tar.gz "https://github.com/knadh/listmonk/releases/download/v${LISTMONK_VERSION}/listmonk_${LISTMONK_VERSION}_linux_amd64.tar.gz"
mkdir /tmp/listmonk
tar -xzf /tmp/listmonk.tar.gz -C /tmp/listmonk
mv /tmp/listmonk/listmonk $LISTMONK_BINARY
chmod +x $LISTMONK_BINARY
fi
# Listmonk config
cat > $LISTMONK_CONFIG <<EOF
[app]
address = "0.0.0.0:9000"
[db]
host = "localhost"
port = 5432
user = "$DB_USER"
password = "$DB_PASS"
database = "$DB_NAME"
ssl_mode = "disable"
max_open = 25
max_idle = 25
max_lifetime = "300s"
EOF
# Listmonk pgsql init db
sudo -u postgres psql <<EOF
CREATE ROLE $DB_USER WITH LOGIN PASSWORD '$DB_PASS';
CREATE DATABASE $DB_NAME WITH OWNER $DB_USER TEMPLATE template0 ENCODING UTF8 LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8';
EOF
$LISTMONK_BINARY --install --config $LISTMONK_CONFIG --yes
systemctl start restore-backup.service
systemctl daemon-reload
systemctl enable listmonk
systemctl start listmonk

View File

@@ -0,0 +1,12 @@
#!/bin/bash
set -euo pipefail
source /opt/environment/.env
LATEST_BACKUP=$(ls -1 $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION 2>/dev/null | sort | tail -n1)
if [ -n "$LATEST_BACKUP" ] && [ -f "$LATEST_BACKUP" ]; then
systemctl stop listmonk
sudo -u $USERNAME pg_restore --clean --if-exists -U "$DB_USER" -d "$DB_NAME" $LATEST_BACKUP
systemctl start listmonk
fi

View File

@@ -0,0 +1,9 @@
[Unit]
Description=Backup Service
Wants=network.target
After=network.target postgresql.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/backup.sh

View File

@@ -0,0 +1,15 @@
[Unit]
Description=listmonk mailing list and newsletter manager (%I)
ConditionPathExists=/home/listmonk/config.toml
Wants=network.target
After=postgresql.service
[Service]
Type=simple
ExecStartPre=/usr/local/bin/listmonk --config /home/listmonk/config.toml --upgrade --yes
ExecStart=/usr/local/bin/listmonk --config /home/listmonk/config.toml
Restart=always
RestartSec=30
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,9 @@
[Unit]
Description=Restore latest backup
After=network.target postgresql.service
Requires=postgresql.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/restore-backup.sh

View File

@@ -0,0 +1,37 @@
module "vm" {
source = "../../vm"
name = var.name
hostname = var.hostname
domain = var.domain
vm_id = var.vm_id
node_name = var.node_name
vm_ip_address = var.vm_ip_address
template_id = var.template_id
cores = var.cores
memory = var.memory
disk_size = var.disk_size
ssh_public_key = var.ssh_public_key
proxmox_host_ip = var.proxmox_host_ip
cloudinit_config = templatefile(
"${path.module}/cloud-init/service.yaml",
{
hostname = var.hostname
domain = var.domain
ssh_key = var.ssh_public_key
proxmox_host_ip = var.proxmox_host_ip
restore-backup-script = indent(6, file("${path.module}/lib/scripts/restore-backup.sh"))
restore-backup-service = indent(6, file("${path.module}/lib/services/restore-backup.service"))
create-backup-script = indent(6, file("${path.module}/lib/scripts/create-backup.sh"))
create-backup-service = indent(6, file("${path.module}/lib/services/create-backup.service"))
create-backup-timer = indent(6, file("${path.module}/../common/services/create-backup.timer"))
install-listmonk-script = indent(6, file("${path.module}/lib/scripts/install-listmonk.sh"))
listmonk-service =indent(6, file("${path.module}/lib/services/listmonk.service"))
env-file-content = indent(6, file("${path.module}/.env"))
}
)
}

View File

@@ -0,0 +1,9 @@
output "traefik_service" {
value = [{
domain = var.domain
name = var.name
host = "${var.hostname}"
ip = var.vm_ip_address
port = 9000
}]
}

View File

@@ -0,0 +1,71 @@
variable "name" {
description = "Virtual Machine name"
type = string
}
variable "vm_id" {
description = "Virtual Machine id"
type = number
}
variable "node_name" {
description = "Proxmox node name"
type = string
default = "mop"
}
variable "cores" {
description = "Number of CPU cores for this virtual machine"
type = number
default = 2
}
variable "memory" {
description = "Memory RAM for this virtual machine"
type = number
default = 2048
}
variable "balloon" {
description = "Minimum vm memory, using ballooning devide to reach Proxmox node memory target."
type = number
default = 1024
}
variable "template_id" {
description = "Virtual machine template ID"
type = number
}
variable "ssh_public_key" {
description = "Public SSH key for cloud-init user"
type = string
}
variable "hostname" {
description = "Virtual Machine hostname (<service-name>)"
type = string
default = "test"
}
variable "domain" {
description = "Virtual Machine domain (example.fr)"
type = string
default = ""
}
variable "disk_size" {
description = "Disk size for the virtual machine"
type = number
default = 10
}
variable "proxmox_host_ip" {
description = "Proxmox host base ip"
type = string
}
variable "vm_ip_address" {
description = "Virtual machine ip"
type = string
}