From 905cc8b43ddcd8ea0154a5cbaa34ca2de95c4e6c Mon Sep 17 00:00:00 2001 From: JulienAldon Date: Fri, 6 Feb 2026 18:36:15 +0100 Subject: [PATCH] add listmonk app --- main.tf | 28 ++++++- modules/apps/listmonk/.env.example | 20 +++++ modules/apps/listmonk/cloud-init/service.yaml | 78 +++++++++++++++++++ .../listmonk/lib/scripts/create-backup.sh | 12 +++ .../listmonk/lib/scripts/install-listmonk.sh | 53 +++++++++++++ .../listmonk/lib/scripts/restore-backup.sh | 12 +++ .../lib/services/create-backup.service | 9 +++ .../listmonk/lib/services/listmonk.service | 15 ++++ .../lib/services/restore-backup.service | 9 +++ modules/apps/listmonk/main.tf | 37 +++++++++ modules/apps/listmonk/output.tf | 9 +++ modules/apps/listmonk/variables.tf | 71 +++++++++++++++++ 12 files changed, 351 insertions(+), 2 deletions(-) create mode 100644 modules/apps/listmonk/.env.example create mode 100644 modules/apps/listmonk/cloud-init/service.yaml create mode 100644 modules/apps/listmonk/lib/scripts/create-backup.sh create mode 100644 modules/apps/listmonk/lib/scripts/install-listmonk.sh create mode 100644 modules/apps/listmonk/lib/scripts/restore-backup.sh create mode 100644 modules/apps/listmonk/lib/services/create-backup.service create mode 100644 modules/apps/listmonk/lib/services/listmonk.service create mode 100644 modules/apps/listmonk/lib/services/restore-backup.service create mode 100644 modules/apps/listmonk/main.tf create mode 100644 modules/apps/listmonk/output.tf create mode 100644 modules/apps/listmonk/variables.tf diff --git a/main.tf b/main.tf index 26e3e76..be8989b 100644 --- a/main.tf +++ b/main.tf @@ -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 diff --git a/modules/apps/listmonk/.env.example b/modules/apps/listmonk/.env.example new file mode 100644 index 0000000..6e3246d --- /dev/null +++ b/modules/apps/listmonk/.env.example @@ -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 diff --git a/modules/apps/listmonk/cloud-init/service.yaml b/modules/apps/listmonk/cloud-init/service.yaml new file mode 100644 index 0000000..67a6fbe --- /dev/null +++ b/modules/apps/listmonk/cloud-init/service.yaml @@ -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} \ No newline at end of file diff --git a/modules/apps/listmonk/lib/scripts/create-backup.sh b/modules/apps/listmonk/lib/scripts/create-backup.sh new file mode 100644 index 0000000..7b677e4 --- /dev/null +++ b/modules/apps/listmonk/lib/scripts/create-backup.sh @@ -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 diff --git a/modules/apps/listmonk/lib/scripts/install-listmonk.sh b/modules/apps/listmonk/lib/scripts/install-listmonk.sh new file mode 100644 index 0000000..0ba562b --- /dev/null +++ b/modules/apps/listmonk/lib/scripts/install-listmonk.sh @@ -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 </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 \ No newline at end of file diff --git a/modules/apps/listmonk/lib/services/create-backup.service b/modules/apps/listmonk/lib/services/create-backup.service new file mode 100644 index 0000000..ad6387d --- /dev/null +++ b/modules/apps/listmonk/lib/services/create-backup.service @@ -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 \ No newline at end of file diff --git a/modules/apps/listmonk/lib/services/listmonk.service b/modules/apps/listmonk/lib/services/listmonk.service new file mode 100644 index 0000000..334f7d9 --- /dev/null +++ b/modules/apps/listmonk/lib/services/listmonk.service @@ -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 \ No newline at end of file diff --git a/modules/apps/listmonk/lib/services/restore-backup.service b/modules/apps/listmonk/lib/services/restore-backup.service new file mode 100644 index 0000000..f75614c --- /dev/null +++ b/modules/apps/listmonk/lib/services/restore-backup.service @@ -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 \ No newline at end of file diff --git a/modules/apps/listmonk/main.tf b/modules/apps/listmonk/main.tf new file mode 100644 index 0000000..fb45368 --- /dev/null +++ b/modules/apps/listmonk/main.tf @@ -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")) + } + ) +} \ No newline at end of file diff --git a/modules/apps/listmonk/output.tf b/modules/apps/listmonk/output.tf new file mode 100644 index 0000000..0e59659 --- /dev/null +++ b/modules/apps/listmonk/output.tf @@ -0,0 +1,9 @@ +output "traefik_service" { + value = [{ + domain = var.domain + name = var.name + host = "${var.hostname}" + ip = var.vm_ip_address + port = 9000 + }] +} \ No newline at end of file diff --git a/modules/apps/listmonk/variables.tf b/modules/apps/listmonk/variables.tf new file mode 100644 index 0000000..c2feb6d --- /dev/null +++ b/modules/apps/listmonk/variables.tf @@ -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 ()" + 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 +} \ No newline at end of file