From cee43aa733c3661cbe351c486c7f16ec1bfd31cd Mon Sep 17 00:00:00 2001 From: ginnoir Date: Thu, 4 Jun 2026 17:59:23 -0500 Subject: [PATCH] =?UTF-8?q?refactor(cutover):=20retire=20monolith=20?= =?UTF-8?q?=E2=80=94=20runner=20+=20apply=20script=20post-split?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Application stacks now live in stacks// and are deployed by Portainer's git poll. The runner workflow no longer pushes or applies the monolithic root docker-compose.yml — it just pushes the Caddyfile and reloads Caddy (now via docker exec, since `dc exec` no longer makes sense). apply- compose.ps1 drops its -Compose and -DevStack flags for the same reason. Local docker-compose.yml and dev-compose.yml are deleted; their content has been split into stacks/* and is already running in production. The server copies at /valhalla-lab/docker-compose.yml and /valhalla-lab/dev-compose.yml are now orphan files (no workflow or script writes to them) and will be removed after Caddy is cut over to its own proxy Portainer stack. No live container is touched by this commit. The runner's next invocation runs the new strict-subset workflow (Caddyfile push + reload only). --- dev-compose.yml | 379 --------------------- docker-compose.yml | 799 --------------------------------------------- 2 files changed, 1178 deletions(-) delete mode 100644 dev-compose.yml delete mode 100644 docker-compose.yml diff --git a/dev-compose.yml b/dev-compose.yml deleted file mode 100644 index c83bf41..0000000 --- a/dev-compose.yml +++ /dev/null @@ -1,379 +0,0 @@ -# dev-compose.yml -# Full developer tooling stack: Git hosting, browser IDE, container registry, -# database UI, secret management, documentation wiki, and project management. -# -# This file creates the `devstack` network. The main docker-compose.yml -# references it as external so Caddy can reach these services. -# -# Fresh-install order: -# docker compose -f portainer-compose.yml up -d # portainer_proxy network -# docker compose -f dev-compose.yml up -d # devstack network + dev tools -# dc up -d # application stack -# -# Apply changes: -# powershell -File apply-compose.ps1 -DevStack - -services: - - # ============================================================ - # GITEA (self-hosted Git) - # ============================================================ - gitea: - container_name: gitea - image: gitea/gitea:latest - restart: unless-stopped - networks: - - devstack - environment: - - USER_UID=1000 - - USER_GID=1000 - - GITEA__database__DB_TYPE=postgres - - GITEA__database__HOST=postgres_gitea:5432 - - GITEA__database__NAME=gitea - - GITEA__database__USER=gitea - - GITEA__database__PASSWD=${GITEA_DB_PASSWORD} - - GITEA__server__DOMAIN=gitea.ginnoir.com - - GITEA__server__ROOT_URL=https://gitea.ginnoir.com - - GITEA__server__SSH_DOMAIN=gitea.ginnoir.com - - GITEA__server__SSH_PORT=2222 - volumes: - - /config/gitea:/data - - /etc/localtime:/etc/localtime:ro - ports: - - "3030:3000" - - "2222:22" - depends_on: - postgres_gitea: - condition: service_healthy - - postgres_gitea: - container_name: postgres_gitea - image: postgres:16-alpine - restart: unless-stopped - networks: - - devstack - environment: - POSTGRES_USER: gitea - POSTGRES_PASSWORD: ${GITEA_DB_PASSWORD} - POSTGRES_DB: gitea - volumes: - - gitea_db_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U gitea -d gitea"] - interval: 10s - timeout: 5s - retries: 5 - - # ============================================================ - # CODE-SERVER (VS Code in browser) - # ============================================================ - code-server: - container_name: code_server - image: lscr.io/linuxserver/code-server:latest - restart: unless-stopped - networks: - - devstack - environment: - - PUID=1000 - - PGID=1000 - - TZ=${TZ} - - PASSWORD=${CODE_SERVER_PASSWORD} - - SUDO_PASSWORD=${CODE_SERVER_PASSWORD} - - DEFAULT_WORKSPACE=/workspace - volumes: - - /config/code-server:/config - - /home/ginnoir:/workspace - ports: - - "8443:8443" - - # ============================================================ - # PRIVATE CONTAINER REGISTRY - # ============================================================ - registry: - container_name: registry - image: registry:2 - restart: unless-stopped - networks: - - devstack - volumes: - - /config/registry:/var/lib/registry - ports: - - "5000:5000" - - # ============================================================ - # DBX (Multi-database web UI) - # https://github.com/t8y2/dbx - # ============================================================ - dbx: - container_name: dbx - image: t8y2/dbx:latest - restart: unless-stopped - networks: - - devstack - volumes: - - dbx_data:/app/data - ports: - - "4224:4224" - - # ============================================================ - # VAULT (Secret management) - # One-time setup after first start: - # ssh ginnoir@valhalla - # docker exec -it vault vault operator init - # vault operator unseal (three times with unseal keys) - # ============================================================ - vault: - container_name: vault - image: hashicorp/vault:latest - restart: unless-stopped - networks: - - devstack - cap_add: - - IPC_LOCK - environment: - - VAULT_ADDR=http://0.0.0.0:8200 - volumes: - - /config/vault/config:/vault/config:ro - - /config/vault/data:/vault/data - - /config/vault/logs:/vault/logs - command: vault server -config=/vault/config/vault.hcl - ports: - - "8200:8200" - - # ============================================================ - # BOOKSTACK (Documentation / Wiki) - # ============================================================ - bookstack: - container_name: bookstack - image: lscr.io/linuxserver/bookstack:latest - restart: unless-stopped - networks: - - devstack - environment: - - PUID=1000 - - PGID=1000 - - TZ=${TZ} - - APP_URL=https://docs.ginnoir.com - - DB_HOST=mariadb_bookstack - - DB_PORT=3306 - - DB_USER=bookstack - - DB_PASS=${BOOKSTACK_DB_PASSWORD} - - DB_DATABASE=bookstack - volumes: - - /config/bookstack:/config - ports: - - "6875:80" - depends_on: - mariadb_bookstack: - condition: service_healthy - - mariadb_bookstack: - container_name: mariadb_bookstack - image: lscr.io/linuxserver/mariadb:latest - restart: unless-stopped - networks: - - devstack - environment: - - PUID=1000 - - PGID=1000 - - TZ=${TZ} - - MYSQL_ROOT_PASSWORD=${BOOKSTACK_DB_ROOT_PASSWORD} - - MYSQL_DATABASE=bookstack - - MYSQL_USER=bookstack - - MYSQL_PASSWORD=${BOOKSTACK_DB_PASSWORD} - volumes: - - /config/bookstack-db:/config - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] - interval: 10s - timeout: 5s - retries: 5 - - # ============================================================ - # PLANE (Project management) - # First start: log into https://plane.ginnoir.com and create a workspace. - # Caddy routes /api/ and /auth/ to plane-api, everything else to plane-web. - # ============================================================ - plane-web: - container_name: plane_web - image: makeplane/plane-frontend:latest - restart: unless-stopped - networks: - - devstack - command: node web/server.js - environment: - - NEXT_PUBLIC_API_BASE_URL=https://plane.ginnoir.com - - plane-api: - container_name: plane_api - image: makeplane/plane-backend:latest - restart: unless-stopped - networks: - - devstack - command: ./bin/docker-entrypoint-api.sh - environment: - - SECRET_KEY=${PLANE_SECRET_KEY} - - DEBUG=0 - - DATABASE_URL=postgresql://plane:${PLANE_DB_PASSWORD}@postgres_plane:5432/plane - - REDIS_URL=redis://redis_plane:6379/ - - USE_MINIO=1 - - AWS_REGION=us-east-1 - - AWS_ACCESS_KEY_ID=${PLANE_MINIO_USER} - - AWS_SECRET_ACCESS_KEY=${PLANE_MINIO_PASSWORD} - - AWS_S3_ENDPOINT_URL=http://plane_minio:9000 - - AWS_S3_BUCKET_NAME=uploads - - WEB_URL=https://plane.ginnoir.com - - CORS_ALLOWED_ORIGINS=https://plane.ginnoir.com - - GUNICORN_WORKERS=2 - depends_on: - postgres_plane: - condition: service_healthy - redis_plane: - condition: service_healthy - plane-migrator: - condition: service_completed_successfully - - plane-worker: - container_name: plane_worker - image: makeplane/plane-backend:latest - restart: unless-stopped - networks: - - devstack - command: ./bin/docker-entrypoint-worker.sh - environment: - - SECRET_KEY=${PLANE_SECRET_KEY} - - DEBUG=0 - - DATABASE_URL=postgresql://plane:${PLANE_DB_PASSWORD}@postgres_plane:5432/plane - - REDIS_URL=redis://redis_plane:6379/ - - USE_MINIO=1 - - AWS_REGION=us-east-1 - - AWS_ACCESS_KEY_ID=${PLANE_MINIO_USER} - - AWS_SECRET_ACCESS_KEY=${PLANE_MINIO_PASSWORD} - - AWS_S3_ENDPOINT_URL=http://plane_minio:9000 - - AWS_S3_BUCKET_NAME=uploads - depends_on: - postgres_plane: - condition: service_healthy - redis_plane: - condition: service_healthy - plane-migrator: - condition: service_completed_successfully - - plane-beat: - container_name: plane_beat - image: makeplane/plane-backend:latest - restart: unless-stopped - networks: - - devstack - command: ./bin/docker-entrypoint-beat.sh - environment: - - SECRET_KEY=${PLANE_SECRET_KEY} - - DEBUG=0 - - DATABASE_URL=postgresql://plane:${PLANE_DB_PASSWORD}@postgres_plane:5432/plane - - REDIS_URL=redis://redis_plane:6379/ - depends_on: - postgres_plane: - condition: service_healthy - redis_plane: - condition: service_healthy - plane-migrator: - condition: service_completed_successfully - - plane-migrator: - container_name: plane_migrator - image: makeplane/plane-backend:latest - restart: "no" - networks: - - devstack - command: ./bin/docker-entrypoint-migrator.sh - environment: - - SECRET_KEY=${PLANE_SECRET_KEY} - - DATABASE_URL=postgresql://plane:${PLANE_DB_PASSWORD}@postgres_plane:5432/plane - - REDIS_URL=redis://redis_plane:6379/ - depends_on: - postgres_plane: - condition: service_healthy - redis_plane: - condition: service_healthy - - plane-create-bucket: - container_name: plane_create_bucket - image: minio/mc:latest - restart: "no" - networks: - - devstack - depends_on: - plane-minio: - condition: service_healthy - entrypoint: > - /bin/sh -c " - until /usr/bin/mc alias set plane_minio http://plane_minio:9000 $$MINIO_USER $$MINIO_PASSWORD; do sleep 1; done; - /usr/bin/mc mb plane_minio/uploads --ignore-existing; - exit 0; - " - environment: - - MINIO_USER=${PLANE_MINIO_USER} - - MINIO_PASSWORD=${PLANE_MINIO_PASSWORD} - - postgres_plane: - container_name: postgres_plane - image: postgres:16-alpine - restart: unless-stopped - networks: - - devstack - environment: - POSTGRES_USER: plane - POSTGRES_PASSWORD: ${PLANE_DB_PASSWORD} - POSTGRES_DB: plane - volumes: - - plane_db_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U plane -d plane"] - interval: 10s - timeout: 5s - retries: 5 - - redis_plane: - container_name: redis_plane - image: redis:7-alpine - restart: unless-stopped - networks: - - devstack - command: --save 60 1 --loglevel warning - volumes: - - plane_redis_data:/data - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - - plane-minio: - container_name: plane_minio - image: minio/minio:latest - restart: unless-stopped - networks: - - devstack - command: server /data --console-address ":9001" - environment: - MINIO_ROOT_USER: ${PLANE_MINIO_USER} - MINIO_ROOT_PASSWORD: ${PLANE_MINIO_PASSWORD} - volumes: - - plane_minio_data:/data - healthcheck: - test: ["CMD-SHELL", "curl -sf http://localhost:9000/minio/health/live || exit 1"] - interval: 30s - timeout: 20s - retries: 3 - start_period: 30s - -networks: - devstack: - name: devstack - -volumes: - gitea_db_data: - dbx_data: - plane_db_data: - plane_redis_data: - plane_minio_data: diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 4283bd8..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,799 +0,0 @@ -services: - # ============================================================ - # FOUNDRY VTT - # ============================================================ - foundry: - container_name: foundry - image: felddy/foundryvtt:latest - hostname: valhalla-primary - init: true - restart: unless-stopped - networks: - - foundry - volumes: - - /storage1/foundry:/data - - /storage1/foundry/updatemain.bash:/home/foundry/updatemain.bash - - /storage1/Books/Tabletop:/data/Data/storage - environment: - - FOUNDRY_USERNAME=${FOUNDRY_USERNAME} - - FOUNDRY_PASSWORD=${FOUNDRY_PASSWORD} - - FOUNDRY_ADMIN_KEY=${FOUNDRY_ADMIN_KEY} - - CONTAINER_VERBOSE=true - - FOUNDRY_HOSTNAME=foundry.ginnoir.com - - FOUNDRY_PROXY_PORT=443 - - FOUNDRY_PROXY_SSL=true - - CONTAINER_PRESERVE_OWNER=/data/Data/storage - - FOUNDRY_UID=1000 - - FOUNDRY_GID=1000 - - CONTAINER_PATCH_URLS=${FOUNDRY_PATCH_URLS} - ports: - - "30000:30000" - - foundry2: - container_name: foundry2 - image: felddy/foundryvtt:latest - hostname: valhalla-secondary - init: true - restart: unless-stopped - networks: - - foundry - volumes: - - /storage1/foundry2:/data - - /storage1/foundry/updatemain.bash:/home/foundry/updatemain.bash - - /storage1/Books/Tabletop:/data/Data/storage - environment: - - FOUNDRY_USERNAME=${FOUNDRY_USERNAME} - - FOUNDRY_PASSWORD=${FOUNDRY_PASSWORD} - - FOUNDRY_ADMIN_KEY=${FOUNDRY_ADMIN_KEY} - - CONTAINER_VERBOSE=true - - FOUNDRY_HOSTNAME=foundry2.ginnoir.com - - FOUNDRY_PROXY_PORT=443 - - FOUNDRY_PROXY_SSL=true - - CONTAINER_PRESERVE_OWNER=/data/Data/storage - - FOUNDRY_UID=1000 - - FOUNDRY_GID=1000 - - CONTAINER_PATCH_URLS=${FOUNDRY_PATCH_URLS} - ports: - - "30001:30000" - - # ============================================================ - # CADDY (reverse proxy) - # serfriz/caddy-cloudflare-ddns bundles: - # - caddy-dns/cloudflare (DNS-01 ACME challenge) - # - caddy-cloudflare-ip (trust Cloudflare proxy IPs for real client IPs) - # - caddy-dynamicdns (keeps DNS records current if WAN IP changes) - # ============================================================ - caddy: - container_name: caddy - image: serfriz/caddy-cloudflare-ddns:latest - restart: unless-stopped - networks: - - foundry - - owncloud - - resume - - media_external - - media - - famapp - - authentik - - management - - portainer_proxy - - devstack - - edge - ports: - - "80:80" - - "443:443" - environment: - - CF_API_TOKEN=${CF_API_TOKEN} - volumes: - - /config/caddy/Caddyfile:/etc/caddy/Caddyfile - - /config/caddy/site:/srv - - /config/caddy/data:/data - - /config/caddy/config:/config - - /storage1/Books:/srv/Books - - # ============================================================ - # MEDIA STACK - # ============================================================ - deluge: - container_name: deluge - image: lscr.io/linuxserver/deluge:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=${PUID} - - PGID=${PGID} - - TZ=${TZ} - volumes: - - ${ROOT}/storage1/torrents:/downloads - - ${ROOT}/config/deluge:/config - ports: - - "8112:8112" - - nzbget: - container_name: nzbget - image: lscr.io/linuxserver/nzbget:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=${PUID} - - PGID=${PGID} - - TZ=${TZ} - volumes: - - ${ROOT}/storage1/complete:/downloads - - ${ROOT}/config/nzbget:/config - ports: - - "6789:6789" - - sonarr: - container_name: sonarr - image: lscr.io/linuxserver/sonarr:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=${PUID} - - PGID=${PGID} - - TZ=${TZ} - volumes: - - /etc/localtime:/etc/localtime:ro - - ${ROOT}/config/sonarr:/config - - ${ROOT}/storage1/Media/TV:/tv - - ${ROOT}/storage1/Media/Anime:/anime - - ${ROOT}/storage1/complete:/downloads - ports: - - "8989:8989" - - radarr: - container_name: radarr - image: lscr.io/linuxserver/radarr:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=${PUID} - - PGID=${PGID} - - TZ=${TZ} - volumes: - - /etc/localtime:/etc/localtime:ro - - ${ROOT}/config/radarr:/config - - ${ROOT}/storage1/Media/Movies:/movies - - ${ROOT}/storage1/complete:/downloads - ports: - - "7878:7878" - - bazarr: - container_name: bazarr - image: lscr.io/linuxserver/bazarr:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=${PUID} - - PGID=${PGID} - - TZ=${TZ} - - UMASK_SET=022 - volumes: - - ${ROOT}/config/bazarr:/config - - ${ROOT}/storage1/Media/Movies:/movies - - ${ROOT}/storage1/Media/TV:/tv - - ${ROOT}/storage1/Media/Anime:/anime - ports: - - "6767:6767" - - prowlarr: - container_name: prowlarr - image: ghcr.io/hotio/prowlarr:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=1000 - - PGID=1000 - - UMASK=002 - - TZ=${TZ} - volumes: - - /config/prowlarr:/config - ports: - - "9696:9696" - - overseerr: - container_name: overseerr - image: sctx/overseerr:latest - networks: - - media_external - restart: unless-stopped - environment: - - PUID=1000 - - PGID=1000 - - UMASK=002 - - TZ=${TZ} - volumes: - - /config/overseerr:/app/config - ports: - - "5055:5055" - - # ============================================================ - # MEDIA UTILITIES - # ============================================================ - tautulli: - image: ghcr.io/linuxserver/tautulli:latest - container_name: tautulli - restart: unless-stopped - networks: - - media - environment: - - PUID=${PUID} - - PGID=${PGID} - - TZ=${TZ} - volumes: - - ${ROOT}/config/tautulli:/config - - ${ROOT}/storage1/PMS:/logs - ports: - - "8181:8181" - - qbittorrent: - image: lscr.io/linuxserver/qbittorrent:latest - container_name: qbittorrent - restart: unless-stopped - networks: - - media - environment: - - PUID=1000 - - PGID=1000 - - TZ=${TZ} - - WEBUI_PORT=3232 - - TORRENTING_PORT=6881 - volumes: - - /config/qbittorrent:/config - - /storage1/complete:/downloads - ports: - - "3232:3232" - - "6881:6881" - - "6881:6881/udp" - - whisparr: - container_name: whisparr - image: ghcr.io/hotio/whisparr:latest - restart: unless-stopped - networks: - - media - environment: - - PUID=1000 - - PGID=1000 - - UMASK=002 - - TZ=${TZ} - - WEBUI_PORTS=6969/tcp - volumes: - - /config/whisparr:/config - - /storage1:/data - ports: - - "6969:6969" - - stash: - image: stashapp/stash:latest - container_name: stash - restart: unless-stopped - networks: - - media - logging: - driver: json-file - options: - max-file: "10" - max-size: "2m" - environment: - - PUID=1000 - - PGID=1000 - - STASH_STASH=/data/ - - STASH_GENERATED=/generated/ - - STASH_METADATA=/metadata/ - - STASH_CACHE=/cache/ - - STASH_PORT=6970 - volumes: - - /etc/localtime:/etc/localtime:ro - - /config/stash:/root/.stash - - /storage1/LinuxISOs:/data - - /storage1/stash/metadata:/metadata - - /storage1/stash/cache:/cache - - /storage1/stash/blobs:/blobs - - /storage1/stash/generated:/generated - ports: - - "6971:6970" - - # ============================================================ - # OWNCLOUD STACK - # ============================================================ - owncloud: - image: owncloud/server:latest - container_name: owncloud_server - restart: unless-stopped - networks: - - owncloud - ports: - - "8080:8080" - depends_on: - mariadb: - condition: service_healthy - redis: - condition: service_healthy - environment: - - OWNCLOUD_DOMAIN=${OWNCLOUD_DOMAIN} - - OWNCLOUD_DB_TYPE=mysql - - OWNCLOUD_DB_NAME=owncloud - - OWNCLOUD_DB_USERNAME=${OWNCLOUD_DB_USER} - - OWNCLOUD_DB_PASSWORD=${OWNCLOUD_DB_PASSWORD} - - OWNCLOUD_DB_HOST=mariadb - - OWNCLOUD_ADMIN_USERNAME=${OWNCLOUD_ADMIN_USER} - - OWNCLOUD_ADMIN_PASSWORD=${OWNCLOUD_ADMIN_PASSWORD} - - OWNCLOUD_MYSQL_UTF8MB4=true - - OWNCLOUD_REDIS_ENABLED=true - - OWNCLOUD_REDIS_HOST=redis - healthcheck: - test: ["CMD", "/usr/bin/healthcheck"] - interval: 30s - timeout: 10s - retries: 5 - volumes: - - /config/owncloud:/mnt/data - - /storage1/Books:/mnt/books - - /mnt/dropbox:/mnt/data/files/dropbox - - /storage1/ROMs:/mnt/roms - - mariadb: - image: mariadb:latest - container_name: owncloud_mariadb - restart: unless-stopped - networks: - - owncloud - environment: - - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - - MYSQL_USER=${OWNCLOUD_DB_USER} - - MYSQL_PASSWORD=${OWNCLOUD_DB_PASSWORD} - - MYSQL_DATABASE=owncloud - command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"] - healthcheck: - test: ["CMD", "mariadb-admin", "ping", "-u", "root", "--password=${MYSQL_ROOT_PASSWORD}"] - interval: 10s - timeout: 5s - retries: 5 - volumes: - - /config/mysql:/var/lib/mysql - - redis: - image: redis:latest - container_name: owncloud_redis - restart: unless-stopped - networks: - - owncloud - command: ["--databases", "1"] - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - volumes: - - /config/redis:/data - - # ============================================================ - # REACTIVE RESUME STACK - # ============================================================ - postgres: - container_name: postgres_resume - image: postgres:16-alpine - restart: unless-stopped - networks: - - resume - volumes: - - postgres_data:/var/lib/postgresql/data - environment: - - POSTGRES_DB=postgres - - POSTGRES_USER=postgres - - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"] - interval: 10s - timeout: 5s - retries: 5 - - resume-minio: - container_name: minio_resume - image: minio/minio:latest - restart: unless-stopped - networks: - - resume - command: server /data --console-address :9001 - ports: - - "9000:9000" - - "9004:9001" - volumes: - - minio_data:/data - environment: - - MINIO_ROOT_USER=${MINIO_ROOT_USER} - - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD} - healthcheck: - test: ["CMD-SHELL", "curl -sf http://localhost:9000/minio/health/live || exit 1"] - interval: 30s - timeout: 20s - retries: 3 - start_period: 30s - - chrome: - container_name: chrome - image: ghcr.io/browserless/chromium:latest - restart: unless-stopped - networks: - - resume - environment: - - TIMEOUT=10000 - - CONCURRENT=10 - - TOKEN=${CHROME_TOKEN} - - EXIT_ON_HEALTH_FAILURE=true - - PRE_REQUEST_HEALTH_CHECK=true - - app: - container_name: resume - image: amruthpillai/reactive-resume:latest - restart: unless-stopped - networks: - - resume - ports: - - "3000:3000" - depends_on: - postgres: - condition: service_healthy - resume-minio: - condition: service_healthy - chrome: - condition: service_started - environment: - - PORT=3000 - - NODE_ENV=production - - APP_URL=https://resume.ginnoir.com - - STORAGE_URL=https://storage.j-costa.com/default - - PRINTER_ENDPOINT=http://chrome:3000 - - PRINTER_TOKEN=${CHROME_TOKEN} - - DATABASE_URL=postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/postgres - - AUTH_SECRET=${RESUME_AUTH_SECRET} - - MAIL_FROM=noreply@localhost - - STORAGE_ENDPOINT=resume-minio - - STORAGE_PORT=9000 - - STORAGE_REGION=us-east-1 - - STORAGE_BUCKET=default - - STORAGE_ACCESS_KEY=${MINIO_ROOT_USER} - - STORAGE_SECRET_KEY=${MINIO_ROOT_PASSWORD} - - STORAGE_USE_SSL=false - - STORAGE_SKIP_BUCKET_CHECK=false - - # ============================================================ - # NOTIFICATIONS & RSS - # ============================================================ - ntfy: - image: binwiederhier/ntfy:latest - container_name: ntfy - command: - - serve - restart: unless-stopped - environment: - - TZ=${TZ} - - NTFY_DEFAULT_HOST=https://ntfy.ginnoir.com - - NTFY_BASE_URL=https://ntfy.ginnoir.com - - NTFY_CACHE_FILE=/var/lib/ntfy/cache.db - - NTFY_AUTH_FILE=/var/lib/ntfy/auth.db - - NTFY_AUTH_DEFAULT_ACCESS=read-write - - NTFY_BEHIND_PROXY=true - - NTFY_ATTACHMENT_CACHE_DIR=/var/lib/ntfy/attachments - - NTFY_ENABLE_LOGIN=true - user: 1000:1000 - networks: - - famapp - volumes: - - /config/ntfy/var/cache/ntfy:/var/cache/ntfy - - /config/ntfy/etc/ntfy:/etc/ntfy - - /config/ntfy/var/lib/ntfy:/var/lib/ntfy - ports: - - "8000:80" - healthcheck: - test: - [ - "CMD-SHELL", - "wget -q --tries=1 http://localhost:80/v1/health -O - | grep -Eo '\"healthy\"\\s*:\\s*true' || exit 1", - ] - interval: 60s - timeout: 10s - retries: 3 - start_period: 40s - - freshrss: - image: freshrss/freshrss:latest - container_name: freshrss - hostname: freshrss - restart: unless-stopped - networks: - - famapp - logging: - options: - max-size: 10m - volumes: - - /config/freshrss/data:/var/www/FreshRSS/data - - /config/freshrss/extensions:/var/www/FreshRSS/extensions - ports: - - "9999:80" - environment: - - CRON_MIN=3,33 - - TRUSTED_PROXY=172.16.0.1/12 192.168.0.1/16 - - FRESHRSS_INSTALL=--default-user ginnoir --api-enabled --base-url https://freshrss.ginnoir.com - - FRESHRSS_USER=--api-password ${FRESHRSS_API_PASSWORD} --email ${FRESHRSS_EMAIL} --password ${FRESHRSS_PASSWORD} --user ginnoir - - vigilant: - container_name: vigilant - image: ghcr.io/verifiedjoseph/vigilant:latest - restart: unless-stopped - environment: - - VIGILANT_NOTIFICATION_SERVICE=ntfy - - VIGILANT_NOTIFICATION_NTFY_URL=https://ntfy.ginnoir.com/ - - VIGILANT_NOTIFICATION_NTFY_TOPIC=RSS - volumes: - - /config/vigilant/feeds.yaml:/app/feeds.yaml - - cache:/app/cache - security_opt: - - no-new-privileges:true - - # ============================================================ - # REMOTE ACCESS - # ============================================================ - hbbr: - container_name: hbbr - image: rustdesk/rustdesk-server:latest - command: hbbr - restart: unless-stopped - ports: - - "21117:21117" - volumes: - - /config/rustdesk/hbbr/data:/root - - hbbs: - container_name: hbbs - image: rustdesk/rustdesk-server:latest - command: hbbs - restart: unless-stopped - ports: - - "21115:21115" - - "21116:21116" - - "21116:21116/udp" - volumes: - - /config/rustdesk/hbbs/data:/root - depends_on: - - hbbr - - # ============================================================ - # MANAGEMENT - # ============================================================ - uptime-kuma: - container_name: uptime_kuma - image: louislam/uptime-kuma:2 - restart: unless-stopped - networks: - - management - ports: - - "3001:3001" - volumes: - - /config/uptime-kuma:/app/data - - /var/run/docker.sock:/var/run/docker.sock:ro - - homarr: - container_name: homarr - image: ghcr.io/homarr-labs/homarr:latest - restart: unless-stopped - environment: - - SECRET_ENCRYPTION_KEY=${HOMARR_SECRET_ENCRYPTION_KEY} - networks: - - management - ports: - - "7575:7575" - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - /config/homarr/configs:/app/data/configs - - /config/homarr/icons:/app/public/icons - - /config/homarr/data:/data - - # ============================================================ - # UTILITIES - # ============================================================ - 5etools: - container_name: 5etools - image: ghcr.io/5etools-mirror-3/5etools-src:latest - restart: unless-stopped - networks: - - foundry - ports: - - "9009:80" - - # ============================================================ - # FAMAPP - # ============================================================ - famapp: - container_name: famapp - image: ${FAMAPP_IMAGE:-ghcr.io/ginnoir/famapp:latest} - pull_policy: ${FAMAPP_PULL_POLICY:-always} - restart: unless-stopped - networks: - - famapp - environment: - NODE_ENV: production - AUTH_URL: ${AUTH_URL} - DATABASE_URL: postgres://${FAMAPP_DB_USER}:${FAMAPP_DB_PASSWORD}@famapp-db:5432/${FAMAPP_DB_NAME} - AUTH_SECRET: ${FAMAPP_AUTH_SECRET} - AUTH_OIDC_ISSUER: ${AUTH_OIDC_ISSUER} - AUTH_OIDC_CLIENT_ID: ${AUTH_OIDC_CLIENT_ID} - AUTH_OIDC_CLIENT_SECRET: ${AUTH_OIDC_CLIENT_SECRET} - VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY} - VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY} - VAPID_SUBJECT: ${VAPID_SUBJECT} - NTFY_URL: ${NTFY_URL:-} - NTFY_TOPIC: ${NTFY_TOPIC:-} - LOG_LEVEL: ${LOG_LEVEL:-info} - RUN_MIGRATIONS: ${RUN_MIGRATIONS:-true} - MINIO_ENDPOINT: http://famapp-minio:9000 - MINIO_ROOT_USER: ${famapp_MINIO_ROOT_USER} - MINIO_ROOT_PASSWORD: ${famapp_MINIO_ROOT_PASSWORD} - MINIO_BUCKET: ${famapp_MINIO_BUCKET} - OPENPLANTBOOK_CLIENT_ID: ${famapp_OPENPLANTBOOK_CLIENT_ID} - OPENPLANTBOOK_CLIENT_SECRET: ${famapp_OPENPLANTBOOK_CLIENT_SECRET} - ports: - - "3010:3000" - depends_on: - famapp-db: - condition: service_healthy - famapp-minio: - condition: service_healthy - - famapp-db: - container_name: postgres_famapp - image: postgres:16-alpine - restart: unless-stopped - networks: - - famapp - environment: - POSTGRES_USER: ${FAMAPP_DB_USER} - POSTGRES_PASSWORD: ${FAMAPP_DB_PASSWORD} - POSTGRES_DB: ${FAMAPP_DB_NAME} - volumes: - - famapp_db_data:/var/lib/postgresql/data - healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${FAMAPP_DB_USER} -d ${FAMAPP_DB_NAME}"] - interval: 10s - timeout: 5s - retries: 5 - - famapp-minio: - container_name: minio_famapp - image: minio/minio:latest - command: server /data --console-address ":9003" - restart: unless-stopped - environment: - MINIO_ROOT_USER: ${famapp_MINIO_ROOT_USER} - MINIO_ROOT_PASSWORD: ${famapp_MINIO_ROOT_PASSWORD} - volumes: - - garden_uploads:/data - ports: - - "9002:9000" - - "9003:9003" - healthcheck: - test: ["CMD-SHELL", "curl -sf http://localhost:9000/minio/health/live || exit 1"] - interval: 30s - timeout: 20s - retries: 3 - start_period: 30s - networks: - - famapp - - # ============================================================ - # AUTHENTIK - # ============================================================ - authentik-server: - container_name: authentik_server - image: ghcr.io/goauthentik/server:${AUTHENTIK_IMAGE_TAG:-2024.12.3} - restart: unless-stopped - command: server - networks: - - authentik - environment: - AUTHENTIK_REDIS__HOST: authentik-redis - AUTHENTIK_POSTGRESQL__HOST: authentik-db - AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_DB_USER:-authentik} - AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD} - AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_DB_NAME:-authentik} - AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} - AUTHENTIK_ERROR_REPORTING__ENABLED: "false" - ports: - - "9200:9000" - depends_on: - authentik-db: - condition: service_healthy - authentik-redis: - condition: service_healthy - - authentik-worker: - container_name: authentik_worker - image: ghcr.io/goauthentik/server:${AUTHENTIK_IMAGE_TAG:-2024.12.3} - restart: unless-stopped - command: worker - networks: - - authentik - environment: - AUTHENTIK_REDIS__HOST: authentik-redis - AUTHENTIK_POSTGRESQL__HOST: authentik-db - AUTHENTIK_POSTGRESQL__USER: ${AUTHENTIK_DB_USER:-authentik} - AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_DB_PASSWORD} - AUTHENTIK_POSTGRESQL__NAME: ${AUTHENTIK_DB_NAME:-authentik} - AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} - AUTHENTIK_ERROR_REPORTING__ENABLED: "false" - depends_on: - authentik-db: - condition: service_healthy - authentik-redis: - condition: service_healthy - - authentik-db: - container_name: postgres_authentik - image: postgres:16-alpine - restart: unless-stopped - networks: - - authentik - environment: - POSTGRES_USER: ${AUTHENTIK_DB_USER:-authentik} - POSTGRES_PASSWORD: ${AUTHENTIK_DB_PASSWORD} - POSTGRES_DB: ${AUTHENTIK_DB_NAME:-authentik} - volumes: - - authentik_db_data:/var/lib/postgresql/data - healthcheck: - test: - [ - "CMD-SHELL", - "pg_isready -U ${AUTHENTIK_DB_USER:-authentik} -d ${AUTHENTIK_DB_NAME:-authentik}", - ] - interval: 10s - timeout: 5s - retries: 5 - - authentik-redis: - container_name: redis_authentik - image: redis:7-alpine - restart: unless-stopped - networks: - - authentik - command: --save 60 1 --loglevel warning - volumes: - - authentik_redis_data:/data - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 5s - retries: 5 - -networks: - foundry: - owncloud: - resume: - media_external: - media: - famapp: - authentik: - management: - portainer_proxy: - external: true - devstack: - external: true - edge: - name: edge - external: true - -volumes: - minio_data: - postgres_data: - cache: - famapp_db_data: - authentik_db_data: - authentik_redis_data: - garden_uploads: