feat: add RomM automation TrueNAS stack

This commit is contained in:
2026-06-22 21:43:35 +00:00
parent f580669293
commit 879bfbba26
3 changed files with 268 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# Keep real runtime environment files and secrets out of Git
*.env
.env
# Local editor/runtime noise
.DS_Store
*.log

View File

@@ -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

View File

@@ -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=