From a56911b89688ee78827b6157a10401608db539d8 Mon Sep 17 00:00:00 2001 From: JulienAldon Date: Tue, 21 Apr 2026 16:52:41 +0200 Subject: [PATCH] Add(module): add girasol module Add(module): add amap module Add(module): add common lib and services Add(module): add base structure for keycloak Add(module): add base structure for rocket Add(module): add n8n and windmill modules Add(docker): add install docker script in common module Add(template): add root for aldon.fr and mathieu.wiki in traefik.service template --- main.tf | 76 +++++- modules/apps/amap/.env.example | 36 +++ modules/apps/amap/cloud-init/service.yaml | 90 +++++++ .../apps/amap/lib/scripts/create-backup.sh | 10 + .../apps/amap/lib/scripts/restore-backup.sh | 10 + modules/apps/amap/lib/services/.gitkeep | 0 modules/apps/amap/main.tf | 41 ++++ modules/apps/amap/output.tf | 9 + modules/apps/amap/variables.tf | 71 ++++++ .../apps/bookshelf/cloud-init/service.yaml | 10 +- modules/apps/bookshelf/main.tf | 1 + modules/apps/common/scripts/install-docker.sh | 23 ++ modules/apps/fefan/cloud-init/service.yaml | 10 +- modules/apps/fefan/main.tf | 1 + modules/apps/gateway/.env.example | 8 +- modules/apps/gateway/cloud-init/service.yaml | 47 +++- .../apps/gateway/lib/scripts/create-backup.sh | 10 + .../gateway/lib/scripts/install-crowdsec.sh | 17 ++ .../gateway/lib/scripts/install-traefik.sh | 10 +- .../gateway/lib/scripts/restore-backup.sh | 10 + modules/apps/gateway/main.tf | 9 +- modules/apps/girasol/.env.example | 22 ++ modules/apps/girasol/cloud-init/service.yaml | 89 +++++++ modules/apps/girasol/lib/create-backup.sh | 7 + modules/apps/girasol/lib/restore-backup.sh | 5 + modules/apps/girasol/main.tf | 41 ++++ modules/apps/girasol/output.tf | 9 + modules/apps/girasol/variables.tf | 71 ++++++ modules/apps/gitea/cloud-init/service.yaml | 10 +- modules/apps/gitea/main.tf | 1 + modules/apps/keycloak/.env.example | 22 ++ modules/apps/keycloak/cloud-init/service.yaml | 71 ++++++ .../keycloak/lib/scripts/create-backup.sh | 18 ++ .../keycloak/lib/scripts/install-keycloak.sh | 34 +++ .../keycloak/lib/scripts/restore-backup.sh | 14 ++ .../lib/services/create-backup.service | 9 + .../keycloak/lib/services/keycloak.service | 17 ++ .../lib/services/restore-backup.service | 9 + modules/apps/keycloak/main.tf | 35 +++ modules/apps/keycloak/output.tf | 9 + modules/apps/keycloak/variables.tf | 71 ++++++ modules/apps/n8n/.env.example | 0 modules/apps/n8n/cloud-init/service.yaml | 91 +++++++ modules/apps/n8n/lib/scripts/create-backup.sh | 10 + modules/apps/n8n/lib/scripts/init-data.sh | 8 + modules/apps/n8n/lib/scripts/install-n8n.sh | 11 + .../apps/n8n/lib/scripts/restore-backup.sh | 10 + .../apps/n8n/lib/services/docker-compose.yaml | 54 +++++ modules/apps/n8n/main.tf | 39 +++ modules/apps/n8n/output.tf | 9 + modules/apps/n8n/variables.tf | 71 ++++++ modules/apps/rocket/main.tf | 0 modules/apps/rocket/output.tf | 0 modules/apps/rocket/variables.tf | 0 modules/apps/windmill/.env.example | 15 ++ modules/apps/windmill/cloud-init/service.yaml | 89 +++++++ .../windmill/lib/scripts/create-backup.sh | 15 ++ .../windmill/lib/scripts/install-windmill.sh | 11 + .../windmill/lib/scripts/restore-backup.sh | 20 ++ modules/apps/windmill/lib/services/Caddyfile | 35 +++ .../windmill/lib/services/docker-compose.yaml | 222 ++++++++++++++++++ modules/apps/windmill/main.tf | 41 ++++ modules/apps/windmill/output.tf | 9 + modules/apps/windmill/variables.tf | 71 ++++++ templates/traefik.services.tpl | 22 ++ 65 files changed, 1893 insertions(+), 23 deletions(-) create mode 100644 modules/apps/amap/.env.example create mode 100644 modules/apps/amap/cloud-init/service.yaml create mode 100644 modules/apps/amap/lib/scripts/create-backup.sh create mode 100644 modules/apps/amap/lib/scripts/restore-backup.sh create mode 100644 modules/apps/amap/lib/services/.gitkeep create mode 100644 modules/apps/amap/main.tf create mode 100644 modules/apps/amap/output.tf create mode 100644 modules/apps/amap/variables.tf create mode 100644 modules/apps/common/scripts/install-docker.sh create mode 100644 modules/apps/gateway/lib/scripts/create-backup.sh create mode 100644 modules/apps/gateway/lib/scripts/install-crowdsec.sh create mode 100644 modules/apps/gateway/lib/scripts/restore-backup.sh create mode 100644 modules/apps/girasol/.env.example create mode 100644 modules/apps/girasol/cloud-init/service.yaml create mode 100644 modules/apps/girasol/lib/create-backup.sh create mode 100644 modules/apps/girasol/lib/restore-backup.sh create mode 100644 modules/apps/girasol/main.tf create mode 100644 modules/apps/girasol/output.tf create mode 100644 modules/apps/girasol/variables.tf create mode 100644 modules/apps/keycloak/.env.example create mode 100644 modules/apps/keycloak/cloud-init/service.yaml create mode 100644 modules/apps/keycloak/lib/scripts/create-backup.sh create mode 100644 modules/apps/keycloak/lib/scripts/install-keycloak.sh create mode 100644 modules/apps/keycloak/lib/scripts/restore-backup.sh create mode 100644 modules/apps/keycloak/lib/services/create-backup.service create mode 100644 modules/apps/keycloak/lib/services/keycloak.service create mode 100644 modules/apps/keycloak/lib/services/restore-backup.service create mode 100644 modules/apps/keycloak/main.tf create mode 100644 modules/apps/keycloak/output.tf create mode 100644 modules/apps/keycloak/variables.tf create mode 100644 modules/apps/n8n/.env.example create mode 100644 modules/apps/n8n/cloud-init/service.yaml create mode 100644 modules/apps/n8n/lib/scripts/create-backup.sh create mode 100644 modules/apps/n8n/lib/scripts/init-data.sh create mode 100644 modules/apps/n8n/lib/scripts/install-n8n.sh create mode 100644 modules/apps/n8n/lib/scripts/restore-backup.sh create mode 100644 modules/apps/n8n/lib/services/docker-compose.yaml create mode 100644 modules/apps/n8n/main.tf create mode 100644 modules/apps/n8n/output.tf create mode 100644 modules/apps/n8n/variables.tf create mode 100644 modules/apps/rocket/main.tf create mode 100644 modules/apps/rocket/output.tf create mode 100644 modules/apps/rocket/variables.tf create mode 100644 modules/apps/windmill/.env.example create mode 100644 modules/apps/windmill/cloud-init/service.yaml create mode 100644 modules/apps/windmill/lib/scripts/create-backup.sh create mode 100644 modules/apps/windmill/lib/scripts/install-windmill.sh create mode 100644 modules/apps/windmill/lib/scripts/restore-backup.sh create mode 100644 modules/apps/windmill/lib/services/Caddyfile create mode 100644 modules/apps/windmill/lib/services/docker-compose.yaml create mode 100644 modules/apps/windmill/main.tf create mode 100644 modules/apps/windmill/output.tf create mode 100644 modules/apps/windmill/variables.tf diff --git a/main.tf b/main.tf index be8989b..e833db4 100644 --- a/main.tf +++ b/main.tf @@ -24,6 +24,7 @@ locals { gitea = module.gitea.traefik_service fefan = module.fefan.traefik_service listmonk = module.listmonk.traefik_service + amap = module.amap.traefik_service } } @@ -177,16 +178,87 @@ module "listmonk" { proxmox_host_ip = var.proxmox_host_ip } +module "amap" { + source = "./modules/apps/amap" + providers = {} + vm_ip_address = "192.168.1.96" + depends_on = [ + module.gitea + ] + + name = "amap" + hostname = "amap" + domain = "aldon.fr" + vm_id = 217 + node_name = "mop" + + template_id = 103 + + cores = 1 + memory = 1024 + balloon = 1024 + disk_size = 16 + + ssh_public_key = var.ssh_public_key + proxmox_host_ip = var.proxmox_host_ip +} + +# module "n8n" { +# source = "./modules/apps/n8n" +# providers = {} +# vm_ip_address = "192.168.1.94" +# depends_on = [] + +# name = "n8n" +# hostname = "n8n" +# domain = "mathieu.wiki" +# vm_id = 215 +# node_name = "mop" + +# template_id = 103 + +# cores = 1 +# memory = 1024 +# balloon = 512 +# disk_size = 16 + +# ssh_public_key = var.ssh_public_key +# proxmox_host_ip = var.proxmox_host_ip +# } + +# module "windmill" { +# source = "./modules/apps/windmill" +# providers = {} +# vm_ip_address = "192.168.1.94" +# depends_on = [] + +# name = "windmill" +# hostname = "windmill" +# domain = "aldon.fr" +# vm_id = 215 +# 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.94" + # vm_ip_address = "192.168.1.95" # depends_on = [] # name = "keycloak" # hostname = "keycloak" # domain = "aldon.fr" - # vm_id = 215 + # vm_id = 216 # node_name = "mop" # template_id = 103 diff --git a/modules/apps/amap/.env.example b/modules/apps/amap/.env.example new file mode 100644 index 0000000..91e8fc0 --- /dev/null +++ b/modules/apps/amap/.env.example @@ -0,0 +1,36 @@ +# Environment files +ENV_FILE_LOCATION=/opt/environment/.env + +# gitea act_runner +ACT_RUNNER_VERSION=0.2.13 +ACT_RUNNER_LOCATION=/usr/local/bin +ACT_RUNNER_USER=act_runner +GITEA_RUNNER_REGISTRATION_TOKEN= +USERNAME=amap + +# gitea instance +GITEA_INSTANCE_URL=https://gitea.aldon.fr +GITEA_SERVICE_APPLICATION_TOKEN= +GITEA_SERVICE_REPOSITORY=mop/amap +GITEA_WORKFLOW_NAME=deploy.yaml + +# Applicaiton specifics +DB_USER=postgres +DB_PASS= +DB_NAME=amap +DB_HOST=localhost +ORIGINS=https://amap.aldon.fr +SECRET_KEY= +VITE_API_URL=https://amap.aldon.fr/api +KEYCLOAK_SERVER=https://keycloak.aldon.fr +KEYCLOAK_REALM=aldon.fr +KEYCLOAK_CLIENT_ID= +KEYCLOAK_CLIENT_SECRET= +KEYCLOAK_REDIRECT_URI=https://amap.aldon.fr/api/auth/callback +MAX_AGE=3600 +DEBUG=True + +# Backup specifics +SERVICE_BACKUPS_DIR=/backups/amap +SERVICE_BACKUPS_PREFIX=amap-dump +SERVICE_BACKUPS_EXTENSION=sql \ No newline at end of file diff --git a/modules/apps/amap/cloud-init/service.yaml b/modules/apps/amap/cloud-init/service.yaml new file mode 100644 index 0000000..f21aff5 --- /dev/null +++ b/modules/apps/amap/cloud-init/service.yaml @@ -0,0 +1,90 @@ +#cloud-config +hostname: ${hostname} +local-hostname: ${hostname} +fqdn: ${hostname}.${domain} +manage_etc_hosts: true + +users: + - default + - name: ${hostname} + groups: sudo + 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 + - jq + - 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: /opt/${hostname}/install-docker.sh + permissions: "0755" + content: | + ${install-docker-script} + - 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/act_runner.service + permissions: "0644" + content: | + ${act_runner-service} + - path: /opt/${hostname}/install-runner.sh + permissions: "0755" + content: | + ${act_runner-install-script} + - path: /opt/${hostname}/install-service.sh + permissions: "0755" + content: | + ${service-install-script} + +runcmd: + # Backup setup + - mkdir -p /backups + - mount -t nfs ${proxmox_host_ip}:/main/backups /backups + - systemctl enable --now create-backup.timer + # Docker setup + - /opt/${hostname}/install-docker.sh + # Act_runner install + - /opt/${hostname}/install-runner.sh + - systemctl daemon-reload + - systemctl enable act_runner.service + - systemctl start act_runner.service + # ${hostname} install + - /opt/${hostname}/install-service.sh + + +final_message: | + Base system ready for ${hostname} \ No newline at end of file diff --git a/modules/apps/amap/lib/scripts/create-backup.sh b/modules/apps/amap/lib/scripts/create-backup.sh new file mode 100644 index 0000000..5a869c3 --- /dev/null +++ b/modules/apps/amap/lib/scripts/create-backup.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -euo pipefail + +source /opt/environment/.env + +TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S') + +sudo -u $USERNAME docker exec -i amap-database-1 pg_dump -F c -U $DB_USER -d $DB_NAME > $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-$TIMESTAMP.$SERVICE_BACKUPS_EXTENSION + +ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION | tail -n +5 | xargs -r rm -f diff --git a/modules/apps/amap/lib/scripts/restore-backup.sh b/modules/apps/amap/lib/scripts/restore-backup.sh new file mode 100644 index 0000000..51e1270 --- /dev/null +++ b/modules/apps/amap/lib/scripts/restore-backup.sh @@ -0,0 +1,10 @@ +#!/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 + sudo -u $USERNAME docker exec -i amap-database-1 pg_restore --clean --if-exists -U "$DB_USER" -v -d "$DB_NAME" < $LATEST_BACKUP +fi \ No newline at end of file diff --git a/modules/apps/amap/lib/services/.gitkeep b/modules/apps/amap/lib/services/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/modules/apps/amap/main.tf b/modules/apps/amap/main.tf new file mode 100644 index 0000000..96f6bbe --- /dev/null +++ b/modules/apps/amap/main.tf @@ -0,0 +1,41 @@ +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}/../common/services/docker/restore-backup.service")) + create-backup-script = indent(6, file("${path.module}/lib/scripts/create-backup.sh")) + create-backup-service = indent(6, file("${path.module}}/../common/services/docker/create-backup.service")) + create-backup-timer = indent(6, file("${path.module}/../common/services/create-backup.timer")) + + act_runner-service = indent(6, file("${path.module}/../common/services/act_runner.service")) + act_runner-install-script = indent(6, file("${path.module}/../common/scripts/install-runner.sh")) + + service-install-script = indent(6, file("${path.module}/../common/scripts/install-service-ci.sh")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) + + env-file-content = indent(6, file("${path.module}/.env")) + } + ) +} \ No newline at end of file diff --git a/modules/apps/amap/output.tf b/modules/apps/amap/output.tf new file mode 100644 index 0000000..f7ad914 --- /dev/null +++ b/modules/apps/amap/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 = 80 + }] +} \ No newline at end of file diff --git a/modules/apps/amap/variables.tf b/modules/apps/amap/variables.tf new file mode 100644 index 0000000..c2feb6d --- /dev/null +++ b/modules/apps/amap/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 diff --git a/modules/apps/bookshelf/cloud-init/service.yaml b/modules/apps/bookshelf/cloud-init/service.yaml index 8429efa..22ca8e8 100644 --- a/modules/apps/bookshelf/cloud-init/service.yaml +++ b/modules/apps/bookshelf/cloud-init/service.yaml @@ -21,8 +21,6 @@ package_upgrade: false packages: - git - nfs-common - - docker.io - - docker-compose - curl - jq @@ -34,6 +32,10 @@ write_files: permissions: "0644" content: | ${env-file-content} + - path: /opt/${hostname}/install-docker.sh + permissions: "0755" + content: | + ${install-docker-script} - path: /usr/local/bin/restore-backup.sh permissions: "0755" content: | @@ -73,9 +75,7 @@ runcmd: - mount -t nfs ${proxmox_host_ip}:/main/backups /backups - systemctl enable --now create-backup.timer # Docker setup - - systemctl enable docker - - systemctl start docker - - usermod -aG docker ${hostname} + - /opt/${hostname}/install-docker.sh # Act_runner install - /opt/${hostname}/install-runner.sh - systemctl daemon-reload diff --git a/modules/apps/bookshelf/main.tf b/modules/apps/bookshelf/main.tf index e1a7203..96f6bbe 100644 --- a/modules/apps/bookshelf/main.tf +++ b/modules/apps/bookshelf/main.tf @@ -33,6 +33,7 @@ module "vm" { act_runner-install-script = indent(6, file("${path.module}/../common/scripts/install-runner.sh")) service-install-script = indent(6, file("${path.module}/../common/scripts/install-service-ci.sh")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) env-file-content = indent(6, file("${path.module}/.env")) } diff --git a/modules/apps/common/scripts/install-docker.sh b/modules/apps/common/scripts/install-docker.sh new file mode 100644 index 0000000..aac1258 --- /dev/null +++ b/modules/apps/common/scripts/install-docker.sh @@ -0,0 +1,23 @@ +#!/bin/bash +set -euo pipefail + +source /opt/environment/.env + +sudo apt update -y +sudo install -m 0755 -d /etc/apt/keyrings +sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc +sudo chmod a+r /etc/apt/keyrings/docker.asc + +sudo tee /etc/apt/sources.list.d/docker.sources < "$TRAEFIK_CONF" </dev/null | sort | tail -n1) + +if [ -n "$LATEST_BACKUP" ] && [ -f "$LATEST_BACKUP" ]; then + sudo -u $USERNAME docker cp "$LATEST_BACKUP" "crowdsec-metabase:/metabase-data/metabase.db/metabase.db.mv.db" +fi \ No newline at end of file diff --git a/modules/apps/gateway/main.tf b/modules/apps/gateway/main.tf index c8933f5..03574b9 100644 --- a/modules/apps/gateway/main.tf +++ b/modules/apps/gateway/main.tf @@ -22,9 +22,16 @@ module "vm" { hostname = var.hostname domain = var.domain ssh_key = var.ssh_public_key - proxmox_host_ip = var.proxmox_host_ip + proxmox_host_ip = var.proxmox_host_ip traefik-service = indent(6, file("${path.module}/lib/services/traefik.service")) install-traefik-script = indent(6, file("${path.module}/lib/scripts/install-traefik.sh")) + install-crowdsec-script = indent(6, file("${path.module}/lib/scripts/install-crowdsec.sh")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) + restore-backup-script = indent(6, file("${path.module}/lib/scripts/restore-backup.sh")) + restore-backup-service = indent(6, file("${path.module}/../common/services/docker/restore-backup.service")) + create-backup-script = indent(6, file("${path.module}/lib/scripts/create-backup.sh")) + create-backup-service = indent(6, file("${path.module}}/../common/services/docker/create-backup.service")) + create-backup-timer = indent(6, file("${path.module}}/../common/services/create-backup.timer")) nginx-error-configuration = indent(6, file("${path.module}/lib/scripts/default")) nginx-error-502 = indent(6, file("${path.module}/lib/scripts/502.html")) env-file-content = indent(6, file("${path.module}/.env")) diff --git a/modules/apps/girasol/.env.example b/modules/apps/girasol/.env.example new file mode 100644 index 0000000..66f159e --- /dev/null +++ b/modules/apps/girasol/.env.example @@ -0,0 +1,22 @@ +# Environment files +ENV_FILE_LOCATION=/opt/environment/.env + +# gitea act_runner +ACT_RUNNER_VERSION=0.2.13 +ACT_RUNNER_LOCATION=/usr/local/bin +ACT_RUNNER_USER=act_runner +GITEA_RUNNER_REGISTRATION_TOKEN= +USERNAME=girasol + +# Gitea instance +GITEA_INSTANCE_URL=https://gitea.aldon.fr +GITEA_SERVICE_APPLICATION_TOKEN= +GITEA_SERVICE_REPOSITORY=mop/girasol +GITEA_WORKFLOW_NAME=deploy.yaml + +# Application specifics + +# Backup specifics +SERVICE_BACKUPS_DIR=/backups/girasol +SERVICE_BACKUPS_PREFIX=girasol-dump +SERVICE_BACKUPS_EXTENSION=sql diff --git a/modules/apps/girasol/cloud-init/service.yaml b/modules/apps/girasol/cloud-init/service.yaml new file mode 100644 index 0000000..22ca8e8 --- /dev/null +++ b/modules/apps/girasol/cloud-init/service.yaml @@ -0,0 +1,89 @@ +#cloud-config +hostname: ${hostname} +local-hostname: ${hostname} +fqdn: ${hostname}.${domain} +manage_etc_hosts: true + +users: + - default + - name: ${hostname} + groups: sudo + 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 + - jq + +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: /opt/${hostname}/install-docker.sh + permissions: "0755" + content: | + ${install-docker-script} + - 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/act_runner.service + permissions: "0644" + content: | + ${act_runner-service} + - path: /opt/${hostname}/install-runner.sh + permissions: "0755" + content: | + ${act_runner-install-script} + - path: /opt/${hostname}/install-service.sh + permissions: "0755" + content: | + ${service-install-script} + +runcmd: + # Backup setup + - mkdir -p /backups + - mount -t nfs ${proxmox_host_ip}:/main/backups /backups + - systemctl enable --now create-backup.timer + # Docker setup + - /opt/${hostname}/install-docker.sh + # Act_runner install + - /opt/${hostname}/install-runner.sh + - systemctl daemon-reload + - systemctl enable act_runner.service + - systemctl start act_runner.service + # ${hostname} install + - /opt/${hostname}/install-service.sh + + +final_message: | + Base system ready for ${hostname} \ No newline at end of file diff --git a/modules/apps/girasol/lib/create-backup.sh b/modules/apps/girasol/lib/create-backup.sh new file mode 100644 index 0000000..83a2bc7 --- /dev/null +++ b/modules/apps/girasol/lib/create-backup.sh @@ -0,0 +1,7 @@ +source /opt/environment/.env + +TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S') + +# create backup file + +ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION | tail -n +5 | xargs -r rm -f diff --git a/modules/apps/girasol/lib/restore-backup.sh b/modules/apps/girasol/lib/restore-backup.sh new file mode 100644 index 0000000..9270da2 --- /dev/null +++ b/modules/apps/girasol/lib/restore-backup.sh @@ -0,0 +1,5 @@ +source /opt/environment/.env + +LATEST_BACKUP=$(ls -1 $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION 2>/dev/null | sort | tail -n1) + +# Restore backup file \ No newline at end of file diff --git a/modules/apps/girasol/main.tf b/modules/apps/girasol/main.tf new file mode 100644 index 0000000..3396eaf --- /dev/null +++ b/modules/apps/girasol/main.tf @@ -0,0 +1,41 @@ +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}/../common/services/docker/restore-backup.service")) + create-backup-script = indent(6, file("${path.module}/lib/scripts/create-backup.sh")) + create-backup-service = indent(6, file("${path.module}}/../common/services/docker/create-backup.service")) + create-backup-timer = indent(6, file("${path.module}/../common/services/create-backup.timer")) + + act_runner-service = indent(6, file("${path.module}/../common/services/act_runner.service")) + act_runner-install-script = indent(6, file("${path.module}/../common/scripts/install-runner.sh")) + + service-install-script = indent(6, file("${path.module}/../common/scripts/install-service-ci.sh")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) + + env-file-content = indent(6, file("${path.module}/.env")) + } + ) +} \ No newline at end of file diff --git a/modules/apps/girasol/output.tf b/modules/apps/girasol/output.tf new file mode 100644 index 0000000..f7ad914 --- /dev/null +++ b/modules/apps/girasol/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 = 80 + }] +} \ No newline at end of file diff --git a/modules/apps/girasol/variables.tf b/modules/apps/girasol/variables.tf new file mode 100644 index 0000000..c2feb6d --- /dev/null +++ b/modules/apps/girasol/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 diff --git a/modules/apps/gitea/cloud-init/service.yaml b/modules/apps/gitea/cloud-init/service.yaml index d46b482..6e2b7fb 100644 --- a/modules/apps/gitea/cloud-init/service.yaml +++ b/modules/apps/gitea/cloud-init/service.yaml @@ -24,8 +24,6 @@ package_upgrade: false packages: - git - nfs-common - - docker.io - - docker-compose - curl - unzip - postgresql @@ -39,6 +37,10 @@ write_files: permissions: "0644" content: | ${env-file-content} + - path: /opt/${hostname}/install-docker.sh + permissions: "0755" + content: | + ${install-docker-script} - path: /usr/local/bin/restore-backup.sh permissions: "0755" content: | @@ -74,9 +76,7 @@ runcmd: - mount -t nfs ${proxmox_host_ip}:/main/backups /backups - systemctl enable --now create-backup.timer # Docker setup - - systemctl enable docker - - systemctl start docker - - usermod -aG docker ${hostname} + - /opt/${hostname}/install-docker.sh # gitea setup - /opt/gitea/install-gitea.sh diff --git a/modules/apps/gitea/main.tf b/modules/apps/gitea/main.tf index 70ac8b6..9e8c1a1 100644 --- a/modules/apps/gitea/main.tf +++ b/modules/apps/gitea/main.tf @@ -31,6 +31,7 @@ module "vm" { install-gitea-script = indent(6, file("${path.module}/lib/scripts/install-gitea.sh")) gitea-service = indent(6, file("${path.module}/lib/services/gitea.service")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) env-file-content = indent(6, file("${path.module}/.env")) } diff --git a/modules/apps/keycloak/.env.example b/modules/apps/keycloak/.env.example new file mode 100644 index 0000000..fbd2048 --- /dev/null +++ b/modules/apps/keycloak/.env.example @@ -0,0 +1,22 @@ +JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 +KC_PROXY_HEADERS=forwarded +KC_HTTP_ENABLED=true +KC_DB=postgres +KC_DB_USERNAME=keycloak +KC_DB_PASSWORD= +KC_HOSTNAME=https://keycloak.aldon.fr + +#Running behind reverse proxy that handles TLS +KC_PROXY=edge + +#Create admin account on first run +KEYCLOAK_ADMIN=admin +KEYCLOAK_ADMIN_PASSWORD= + +KEYCLOAK_DIRECTORY=/home/keycloak/keycloak +KEYCLOAK_VERSION=26.2.4 + +# Backup specifics +SERVICE_BACKUPS_DIR=/backups/keycloak +SERVICE_BACKUPS_PREFIX=keycloak-dump +SERVICE_BACKUPS_EXTENSION=sql \ No newline at end of file diff --git a/modules/apps/keycloak/cloud-init/service.yaml b/modules/apps/keycloak/cloud-init/service.yaml new file mode 100644 index 0000000..97be3ae --- /dev/null +++ b/modules/apps/keycloak/cloud-init/service.yaml @@ -0,0 +1,71 @@ +#cloud-config +hostname: ${hostname} +local-hostname: ${hostname} +fqdn: ${hostname}.${domain} +manage_etc_hosts: true + +users: + - default + - name: ${hostname} + groups: sudo + 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 + - openjdk-21-jdk-headless + - postgresql + - postgresql-contrib + +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/keycloak.service + permissions: "0644" + content: | + ${keycloak-service} + +runcmd: + # Backup setup + - mkdir -p /backups + - mount -t nfs ${proxmox_host_ip}:/main/backups /backups + - systemctl enable --now create-backup.timer + + +final_message: | + Base system ready for ${hostname} \ No newline at end of file diff --git a/modules/apps/keycloak/lib/scripts/create-backup.sh b/modules/apps/keycloak/lib/scripts/create-backup.sh new file mode 100644 index 0000000..507c1c6 --- /dev/null +++ b/modules/apps/keycloak/lib/scripts/create-backup.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -euo pipefail + +source /opt/environment/.env + +TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S') + +# Backup realms + +sh $KEYCLOAK_DIRECTORY/kc.sh export --file $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-$TIMESTAMP.json + + +# Backup database +pg_dump -U keycloak -F c -b -v -f $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-$TIMESTAMP.$SERVICE_BACKUPS_EXTENSION + + +ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION | tail -n +5 | xargs -r rm -f +ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.json | tail -n +5 | xargs -r rm -f \ No newline at end of file diff --git a/modules/apps/keycloak/lib/scripts/install-keycloak.sh b/modules/apps/keycloak/lib/scripts/install-keycloak.sh new file mode 100644 index 0000000..4d59ad9 --- /dev/null +++ b/modules/apps/keycloak/lib/scripts/install-keycloak.sh @@ -0,0 +1,34 @@ +#//bin/bash + +# KEYCLOAK_DIRECTORY=/home/keycloak/keycloak +# KEYCLOAK_VERSION: 26.2.4 +# KC_DB_PASSWORD +# SERVICE_BACKUPS_DIR +# SERVICE_BACKUPS_PREFIX +# SERVICE_BACKUPS_EXTENSION + +if [ ! -f $KEYCLOAK_DIRECTORY ]; then + wget -O /tmp/keycloak.zip https://github.com/keycloak/keycloak/releases/download/$KEYCLOAK_VERSION/keycloak-$KEYCLOAK_VERSION.zip + unzip -o /tmp/keycloak /tmp/keycloak.zip -d /tmp + mv /tmp/keycloak $KEYCLOAK_DIRECTORY + chmod o+x $KEYCLOAK_DIRECTORY/bin +fi + +groupadd keycloak + +sudo -u postgres psql </dev/null 2>&1; then + echo "---- Backup found, restoring Gitea ----" + /usr/local/bin/restore-backup.sh +else + echo "---- No backup found in $SERVICE_BACKUPS_DIR, skipping restore ----" +fi + +sudo systemctl enable keycloak +sudo systemctl start keycloak \ No newline at end of file diff --git a/modules/apps/keycloak/lib/scripts/restore-backup.sh b/modules/apps/keycloak/lib/scripts/restore-backup.sh new file mode 100644 index 0000000..b7a5755 --- /dev/null +++ b/modules/apps/keycloak/lib/scripts/restore-backup.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +source /opt/environment/.env + +LATEST_BACKUP_DB=$(ls -1 $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION 2>/dev/null | sort | tail -n1) +LATEST_BACKUP_REALMS=$(ls -1 $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.json 2>/dev/null | sort | tail -n1) + +if [ -n "$LATEST_BACKUP_DB" ] && [ -f "$LATEST_BACKUP_DB" ]; then + psql -U keycloak $KC_DB < $LATEST_BACKUP_DB +fi + +if [ -n "$LATEST_BACKUP_REALMS" ] && [ -f "$LATEST_BACKUP_REALMS" ]; then + sh $KEYCLOAK_DIRECTORY/kc.sh import --file $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-$TIMESTAMP.json +fi diff --git a/modules/apps/keycloak/lib/services/create-backup.service b/modules/apps/keycloak/lib/services/create-backup.service new file mode 100644 index 0000000..b83a992 --- /dev/null +++ b/modules/apps/keycloak/lib/services/create-backup.service @@ -0,0 +1,9 @@ +[Unit] +Description=Backup Service +Wants=network.target +After=network.target + +[Service] +Type=oneshot +User=root +ExecStart=/usr/local/bin/backup.sh \ No newline at end of file diff --git a/modules/apps/keycloak/lib/services/keycloak.service b/modules/apps/keycloak/lib/services/keycloak.service new file mode 100644 index 0000000..ede21fb --- /dev/null +++ b/modules/apps/keycloak/lib/services/keycloak.service @@ -0,0 +1,17 @@ +[Unit] +Description=Keycloak Authorization Server +Requires=network.target +After=syslog.target network.target + +[Service] +Type=idle +User=keycloak +Group=keycloak +ExecStart=/home/keycloak/keycloak/bin/kc.sh start +ExecStop=/home/keycloak/keycloak/bin/kc.sh stop +Restart=always +RestartSec=15 +EnvironmentFile=/opt/environment/.env + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/modules/apps/keycloak/lib/services/restore-backup.service b/modules/apps/keycloak/lib/services/restore-backup.service new file mode 100644 index 0000000..f75614c --- /dev/null +++ b/modules/apps/keycloak/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/keycloak/main.tf b/modules/apps/keycloak/main.tf new file mode 100644 index 0000000..0b6615d --- /dev/null +++ b/modules/apps/keycloak/main.tf @@ -0,0 +1,35 @@ +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")) + + env-file-content = indent(6, file("${path.module}/.env")) + } + ) +} \ No newline at end of file diff --git a/modules/apps/keycloak/output.tf b/modules/apps/keycloak/output.tf new file mode 100644 index 0000000..326caa9 --- /dev/null +++ b/modules/apps/keycloak/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 = 8080 + }] +} \ No newline at end of file diff --git a/modules/apps/keycloak/variables.tf b/modules/apps/keycloak/variables.tf new file mode 100644 index 0000000..c2feb6d --- /dev/null +++ b/modules/apps/keycloak/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 diff --git a/modules/apps/n8n/.env.example b/modules/apps/n8n/.env.example new file mode 100644 index 0000000..e69de29 diff --git a/modules/apps/n8n/cloud-init/service.yaml b/modules/apps/n8n/cloud-init/service.yaml new file mode 100644 index 0000000..79afd7b --- /dev/null +++ b/modules/apps/n8n/cloud-init/service.yaml @@ -0,0 +1,91 @@ +#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 + - ca-certificates + - gnupg + - 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: /opt/n8n/install-n8n.sh + permissions: "0755" + content: | + ${install-n8n-script} + - path: /opt/n8n/install-docker.sh + permissions: "0755" + content: | + ${install-docker-script} + - path: /home/n8n/docker-compose.yaml + permissions: "0755" + content: | + ${n8n-docker-compose} + - path: /home/n8n/init-data.sh + permissions: "0755" + content: | + ${n8n-init-data} + + +runcmd: + # Docker install + - /opt/n8n/install-docker.sh + # Backup setup + - mkdir -p /backups + - mount -t nfs ${proxmox_host_ip}:/main/backups /backups + - systemctl enable --now create-backup.timer + # Install n8n + - /opt/n8n/install-n8n.sh + +final_message: | + Base system ready for ${hostname} \ No newline at end of file diff --git a/modules/apps/n8n/lib/scripts/create-backup.sh b/modules/apps/n8n/lib/scripts/create-backup.sh new file mode 100644 index 0000000..3f1cd0d --- /dev/null +++ b/modules/apps/n8n/lib/scripts/create-backup.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -euo pipefail + +source /opt/environment/.env + +TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S') + +sudo -u $USERNAME docker exec -i n8n-postgres-1 pg_dump -F c -U $DB_USER -d $DB_NAME > $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-$TIMESTAMP.$SERVICE_BACKUPS_EXTENSION + +ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION | tail -n +5 | xargs -r rm -f diff --git a/modules/apps/n8n/lib/scripts/init-data.sh b/modules/apps/n8n/lib/scripts/init-data.sh new file mode 100644 index 0000000..df82df9 --- /dev/null +++ b/modules/apps/n8n/lib/scripts/init-data.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -e + +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL + CREATE USER $POSTGRES_NON_ROOT_USER WITH PASSWORD '$POSTGRES_NON_ROOT_PASSWORD'; + CREATE DATABASE $POSTGRES_DB; + GRANT ALL PRIVILEGES ON DATABASE $POSTGRES_DB TO $POSTGRES_NON_ROOT_USER; +EOSQL \ No newline at end of file diff --git a/modules/apps/n8n/lib/scripts/install-n8n.sh b/modules/apps/n8n/lib/scripts/install-n8n.sh new file mode 100644 index 0000000..1607b45 --- /dev/null +++ b/modules/apps/n8n/lib/scripts/install-n8n.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#https://docs.n8n.io/hosting/installation/docker/#using-with-postgresql + +set -euo pipefail + +source /opt/environment/.env + +cd $SERVICE_WORKDIR +cp /opt/environment/.env $SERVICE_WORKDIR/.env +docker-compose up -d \ No newline at end of file diff --git a/modules/apps/n8n/lib/scripts/restore-backup.sh b/modules/apps/n8n/lib/scripts/restore-backup.sh new file mode 100644 index 0000000..876717b --- /dev/null +++ b/modules/apps/n8n/lib/scripts/restore-backup.sh @@ -0,0 +1,10 @@ +#!/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 + sudo -u $USERNAME docker exec -i n8n-postgres-1 pg_restore --clean --if-exists -U "$DB_USER" -v -d "$DB_NAME" < $LATEST_BACKUP +fi \ No newline at end of file diff --git a/modules/apps/n8n/lib/services/docker-compose.yaml b/modules/apps/n8n/lib/services/docker-compose.yaml new file mode 100644 index 0000000..39c654c --- /dev/null +++ b/modules/apps/n8n/lib/services/docker-compose.yaml @@ -0,0 +1,54 @@ +volumes: + db_storage: + n8n_storage: + +services: + postgres: + image: postgres:16 + restart: always + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_NON_ROOT_USER=${POSTGRES_NON_ROOT_USER} + - POSTGRES_NON_ROOT_PASSWORD=${POSTGRES_NON_ROOT_PASSWORD} + volumes: + - db_storage:/var/lib/postgresql/data + - ./init-data.sh:/docker-entrypoint-initdb.d/init-data.sh + healthcheck: + test: ['CMD-SHELL', 'pg_isready -h localhost -U ${POSTGRES_USER} -d ${POSTGRES_DB}'] + interval: 5s + timeout: 5s + retries: 10 + + n8n: + image: docker.n8n.io/n8nio/n8n:${N8N_VERSION} + restart: always + environment: + - DB_TYPE=postgresdb + - DB_POSTGRESDB_HOST=postgres + - DB_POSTGRESDB_PORT=5432 + - DB_POSTGRESDB_DATABASE=${POSTGRES_DB} + - DB_POSTGRESDB_USER=${POSTGRES_USER} + - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD} + - N8N_RUNNERS_MODE=external + - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN} + - N8N_RUNNERS_BROKER_LISTEN_ADDRESS=0.0.0.0 + ports: + - 5678:5678 + links: + - postgres + volumes: + - n8n_storage:/home/node/.n8n + depends_on: + postgres: + condition: service_healthy + + n8n-runner: + image: n8nio/runners:${N8N_VERSION} + restart: always + environment: + - N8N_RUNNERS_AUTH_TOKEN=${RUNNERS_AUTH_TOKEN} + - N8N_RUNNERS_TASK_BROKER_URI=http://n8n:5679 + depends_on: + - n8n diff --git a/modules/apps/n8n/main.tf b/modules/apps/n8n/main.tf new file mode 100644 index 0000000..422bfa9 --- /dev/null +++ b/modules/apps/n8n/main.tf @@ -0,0 +1,39 @@ +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}/../common/services/docker/restore-backup.service")) + create-backup-script = indent(6, file("${path.module}/lib/scripts/create-backup.sh")) + create-backup-timer = indent(6, file("${path.module}/../common/services/create-backup.timer")) + create-backup-service = indent(6, file("${path.module}/../common/services/docker/create-backup.service")) + + install-n8n-script = indent(6, file("${path.module}/lib/scripts/install-n8n.sh")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) + n8n-docker-compose = indent(6, file("${path.module}/lib/services/docker-compose.yaml")) + n8n-init-data = indent(6, file("${path.module}/lib/scripts/init-data.sh")) + env-file-content = indent(6, file("${path.module}/.env")) + } + ) +} \ No newline at end of file diff --git a/modules/apps/n8n/output.tf b/modules/apps/n8n/output.tf new file mode 100644 index 0000000..c318a13 --- /dev/null +++ b/modules/apps/n8n/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 = 5678 + }] +} \ No newline at end of file diff --git a/modules/apps/n8n/variables.tf b/modules/apps/n8n/variables.tf new file mode 100644 index 0000000..3610517 --- /dev/null +++ b/modules/apps/n8n/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 diff --git a/modules/apps/rocket/main.tf b/modules/apps/rocket/main.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/apps/rocket/output.tf b/modules/apps/rocket/output.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/apps/rocket/variables.tf b/modules/apps/rocket/variables.tf new file mode 100644 index 0000000..e69de29 diff --git a/modules/apps/windmill/.env.example b/modules/apps/windmill/.env.example new file mode 100644 index 0000000..9af3469 --- /dev/null +++ b/modules/apps/windmill/.env.example @@ -0,0 +1,15 @@ +# Environment files +ENV_FILE_LOCATION=/opt/environment/.env + +# Application specifics +DATABASE_URL=postgres://postgres:changeme@db/windmill?sslmode=disable +DB_USER=postgres +DB_NAME=windmill +DB_PASS= +WM_IMAGE=ghcr.io/windmill-labs/windmill:main +SERVICE_WORKDIR=/home/windmill + +# Backup specifics +SERVICE_BACKUPS_DIR=/backups/windmill +SERVICE_BACKUPS_PREFIX=windmill-dump +SERVICE_BACKUPS_EXTENSION=dump \ No newline at end of file diff --git a/modules/apps/windmill/cloud-init/service.yaml b/modules/apps/windmill/cloud-init/service.yaml new file mode 100644 index 0000000..c6274f8 --- /dev/null +++ b/modules/apps/windmill/cloud-init/service.yaml @@ -0,0 +1,89 @@ +#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: /opt/${hostname}/install-docker.sh + permissions: "0755" + content: | + ${install-docker-script} + - 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: /opt/windmill/install-windmill.sh + permissions: "0755" + content: | + ${install-windmill-script} + - path: /home/windmill/docker-compose.yaml + permissions: "0755" + content: | + ${windmill-docker-compose} + - path: /home/windmill/Caddyfile + permissions: "0755" + content: | + ${windmill-caddyfile} + + +runcmd: + # Backup setup + - mkdir -p /backups + - mount -t nfs ${proxmox_host_ip}:/main/backups /backups + - systemctl enable --now create-backup.timer + # Docker setup + - /opt/${hostname}/install-docker.sh + # windmill setup + - /opt/windmill/install-windmill.sh + +final_message: | + Base system ready for ${hostname} \ No newline at end of file diff --git a/modules/apps/windmill/lib/scripts/create-backup.sh b/modules/apps/windmill/lib/scripts/create-backup.sh new file mode 100644 index 0000000..edc07ec --- /dev/null +++ b/modules/apps/windmill/lib/scripts/create-backup.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +#SERVICE_BACKUPS_DIR +#SERVICE_BACKUPS_PREFIX +#SERVICE_BACKUPS_EXTENSION + +set -euo pipefail + +source /opt/environment/.env + +TIMESTAMP=$(date +'%Y-%m-%d_%H%M%S') + +# docker exec $DB_SERVICE + +ls -1dt $SERVICE_BACKUPS_DIR/$SERVICE_BACKUPS_PREFIX-*.$SERVICE_BACKUPS_EXTENSION | tail -n +5 | xargs -r rm -f diff --git a/modules/apps/windmill/lib/scripts/install-windmill.sh b/modules/apps/windmill/lib/scripts/install-windmill.sh new file mode 100644 index 0000000..387f40e --- /dev/null +++ b/modules/apps/windmill/lib/scripts/install-windmill.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#https://www.windmill.dev/docs/advanced/self_host + +set -euo pipefail + +source /opt/environment/.env + +cd $SERVICE_WORKDIR +cp /opt/environment/.env $SERVICE_WORKDIR/.env +docker-compose up -d \ No newline at end of file diff --git a/modules/apps/windmill/lib/scripts/restore-backup.sh b/modules/apps/windmill/lib/scripts/restore-backup.sh new file mode 100644 index 0000000..20cc6b2 --- /dev/null +++ b/modules/apps/windmill/lib/scripts/restore-backup.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +#USERNAME +#SERVICE_BACKUPS_DIR +#SERVICE_BACKUPS_PREFIX +#SERVICE_BACKUPS_EXTENSION +#DB_USER +#DB_NAME + +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 \ No newline at end of file diff --git a/modules/apps/windmill/lib/services/Caddyfile b/modules/apps/windmill/lib/services/Caddyfile new file mode 100644 index 0000000..d01ca0d --- /dev/null +++ b/modules/apps/windmill/lib/services/Caddyfile @@ -0,0 +1,35 @@ +{ + layer4 { + :25 { + proxy { + to windmill_server:2525 + } + } + } +} + +{$BASE_URL} { + bind {$ADDRESS} + + # LSP - Language Server Protocol for code intelligence (windmill_extra:3001) + reverse_proxy /ws/* http://windmill_extra:3001 + + # Multiplayer - Real-time collaboration, Enterprise Edition (windmill_extra:3002) + # Uncomment and set ENABLE_MULTIPLAYER=true in docker-compose.yml + # reverse_proxy /ws_mp/* http://windmill_extra:3002 + + # Debugger - Interactive debugging via DAP WebSocket (windmill_extra:3003) + # Set ENABLE_DEBUGGER=true in docker-compose.yml to enable + handle_path /ws_debug/* { + reverse_proxy http://windmill_extra:3003 + } + + # Search indexer, Enterprise Edition (windmill_indexer:8002) + # reverse_proxy /api/srch/* http://windmill_indexer:8002 + + # Default: Windmill server + reverse_proxy /* http://windmill_server:8000 + + # TLS with custom certificates + # tls /certs/cert.pem /certs/key.pem +} \ No newline at end of file diff --git a/modules/apps/windmill/lib/services/docker-compose.yaml b/modules/apps/windmill/lib/services/docker-compose.yaml new file mode 100644 index 0000000..26f939e --- /dev/null +++ b/modules/apps/windmill/lib/services/docker-compose.yaml @@ -0,0 +1,222 @@ +version: "3.7" + +x-logging: &default-logging + driver: "json-file" + options: + max-size: "${LOG_MAX_SIZE:-20m}" + max-file: "${LOG_MAX_FILE:-10}" + compress: "true" + +services: + db: + deploy: + # To use an external database, set replicas to 0 and set DATABASE_URL to the external database url in the .env file + replicas: 1 + image: postgres:16 + shm_size: 1g + restart: unless-stopped + volumes: + - db_data:/var/lib/postgresql/data + expose: + - 5432 + environment: + POSTGRES_PASSWORD: ${DB_PASS} + POSTGRES_DB: ${DB_NAME} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + logging: *default-logging + + windmill_server: + image: ${WM_IMAGE} + pull_policy: always + deploy: + replicas: 1 + restart: unless-stopped + expose: + - 8000 + - 2525 + environment: + - DATABASE_URL=${DATABASE_URL} + - MODE=server + depends_on: + db: + condition: service_healthy + volumes: + - worker_logs:/tmp/windmill/logs + + logging: *default-logging + + windmill_worker: + image: ${WM_IMAGE} + pull_policy: always + deploy: + replicas: 3 + resources: + limits: + cpus: "1" + memory: 2048M + # for GB, use syntax '2Gi' + restart: unless-stopped + # Uncomment to enable PID namespace isolation (recommended for security) + # Requires privileged mode for --mount-proc flag + # See: https://www.windmill.dev/docs/advanced/security_isolation + # privileged: true + environment: + - DATABASE_URL=${DATABASE_URL} + - MODE=worker + - WORKER_GROUP=default + # If running with non-root/non-windmill UID (e.g., user: "1001:1001"), + # add: - HOME=/tmp + # Uncomment to enable PID namespace isolation (requires privileged: true above) + # - ENABLE_UNSHARE_PID=true + depends_on: + db: + condition: service_healthy + # to mount the worker folder to debug, KEEP_JOB_DIR=true and mount /tmp/windmill + volumes: + # mount the docker socket to allow to run docker containers from within the workers + - /var/run/docker.sock:/var/run/docker.sock + - worker_dependency_cache:/tmp/windmill/cache + - worker_logs:/tmp/windmill/logs + + logging: *default-logging + + ## This worker is specialized for "native" jobs. Native jobs run in-process and thus are much more lightweight than other jobs + windmill_worker_native: + # Use ghcr.io/windmill-labs/windmill-ee:main for the ee + image: ${WM_IMAGE} + pull_policy: always + deploy: + replicas: 1 + resources: + limits: + cpus: "1" + memory: 2048M + # for GB, use syntax '2Gi' + restart: unless-stopped + # Uncomment to enable PID namespace isolation (recommended for security) + # Requires privileged mode for --mount-proc flag + # See: https://www.windmill.dev/docs/advanced/security_isolation + # privileged: true + environment: + - DATABASE_URL=${DATABASE_URL} + - MODE=worker + - WORKER_GROUP=native + - NUM_WORKERS=8 + - SLEEP_QUEUE=200 + # Uncomment to enable PID namespace isolation (requires privileged: true above) + # - ENABLE_UNSHARE_PID=true + depends_on: + db: + condition: service_healthy + volumes: + - worker_logs:/tmp/windmill/logs + logging: *default-logging + # This worker is specialized for reports or scraping jobs. It is assigned the "reports" worker group which has an init script that installs chromium and can be targeted by using the "chromium" worker tag. + # windmill_worker_reports: + # image: ${WM_IMAGE} + # pull_policy: always + # deploy: + # replicas: 1 + # resources: + # limits: + # cpus: "1" + # memory: 2048M + # # for GB, use syntax '2Gi' + # restart: unless-stopped + # # Uncomment to enable PID namespace isolation (recommended for security) + # # Requires privileged mode for --mount-proc flag + # # See: https://www.windmill.dev/docs/advanced/security_isolation + # # privileged: true + # environment: + # - DATABASE_URL=${DATABASE_URL} + # - MODE=worker + # - WORKER_GROUP=reports + # # Uncomment to enable PID namespace isolation (requires privileged: true above) + # # - ENABLE_UNSHARE_PID=true + # depends_on: + # db: + # condition: service_healthy + # # to mount the worker folder to debug, KEEP_JOB_DIR=true and mount /tmp/windmill + # volumes: + # # mount the docker socket to allow to run docker containers from within the workers + # - /var/run/docker.sock:/var/run/docker.sock + # - worker_dependency_cache:/tmp/windmill/cache + # - worker_logs:/tmp/windmill/logs + + # The indexer powers full-text job and log search, an EE feature. + windmill_indexer: + image: ${WM_IMAGE} + pull_policy: always + deploy: + replicas: 0 # set to 1 to enable full-text job and log search + restart: unless-stopped + expose: + - 8002 + environment: + - PORT=8002 + - DATABASE_URL=${DATABASE_URL} + - MODE=indexer + depends_on: + db: + condition: service_healthy + volumes: + - windmill_index:/tmp/windmill/search + - worker_logs:/tmp/windmill/logs + logging: *default-logging + + # Combined extra services: LSP, Multiplayer, and Debugger + # Each service can be enabled/disabled via environment variables: + # - ENABLE_LSP=true (default) - Language Server Protocol for code intelligence + # - ENABLE_MULTIPLAYER=false - Real-time collaboration (Enterprise Edition) + # - ENABLE_DEBUGGER=false - Interactive debugging via DAP WebSocket + windmill_extra: + image: ghcr.io/windmill-labs/windmill-extra:latest + pull_policy: always + restart: unless-stopped + expose: + - 3001 # LSP + - 3002 # Multiplayer + - 3003 # Debugger + environment: + - ENABLE_LSP=true + - ENABLE_MULTIPLAYER=false # Set to true to enable multiplayer (Enterprise Edition) + - ENABLE_DEBUGGER=true # Set to true to enable debugger + - DEBUGGER_PORT=3003 # Debugger service port + - ENABLE_NSJAIL=false # Set to true for nsjail sandboxing (requires privileged: true) + - REQUIRE_SIGNED_DEBUG_REQUESTS=false # Set to true to require JWT tokens for debug sessions + - WINDMILL_BASE_URL=http://windmill_server:8000 + volumes: + - lsp_cache:/pyls/.cache + logging: *default-logging + + caddy: + image: ghcr.io/windmill-labs/caddy-l4:latest + restart: unless-stopped + # Configure the mounted Caddyfile and the exposed ports or use another reverse proxy if needed + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - caddy_data:/data + # - ./certs:/certs # Provide custom certificate files like cert.pem and key.pem to enable HTTPS - See the corresponding section in the Caddyfile + ports: + # To change the exposed port, simply change 80:80 to :80. No other changes needed + - 80:80 + - 25:25 + # - 443:443 # Uncomment to enable HTTPS handling by Caddy + environment: + - BASE_URL=":80" + # - BASE_URL=":443" # uncomment and comment line above to enable HTTPS via custom certificate and key files + # - BASE_URL=mydomain.com # Uncomment and comment line above to enable HTTPS handling by Caddy + logging: *default-logging + +volumes: + db_data: null + worker_dependency_cache: null + worker_logs: null + worker_memory: null + windmill_index: null + lsp_cache: null + caddy_data: null \ No newline at end of file diff --git a/modules/apps/windmill/main.tf b/modules/apps/windmill/main.tf new file mode 100644 index 0000000..e1429c3 --- /dev/null +++ b/modules/apps/windmill/main.tf @@ -0,0 +1,41 @@ +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}/../common/services/docker/restore-backup.service")) + create-backup-script = indent(6, file("${path.module}/lib/scripts/create-backup.sh")) + create-backup-timer = indent(6, file("${path.module}/../common/services/create-backup.timer")) + create-backup-service = indent(6, file("${path.module}/../common/services/docker/create-backup.service")) + + install-windmill-script = indent(6, file("${path.module}/lib/scripts/install-windmill.sh")) + + windmill-docker-compose = indent(6, file("${path.module}/lib/services/docker-compose.yaml")) + windmill-caddyfile = indent(6, file("${path.module}/lib/services/Caddyfile")) + install-docker-script = indent(6, file("${path.module}/../common/scripts/install-docker.sh")) + + env-file-content = indent(6, file("${path.module}/.env")) + } + ) +} \ No newline at end of file diff --git a/modules/apps/windmill/output.tf b/modules/apps/windmill/output.tf new file mode 100644 index 0000000..f7ad914 --- /dev/null +++ b/modules/apps/windmill/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 = 80 + }] +} \ No newline at end of file diff --git a/modules/apps/windmill/variables.tf b/modules/apps/windmill/variables.tf new file mode 100644 index 0000000..c2feb6d --- /dev/null +++ b/modules/apps/windmill/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 diff --git a/templates/traefik.services.tpl b/templates/traefik.services.tpl index 8529a63..dac7aa6 100644 --- a/templates/traefik.services.tpl +++ b/templates/traefik.services.tpl @@ -56,6 +56,23 @@ http: certResolver: letsencrypt middlewares: - redirect-errors + mathieu: + rule: "Host(`mathieu.wiki`)" + entryPoints: + - websecure + service: noop + tls: + certResolver: letsencrypt + middlewares: + - redirect-to-mathieu + - redirect-errors + mathieu-http: + rule: "Host(`mathieu.wiki`)" + entryPoints: + - web + middlewares: + - redirect-to-mathieu + service: noop wiki: rule: "Host(`benoit.mathieu.wiki`)" entryPoints: @@ -131,6 +148,11 @@ http: servers: - url: "http://127.0.0.1:8090" middlewares: + redirect-to-mathieu: + redirectRegex: + regex: "^https?://mathieu.wiki/(.*)" + replacement: "https://benoit.mathieu.wiki/$1" + permanent: true redirect-to-aldon: redirectRegex: regex: "^https?://aldon.fr/(.*)"