diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7310f80 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +# Keep real runtime environment files and secrets out of Git +*.env +.env + +# Local editor/runtime noise +.DS_Store +*.log diff --git a/romm-automation-truenas-compose.yml b/romm-automation-truenas-compose.yml new file mode 100644 index 0000000..807ff0e --- /dev/null +++ b/romm-automation-truenas-compose.yml @@ -0,0 +1,191 @@ +# ============================================ +# RomM Automation — TrueNAS Promotion Compose +# ============================================ +# Target: TrueNAS regular Docker / Portainer Compose deployment. +# Purpose: run the request/intake helpers near the production RomM library. +# +# Source of truth: +# gitea@192.168.20.254:Wheelz/Docker-Compose-Stacks.git +# +# Deploy after creating a real runtime env file on TrueNAS/Portainer: +# docker compose --env-file romm-automation.env -f romm-automation-truenas-compose.yml up -d +# +# Validate with example values: +# docker compose --env-file romm-automation-truenas.env.example -f romm-automation-truenas-compose.yml config +# +# Notes: +# - Keep secrets out of Git. Real .env files are ignored by .gitignore. +# - Keep this LAN/VPN-only until auth/reverse-proxy behavior is reviewed. +# - Romarr is still experimental here; upstream image availability must be confirmed. +# - Staging stays separate from the production RomM library. +# - Igir mounts the production RomM library only for the validation/import profile. +# ============================================ + +name: romm-automation + +services: + ggrequestz: + image: ghcr.io/xtreemmak/ggrequestz:latest + container_name: ggrequestz + restart: unless-stopped + depends_on: + ggrequestz-postgres: + condition: service_healthy + ggrequestz-redis: + condition: service_healthy + ggrequestz-typesense: + condition: service_healthy + ports: + - "${GGREQUESTZ_PORT:-3003}:3000" + environment: + PUID: ${PUID:-568} + PGID: ${PGID:-568} + TZ: ${TZ:-America/Chicago} + NODE_ENV: production + APP_PORT: 3000 + PUBLIC_SITE_URL: ${GGREQUESTZ_PUBLIC_SITE_URL:-http://localhost:3003} + POSTGRES_HOST: ggrequestz-postgres + POSTGRES_PORT: 5432 + POSTGRES_DB: ${GGREQUESTZ_POSTGRES_DB:-ggrequestz} + POSTGRES_USER: ${GGREQUESTZ_POSTGRES_USER:-ggrequestz} + POSTGRES_PASSWORD: ${GGREQUESTZ_POSTGRES_PASSWORD:?set GGREQUESTZ_POSTGRES_PASSWORD in .env} + REDIS_URL: redis://:${GGREQUESTZ_REDIS_PASSWORD:?set GGREQUESTZ_REDIS_PASSWORD in .env}@ggrequestz-redis:6379 + TYPESENSE_HOST: ggrequestz-typesense + TYPESENSE_PORT: 8108 + TYPESENSE_PROTOCOL: http + TYPESENSE_API_KEY: ${GGREQUESTZ_TYPESENSE_API_KEY:?set GGREQUESTZ_TYPESENSE_API_KEY in .env} + AUTH_METHOD: ${GGREQUESTZ_AUTH_METHOD:-basic} + AUTHENTIK_CLIENT_ID: ${GGREQUESTZ_AUTHENTIK_CLIENT_ID:-} + AUTHENTIK_CLIENT_SECRET: ${GGREQUESTZ_AUTHENTIK_CLIENT_SECRET:-} + AUTHENTIK_ISSUER: ${GGREQUESTZ_AUTHENTIK_ISSUER:-} + SESSION_SECRET: ${GGREQUESTZ_SESSION_SECRET:?set GGREQUESTZ_SESSION_SECRET in .env} + IGDB_CLIENT_ID: ${IGDB_CLIENT_ID:?set IGDB_CLIENT_ID in .env} + IGDB_CLIENT_SECRET: ${IGDB_CLIENT_SECRET:?set IGDB_CLIENT_SECRET in .env} + ROMM_SERVER_URL: ${ROMM_SERVER_URL:-} + ROMM_USERNAME: ${ROMM_USERNAME:-} + ROMM_PASSWORD: ${ROMM_PASSWORD:-} + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/ggrequestz/app:/app/data + networks: + - romm-automation + + ggrequestz-postgres: + image: postgres:16-alpine + container_name: ggrequestz-postgres + restart: unless-stopped + # postgres:16-alpine uses UID/GID 70 internally after init. On TrueNAS, make sure + # this dataset path can be written by the container during first startup. + environment: + POSTGRES_DB: ${GGREQUESTZ_POSTGRES_DB:-ggrequestz} + POSTGRES_USER: ${GGREQUESTZ_POSTGRES_USER:-ggrequestz} + POSTGRES_PASSWORD: ${GGREQUESTZ_POSTGRES_PASSWORD:?set GGREQUESTZ_POSTGRES_PASSWORD in .env} + TZ: ${TZ:-America/Chicago} + PGDATA: /var/lib/postgresql/data/pgdata + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/ggrequestz/postgres:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${GGREQUESTZ_POSTGRES_USER:-ggrequestz} -d ${GGREQUESTZ_POSTGRES_DB:-ggrequestz}"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 30s + networks: + - romm-automation + + ggrequestz-redis: + image: redis:7-alpine + container_name: ggrequestz-redis + restart: unless-stopped + command: ["redis-server", "--appendonly", "yes", "--requirepass", "${GGREQUESTZ_REDIS_PASSWORD:?set GGREQUESTZ_REDIS_PASSWORD in .env}"] + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/ggrequestz/redis:/data + healthcheck: + test: ["CMD", "redis-cli", "-a", "${GGREQUESTZ_REDIS_PASSWORD:?set GGREQUESTZ_REDIS_PASSWORD in .env}", "ping"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 10s + networks: + - romm-automation + + ggrequestz-typesense: + image: typesense/typesense:27.1 + container_name: ggrequestz-typesense + restart: unless-stopped + command: ["--data-dir", "/data", "--api-key", "${GGREQUESTZ_TYPESENSE_API_KEY:?set GGREQUESTZ_TYPESENSE_API_KEY in .env}", "--enable-cors"] + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/ggrequestz/typesense:/data + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8108/health"] + interval: 30s + timeout: 5s + retries: 5 + start_period: 10s + networks: + - romm-automation + + romarr: + image: ${ROMARR_IMAGE:-romarr/romarr:latest} + container_name: romarr + restart: unless-stopped + profiles: ["romarr"] + ports: + - "${ROMARR_PORT:-9797}:9797" + environment: + PUID: ${PUID:-568} + PGID: ${PGID:-568} + TZ: ${TZ:-America/Chicago} + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/romarr/config:/config + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/staging/romarr-library:/roms + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/staging/downloads:/downloads + networks: + - romm-automation + + romm-comm: + image: idiosync000/romm-comm:latest + container_name: romm-comm + restart: unless-stopped + profiles: ["discord"] + environment: + TZ: ${TZ:-America/Chicago} + TOKEN: ${ROMMCOMM_DISCORD_TOKEN:?set ROMMCOMM_DISCORD_TOKEN in .env} + GUILD: ${ROMMCOMM_GUILD_ID:?set ROMMCOMM_GUILD_ID in .env} + API_URL: ${ROMM_SERVER_URL:?set ROMM_SERVER_URL in .env} + USER: ${ROMM_USERNAME:?set ROMM_USERNAME in .env} + PASS: ${ROMM_PASSWORD:?set ROMM_PASSWORD in .env} + ADMIN_ID: ${ROMMCOMM_ADMIN_ID:-} + DOMAIN: ${ROMMCOMM_DOMAIN:-} + REQUESTS_ENABLED: ${ROMMCOMM_REQUESTS_ENABLED:-true} + IGDB_CLIENT_ID: ${IGDB_CLIENT_ID:-} + IGDB_CLIENT_SECRET: ${IGDB_CLIENT_SECRET:-} + CHANNEL_ID: ${ROMMCOMM_CHANNEL_ID:-} + RECENT_ROMS_ENABLED: ${ROMMCOMM_RECENT_ROMS_ENABLED:-true} + RECENT_ROMS_CHANNEL_ID: ${ROMMCOMM_RECENT_ROMS_CHANNEL_ID:-} + GGREQUESTZ_ENABLED: ${ROMMCOMM_GGREQUESTZ_ENABLED:-true} + GGREQUESTZ_URL: http://ggrequestz:3000 + GGREQUESTZ_API_KEY: ${GGREQUESTZ_API_KEY:-} + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/romm-comm/data:/app/data + networks: + - romm-automation + + igir-worker: + image: node:22-alpine + container_name: igir-worker + restart: unless-stopped + profiles: ["validation"] + working_dir: /work + command: ["sh", "-c", "npm install -g igir@latest && sleep infinity"] + volumes: + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/staging:/staging + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/dat:/dat:ro + - ${TRUENAS_DOCKER_ROOT:-/mnt/HomeStorage02/Docker}/RomMAutomation/reports:/reports + - ${ROMM_LIBRARY_PATH:?set ROMM_LIBRARY_PATH in .env}:/romm/library + networks: + - romm-automation + +networks: + romm-automation: + name: romm-automation + driver: bridge diff --git a/romm-automation-truenas.env.example b/romm-automation-truenas.env.example new file mode 100644 index 0000000..0abbc0f --- /dev/null +++ b/romm-automation-truenas.env.example @@ -0,0 +1,70 @@ +# RomM Automation / Intake TrueNAS example environment +# Copy to romm-automation.env on TrueNAS/Portainer and fill real values. +# Do not commit real secrets. This repo ignores *.env files. + +TZ=America/Chicago +PUID=568 +PGID=568 + +# TrueNAS Docker dataset root. This follows the current TrueNAS promotion pattern. +TRUENAS_DOCKER_ROOT=/mnt/HomeStorage02/Docker + +# Existing production RomM library path on TrueNAS. +# This should be the path that contains RomM's library folders such as roms/, bios/, etc. +# Example only; adjust to the real RomM dataset/path. +ROMM_LIBRARY_PATH=/mnt/HomeStorage02/Docker/RomM/library + +# Published ports on the TrueNAS Docker host +GGREQUESTZ_PORT=3003 +ROMARR_PORT=9797 + +# Optional Compose profiles. +# Start blank or validation-only first. Add romarr only after ROMARR_IMAGE is confirmed. +# Valid values: romarr,discord,validation or comma-separated combinations. +COMPOSE_PROFILES=validation + +# GG Requestz support services +GGREQUESTZ_POSTGRES_DB=ggrequestz +GGREQUESTZ_POSTGRES_USER=ggrequestz +GGREQUESTZ_POSTGRES_PASSWORD=change_me_generate_long_random +GGREQUESTZ_REDIS_PASSWORD=change_me_generate_long_random +GGREQUESTZ_TYPESENSE_API_KEY=change_me_generate_long_random +GGREQUESTZ_SESSION_SECRET=change_me_generate_32_plus_chars +GGREQUESTZ_AUTH_METHOD=basic +GGREQUESTZ_PUBLIC_SITE_URL=http://your-truenas-host:3003 + +# Optional Authentik/OIDC later. Leave blank for basic auth first. +GGREQUESTZ_AUTHENTIK_CLIENT_ID= +GGREQUESTZ_AUTHENTIK_CLIENT_SECRET= +GGREQUESTZ_AUTHENTIK_ISSUER= + +# IGDB/Twitch credentials required by GG Requestz and useful for RomM-ComM requests. +IGDB_CLIENT_ID=fill_me +IGDB_CLIENT_SECRET=fill_me + +# Existing RomM connection. +ROMM_SERVER_URL=http://your-romm-host:port +ROMM_USERNAME=fill_me +ROMM_PASSWORD=fill_me + +# Romarr image. Upstream docs list romarr/romarr:latest, but the public image was not pullable +# when this scaffold was created. Override this if we build/publish a local image. +ROMARR_IMAGE=romarr/romarr:latest + +# Existing Arr stack connections for manual configuration inside Romarr/GG Requestz. +# These are documented here for setup reference; the apps may store them internally after UI config. +PROWLARR_URL=http://your-prowlarr-host:9696 +QBITTORRENT_URL=http://your-vpn-qbit-host:8080 +QBITTORRENT_CATEGORY=romarr + +# RomM-ComM / Discord bot. Only needed if starting the discord profile. +ROMMCOMM_DISCORD_TOKEN=fill_me +ROMMCOMM_GUILD_ID=fill_me +ROMMCOMM_ADMIN_ID= +ROMMCOMM_DOMAIN= +ROMMCOMM_CHANNEL_ID= +ROMMCOMM_RECENT_ROMS_CHANNEL_ID= +ROMMCOMM_REQUESTS_ENABLED=true +ROMMCOMM_RECENT_ROMS_ENABLED=true +ROMMCOMM_GGREQUESTZ_ENABLED=true +GGREQUESTZ_API_KEY=