diff --git a/nodes/heimdall/recipesage/compose.yaml b/nodes/heimdall/recipesage/compose.yaml new file mode 100644 index 0000000..71009ff --- /dev/null +++ b/nodes/heimdall/recipesage/compose.yaml @@ -0,0 +1,107 @@ +version: "3.8" + +networks: + proxy-net: + external: true + recipesage-internal: + internal: true + +services: + proxy: + image: julianpoy/recipesage-selfhost-proxy:v4.0.0 + container_name: recipesage_proxy + restart: unless-stopped + networks: + - proxy-net + - recipesage-internal + depends_on: + - static + - api + - pushpin + labels: + - "traefik.enable=true" + - "traefik.docker.network=proxy-net" + + # --- 1. Authenticated Router (Priority 10) --- + - "traefik.http.routers.recipesage.rule=Host(`${DOMAIN_NAME}`)" + - "traefik.http.routers.recipesage.entrypoints=websecure" + - "traefik.http.routers.recipesage.tls=true" + - "traefik.http.routers.recipesage.tls.certresolver=cloudflare" + - "traefik.http.routers.recipesage.middlewares=authentik-auth@file" + - "traefik.http.routers.recipesage.priority=10" + - "traefik.http.routers.recipesage.service=recipesage-svc" + + # --- 2. Public Share Bypass Router (Priority 20) --- + # Bypasses Authentik for public share links, shared profile routes, and media assets + - "traefik.http.routers.recipesage-public.rule=Host(`${DOMAIN_NAME}`) && (PathPrefix(`/share`) || PathPrefix(`/p/`) || PathPrefix(`/api/v1/share`) || PathPrefix(`/assets/`))" + - "traefik.http.routers.recipesage-public.entrypoints=websecure" + - "traefik.http.routers.recipesage-public.tls=true" + - "traefik.http.routers.recipesage-public.tls.certresolver=cloudflare" + - "traefik.http.routers.recipesage-public.priority=20" + - "traefik.http.routers.recipesage-public.service=recipesage-svc" + + # --- Service Target Port --- + - "traefik.http.services.recipesage-svc.loadbalancer.server.port=80" + + api: + image: julianpoy/recipesage-selfhost:api-v3.0.10 + container_name: recipesage_api + restart: unless-stopped + networks: + - recipesage-internal + environment: + - NODE_ENV=production + - PORT=3000 + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?schema=public + - JWT_SECRET=${JWT_SECRET} + - DISABLE_REGISTRATION=${DISABLE_REGISTRATION} + - BROWSERLESS_URL=http://browserless:3000 + - PUSHPIN_URL=http://pushpin:7999 + - OPENAI_API_KEY=${OPENAI_API_KEY:-} + - OPENAI_API_BASE_URL=${OPENAI_API_BASE_URL:-} + volumes: + - /mnt/appdata/recipesage/data/uploads:/app/uploads + depends_on: + postgres: + condition: service_healthy + + static: + image: julianpoy/recipesage-selfhost:static-v3.0.10 + container_name: recipesage_static + restart: unless-stopped + networks: + - recipesage-internal + + pushpin: + image: fanout/pushpin:1.37.0 + container_name: recipesage_pushpin + restart: unless-stopped + networks: + - recipesage-internal + + browserless: + image: browserless/chrome:1.53.0-puppeteer-10.1.0 + container_name: recipesage_browserless + restart: unless-stopped + networks: + - recipesage-internal + environment: + - MAX_CONCURRENT_SESSIONS=5 + + postgres: + image: postgres:15-alpine + container_name: recipesage_postgres + restart: unless-stopped + networks: + - recipesage-internal + environment: + - POSTGRES_DB=${POSTGRES_DB} + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + volumes: + - /mnt/appdata/recipesage/data/postgres:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + interval: 5s + timeout: 5s + retries: 5 \ No newline at end of file