From 08f705ffd7a904f3ca84b355b570c3e8f7021665 Mon Sep 17 00:00:00 2001 From: thesabear Date: Mon, 6 Jul 2026 02:25:54 +0300 Subject: [PATCH] Add sanitized compose for caddy-vm and automation-vm stacks Caddy (+ a truncated/sanitized example Caddyfile showing the mTLS + Authentik forward-auth pattern without the real subdomain list), Hawser, Gitea (private instance only, dropped the public-mirror service - that's already its own public thing), Kestra (genericized the ansible-repo/SSH-key bind mounts), Mosquitto, n8n, NetBox, Node-RED. --- Docker/Caddy/Caddyfile | 68 ++++++++++++++++ Docker/Caddy/docker-compose.yaml | 18 +++++ Docker/Gitea/docker-compose.yaml | 48 ++++++++++++ Docker/Hawser/docker-compose.yaml | 19 +++++ Docker/Kestra/docker-compose.yaml | 75 ++++++++++++++++++ Docker/Mosquitto/docker-compose.yaml | 19 +++++ Docker/N8n/docker-compose.yaml | 64 +++++++++++++++ Docker/NetBox/docker-compose.yaml | 112 +++++++++++++++++++++++++++ Docker/Node-RED/docker-compose.yaml | 19 +++++ 9 files changed, 442 insertions(+) create mode 100644 Docker/Caddy/Caddyfile create mode 100644 Docker/Caddy/docker-compose.yaml create mode 100644 Docker/Gitea/docker-compose.yaml create mode 100644 Docker/Hawser/docker-compose.yaml create mode 100644 Docker/Kestra/docker-compose.yaml create mode 100644 Docker/Mosquitto/docker-compose.yaml create mode 100644 Docker/N8n/docker-compose.yaml create mode 100644 Docker/NetBox/docker-compose.yaml create mode 100644 Docker/Node-RED/docker-compose.yaml diff --git a/Docker/Caddy/Caddyfile b/Docker/Caddy/Caddyfile new file mode 100644 index 0000000..9e5ae38 --- /dev/null +++ b/Docker/Caddy/Caddyfile @@ -0,0 +1,68 @@ +# Truncated, sanitized example - real Caddyfile has one block per app. +# Shows the pattern: mTLS + Authentik forward-auth in front of every +# reverse-proxied service. + +{ + servers { + protocols h1 h2 + } +} + +# ------------------------- +# mTLS +# ------------------------- +(local_mtls) { + tls /etc/caddy/certs/example.com.crt /etc/caddy/certs/example.com.key { + client_auth { + mode require_and_verify + + trust_pool file { + pem_file /etc/caddy/certs/example.com.ca.crt + } + } + } +} + +# ------------------------- +# Authentik forward auth +# ------------------------- +(authentik_forward_auth) { + forward_auth http://authentik.internal:9054 { + uri /outpost.goauthentik.io/auth/caddy + + trusted_proxies private_ranges + + header_up Host {host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Proto {scheme} + header_up X-Forwarded-For {remote_host} + header_up X-Real-IP {remote_host} + + copy_headers { + X-Authentik-Username + X-Authentik-Email + X-Authentik-Groups + X-Authentik-Uid + } + } +} + +# ------------------------- +# Example app entries +# ------------------------- +app1.example.com { + import local_mtls + import authentik_forward_auth + reverse_proxy http://app1.internal:8080 +} + +app2.example.com { + import local_mtls + reverse_proxy http://app2.internal:9000 { + header_up Host {host} + header_up X-Forwarded-Host {host} + header_up X-Forwarded-Proto {scheme} + header_up X-Forwarded-For {remote_host} + header_up X-Real-IP {remote_host} + } +} diff --git a/Docker/Caddy/docker-compose.yaml b/Docker/Caddy/docker-compose.yaml new file mode 100644 index 0000000..d5cc860 --- /dev/null +++ b/Docker/Caddy/docker-compose.yaml @@ -0,0 +1,18 @@ +services: + caddy: + image: caddy:latest + container_name: caddy + restart: always + ports: + - "${HTTPS_PORT}:443" + volumes: + - ./Caddyfile:/etc/caddy/Caddyfile + - /path/to/caddy/caddy_data:/data + - /path/to/caddy/caddy_config:/config + - /etc/caddy/certs:/etc/caddy/certs + networks: + - caddy-net + +networks: + caddy-net: + external: true diff --git a/Docker/Gitea/docker-compose.yaml b/Docker/Gitea/docker-compose.yaml new file mode 100644 index 0000000..638b5d3 --- /dev/null +++ b/Docker/Gitea/docker-compose.yaml @@ -0,0 +1,48 @@ +services: + gitea: + image: gitea/gitea:latest + container_name: gitea + environment: + - PUID=${PUID} + - PGID=${PGID} + - TZ=${TZ} + - GITEA__database__DB_TYPE=postgres + - GITEA__database__HOST=gitea-db + - GITEA__database__PORT=5432 + - GITEA__database__NAME=${POSTGRES_DB} + - GITEA__database__USER=${POSTGRES_USER} + - GITEA__database__PASSWD=${POSTGRES_PASSWORD} + - ROOT_URL=${GITEA_ROOT_URL} + - DOMAIN=${GITEA_DOMAIN} + - GITEA__migrations__ALLOW_LOCALNETWORKS=true + restart: always + volumes: + - /path/to/gitea:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "${HTTP_PORT}:3000" + - "${SSH_PORT}:22" + depends_on: + - gitea-db + security_opt: + - no-new-privileges:true + networks: + - gitea-net + + gitea-db: + image: postgres:latest + container_name: gitea-db + restart: always + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_DB=${POSTGRES_DB} + volumes: + - /path/to/gitea/postgres:/var/lib/postgresql + networks: + - gitea-net + +networks: + gitea-net: + external: true diff --git a/Docker/Hawser/docker-compose.yaml b/Docker/Hawser/docker-compose.yaml new file mode 100644 index 0000000..44f135b --- /dev/null +++ b/Docker/Hawser/docker-compose.yaml @@ -0,0 +1,19 @@ +services: + hawser: + image: ghcr.io/finsys/hawser:latest + container_name: hawser + restart: unless-stopped + ports: + - "${HTTP_PORT}:2376" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /path/to/hawser/hawser_stacks:/data/stacks + environment: + - TOKEN=${TOKEN} + - TZ=${TZ} + networks: + - hawser-net + +networks: + hawser-net: + external: true diff --git a/Docker/Kestra/docker-compose.yaml b/Docker/Kestra/docker-compose.yaml new file mode 100644 index 0000000..1f6bcb1 --- /dev/null +++ b/Docker/Kestra/docker-compose.yaml @@ -0,0 +1,75 @@ +services: + postgres: + image: postgres:18 + container_name: kestra-postgres + volumes: + - /path/to/kestra/postgres-data:/var/lib/postgresql + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"] + interval: 30s + timeout: 10s + retries: 10 + networks: + - kestra-net + + kestra: + image: kestra/kestra:latest + container_name: kestra + pull_policy: always + # Kestra, by default, has a termination grace period of 5m. We need to wait a little more to be sure no active tasks are running. + stop_grace_period: 6m + # Note that this setup with a root user is intended for development purpose. + # Our base image runs without root, but the Docker Compose implementation needs root to access the Docker socket + user: "root" + restart: unless-stopped + command: server standalone + volumes: + - /path/to/kestra/kestra-data:/app/storage + - /var/run/docker.sock:/var/run/docker.sock + - /tmp/kestra-wd:/tmp/kestra-wd + # Mounted read-only so Kestra flows can drive the ansible repo directly + - /path/to/repos/ansible:/opt/repos/ansible:ro + - /path/to/ansible-venv:/home/user/ansible-venv:ro + - /path/to/ssh-keys:/home/user/.ssh:ro + environment: + KESTRA_CONFIGURATION: | + datasources: + postgres: + url: jdbc:postgresql://postgres:5432/kestra + driverClassName: org.postgresql.Driver + username: ${POSTGRES_USER} + password: ${POSTGRES_PASSWORD} + kestra: + server: + basic-auth: + username: ${USERNAME} + password: ${PASSWORD} + repository: + type: postgres + storage: + type: local + local: + base-path: "/app/storage" + queue: + type: postgres + tasks: + tmp-dir: + path: /tmp/kestra-wd/tmp + url: http://localhost:8080/ + ports: + - "${HTTP_PORT}:8080" + - "8081:8081" + depends_on: + postgres: + condition: service_started + networks: + - kestra-net + +networks: + kestra-net: + external: true diff --git a/Docker/Mosquitto/docker-compose.yaml b/Docker/Mosquitto/docker-compose.yaml new file mode 100644 index 0000000..58a530e --- /dev/null +++ b/Docker/Mosquitto/docker-compose.yaml @@ -0,0 +1,19 @@ +services: + mosquitto: + image: eclipse-mosquitto:latest + container_name: mosquitto + restart: unless-stopped + ports: + - "${HTTP_PORT}:1883" + volumes: + - /path/to/mosquitto/config/mosquitto.conf:/mosquitto/config/mosquitto.conf:ro + - /path/to/mosquitto/config/passwords:/mosquitto/config/passwords:ro + - /path/to/mosquitto/config/acl:/mosquitto/config/acl:ro + - /path/to/mosquitto/data:/mosquitto/data + - /path/to/mosquitto/log:/mosquitto/log + networks: + - notifier-net + +networks: + notifier-net: + external: true diff --git a/Docker/N8n/docker-compose.yaml b/Docker/N8n/docker-compose.yaml new file mode 100644 index 0000000..c4b5052 --- /dev/null +++ b/Docker/N8n/docker-compose.yaml @@ -0,0 +1,64 @@ +services: + n8n: + image: n8nio/n8n:latest + container_name: n8n + restart: unless-stopped + security_opt: + - no-new-privileges:true + environment: + - PUID=${PUID} + - PGID=${PGID} + - TZ=${TZ} + - GENERIC_TIMEZONE=${TZ} + - N8N_HOST=${N8N_HOST} + - N8N_PORT=${N8N_PORT} + - N8N_PROTOCOL=https + - DB_TYPE=postgresdb + - DB_POSTGRESDB_HOST=postgres + - DB_POSTGRESDB_PORT=5432 + - DB_POSTGRESDB_DATABASE=n8n + - DB_POSTGRESDB_USER=n8n + - DB_POSTGRESDB_PASSWORD=${N8N_POSTGRES_PASSWORD} + - N8N_BASIC_AUTH_ACTIVE=true + - N8N_BASIC_AUTH_USER=${N8N_USER} + - N8N_BASIC_AUTH_PASSWORD=${N8N_BASIC_AUTH_PASSWORD} + - WEBHOOK_URL=https://${N8N_HOST} + - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true + volumes: + - /path/to/n8n/data:/home/node/ + ports: + - ${N8N_PORT}:5678 + depends_on: + - postgres + networks: + - n8n-net + + postgres: + image: postgres:latest + container_name: n8n-postgres + restart: unless-stopped + security_opt: + - no-new-privileges:true + environment: + POSTGRES_USER: n8n + POSTGRES_PASSWORD: ${N8N_POSTGRES_PASSWORD} + POSTGRES_DB: n8n + volumes: + - /path/to/n8n/postgres_data:/var/lib/postgresql + ports: + - "127.0.0.1:${POSTGRES_PORT}:5432" + networks: + - n8n-net + + adminer: + image: adminer:latest + container_name: adminer + restart: unless-stopped + ports: + - "127.0.0.1:${ADMINER_PORT}:8080" + networks: + - n8n-net + +networks: + n8n-net: + external: true diff --git a/Docker/NetBox/docker-compose.yaml b/Docker/NetBox/docker-compose.yaml new file mode 100644 index 0000000..e61b261 --- /dev/null +++ b/Docker/NetBox/docker-compose.yaml @@ -0,0 +1,112 @@ +services: + postgres: + image: postgres:17-alpine + container_name: netbox-postgres + restart: unless-stopped + environment: + POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_USER: ${POSTGRES_USER} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} + volumes: + - /path/to/netbox/postgres_data:/var/lib/postgresql/data + healthcheck: + test: pg_isready -q -t 2 -d $$POSTGRES_DB -U $$POSTGRES_USER + start_period: 20s + timeout: 30s + interval: 10s + retries: 5 + networks: + - netbox-net + + redis: + image: valkey/valkey:9.0-alpine + container_name: netbox-redis + restart: unless-stopped + command: + - sh + - -c + - valkey-server --appendonly yes --requirepass $$REDIS_PASSWORD + environment: + REDIS_PASSWORD: ${REDIS_PASSWORD} + volumes: + - /path/to/netbox/redis_data:/data + networks: + - netbox-net + + redis-cache: + image: valkey/valkey:9.0-alpine + container_name: netbox-redis-cache + restart: unless-stopped + command: + - sh + - -c + - valkey-server --requirepass $$REDIS_PASSWORD + environment: + REDIS_PASSWORD: ${REDIS_CACHE_PASSWORD} + volumes: + - /path/to/netbox/redis_cache:/data + networks: + - netbox-net + + netbox: &netbox + image: netboxcommunity/netbox:latest + container_name: netbox + user: "netbox:root" + restart: unless-stopped + depends_on: + - postgres + - redis + - redis-cache + env_file: .env + ports: + - ${HTTP_PORT}:8080 + environment: + SECRET_KEY: ${NETBOX_SECRET_KEY} + DB_NAME: ${POSTGRES_DB} + DB_USER: ${POSTGRES_USER} + DB_PASSWORD: ${POSTGRES_PASSWORD} + DB_HOST: postgres + REDIS_HOST: redis + REDIS_PORT: 6379 + REDIS_PASSWORD: ${REDIS_PASSWORD} + REDIS_DATABASE: 0 + REDIS_CACHE_HOST: redis-cache + REDIS_CACHE_PORT: 6379 + REDIS_CACHE_PASSWORD: ${REDIS_CACHE_PASSWORD} + REDIS_CACHE_DATABASE: 1 + SUPERUSER_NAME: ${SUPERUSER_NAME} + SUPERUSER_PASSWORD: ${SUPERUSER_PASSWORD} + SUPERUSER_EMAIL: ${SUPERUSER_EMAIL} + volumes: + - /path/to/netbox/netbox_media:/opt/netbox/netbox/media + - /path/to/netbox/netbox_reports:/opt/netbox/netbox/reports + - /path/to/netbox/netbox_scripts:/opt/netbox/netbox/scripts + - ./configuration/extra.py:/etc/netbox/config/extra.py:ro + healthcheck: + test: curl -f http://localhost:8080/login/ || exit 1 + start_period: 90s + timeout: 3s + interval: 15s + networks: + - netbox-net + + netbox-worker: + <<: *netbox + container_name: netbox-worker + ports: [] + depends_on: + netbox: + condition: service_healthy + command: + - /opt/netbox/venv/bin/python + - /opt/netbox/netbox/manage.py + - rqworker + healthcheck: + test: ps -aux | grep -v grep | grep -q rqworker || exit 1 + start_period: 20s + timeout: 3s + interval: 15s + +networks: + netbox-net: + external: true diff --git a/Docker/Node-RED/docker-compose.yaml b/Docker/Node-RED/docker-compose.yaml new file mode 100644 index 0000000..d89be73 --- /dev/null +++ b/Docker/Node-RED/docker-compose.yaml @@ -0,0 +1,19 @@ +services: + nodered: + image: nodered/node-red:latest + container_name: nodered + restart: unless-stopped + environment: + - TZ=${TZ} + - PUID=${PUID} + - PGID=${PGID} + ports: + - "${HTTP_PORT}:1880" + volumes: + - /path/to/nodered_data:/data + networks: + - notifier-net + +networks: + notifier-net: + external: true