Files
GerbilManager/deploy/truenas/compose.yaml
Gulum c45bcc99f0
Some checks failed
CI / Backend Tests (.NET) (push) Successful in 59s
CI / Frontend Tests (Node/Vite) (push) Successful in 9m33s
CI / Docker Build & Push (push) Failing after 8s
Merge feature/ops-2 (OPS-2): TrueNAS Goldeye deploy config (registry git.rismer.de + JailStorage paths) + ops runbook
# Conflicts:
#	deploy/truenas/compose.yaml
2026-06-07 02:28:00 +02:00

150 lines
5.0 KiB
YAML

# GerbilManager — TrueNAS Custom Application
# ==============================================
# Vor dem ersten Start:
# 1. Kopiere deploy/truenas/.env.example -> deploy/truenas/.env und setze die Werte.
# 2. Lege die Dataset-Pfade auf der NAS an (pgdata, photos, backups).
# 3. docker compose -f deploy/truenas/compose.yaml up -d
#
# Zugriff: http://<NAS-IP>:${PORT:-80}
# API-Doku: http://<NAS-IP>:${PORT:-80}/scalar
services:
# --- PostgreSQL-Datenbank ---
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_DB: gerbilmanager
POSTGRES_USER: postgres
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d gerbilmanager"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
# --- .NET API (GerbilManagerWebAPI) ---
api:
image: "${REGISTRY:-git.rismer.de/gulum}/gerbilmanager-api:${TAG:-latest}"
build:
context: ../..
dockerfile: GerbilManagerWebAPI/Dockerfile
restart: unless-stopped
environment:
ASPNETCORE_ENVIRONMENT: Production
# Verbindung zur Postgres-DB im selben Compose-Netz
ConnectionStrings__gerbilmanager: "Host=db;Port=5432;Database=gerbilmanager;Username=postgres;Password=${POSTGRES_PASSWORD}"
# Speicherort der hochgeladenen Fotos (NAS-Dataset gemounted unter /data/photos)
Photos__RootPath: /data/photos
# AR-3: Data Protection Key-Ring (persistiert Gmail-App-Passwort-Verschlüsselung über Redeployments)
DataProtection__KeyRingPath: /data/keys
# AR-4: KI-Funktionen (Verkaufstext + Posteingang-Entwurf, Sektion AI; beliebiger OpenAI-kompatibler Anbieter)
# Anbieter-Optionen und Schlüssel-Beispiele: docs/ai-provider.md
# Leer lassen = KI deaktiviert (503 AiKeyMissing statt Fehler)
AI__BaseUrl: "${AI__BaseUrl:-}"
AI__ApiKey: "${AI__ApiKey:-}"
AI__Model: "${AI__Model:-gemini-flash-latest}"
# WEB-2: Pfad wo POST /api/publish die oeffentliche Seite hinschreibt
PublicSite__RootPath: /data/publicsite
volumes:
- photos:/data/photos
- keys:/data/keys
- publicsite:/data/publicsite
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 90s
# --- nginx Frontend (React SPA + API-Proxy) ---
frontend:
image: "${REGISTRY:-git.rismer.de/gulum}/gerbilmanager-frontend:${TAG:-latest}"
build:
context: ../..
dockerfile: gerbil-manager-web/Dockerfile
restart: unless-stopped
ports:
- "${PORT:-80}:80"
depends_on:
api:
condition: service_healthy
# --- nginx Public Site (WEB-2) ---
# Serviert NUR die statische oeffentliche Seite (live/ aus dem publicsite-Volume).
# SICHERHEIT: Kein Proxy auf api/frontend — nur statisches HTML nach aussen.
# Julian's externer nginx-Proxy leitet <DOMAIN> auf Port 8081 weiter.
publicsite:
image: nginx:alpine
restart: unless-stopped
ports:
- "${PUBLICSITE_PORT:-8081}:80"
volumes:
- publicsite:/usr/share/nginx/html:ro
- ./nginx/publicsite.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- api
# --- Backup-Sidecar (taeglicher pg_dump + Foto-Archiv + Rotation) ---
backup:
image: postgres:17-alpine
restart: unless-stopped
environment:
PGPASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_HOST: db
POSTGRES_USER: postgres
POSTGRES_DB: gerbilmanager
BACKUP_KEEP_DAYS: "${BACKUP_KEEP_DAYS:-7}"
volumes:
- photos:/data/photos:ro
- backups:/backups
- ./scripts:/scripts:ro
depends_on:
db:
condition: service_healthy
entrypoint: ["/bin/sh", "/scripts/entrypoint.sh"]
volumes:
# NAS-Datasets als Bind-Mounts (Pfade in .env konfigurieren).
# TrueNAS Goldeye: /mnt/JailStorage/DockerVolumes/gerbilmanager/<name>
pgdata:
driver: local
driver_opts:
type: none
o: bind
device: "${PGDATA_PATH:-/mnt/JailStorage/DockerVolumes/gerbilmanager/pgdata}"
photos:
driver: local
driver_opts:
type: none
o: bind
device: "${PHOTOS_PATH:-/mnt/JailStorage/DockerVolumes/gerbilmanager/photos}"
# AR-3: Data Protection key ring — persistiert Gmail-App-Passwort-Verschlüsselung.
# Muss ein persistentes NAS-Dataset sein (nicht dasselbe wie photos).
keys:
driver: local
driver_opts:
type: none
o: bind
device: "${KEYS_PATH:-/mnt/JailStorage/DockerVolumes/gerbilmanager/keys}"
backups:
driver: local
driver_opts:
type: none
o: bind
device: "${BACKUPS_PATH:-/mnt/JailStorage/DockerVolumes/gerbilmanager/backups}"
# WEB-2: gemeinsames Volume fuer api (rw) und publicsite-nginx (ro).
publicsite:
driver: local
driver_opts:
type: none
o: bind
device: "${PUBLICSITE_PATH:-/mnt/JailStorage/DockerVolumes/gerbilmanager/publicsite}"