Files
Frank 93d1181fee docs: OKF v0.1 compliance pass + fact-check + 3 research briefs
- Migrate all 127 non-reserved docs to OKF v0.1 frontmatter (type/description/tags/timestamp); fix 13 YAML issues, 2 duplicate-FM blocks, strip reserved-page FM
- Restructure log.md to OKF (## YYYY-MM-DD, newest-first)
- Fact-check against scripts/AGENTS.md ground truth: fix 6 false 'Active' banners on retired runbooks, 96->114 GiB GTT, deployment.md vs deploy-plan.py/deploy-remote.sh, Deployment Flow frank-medium=Quadlet, Calibre 9.9.0->9.15.0 + CVE-2025-7404 conflation, Copyparty v1.20.24, RomM 5.3.0 breaking change
- Move *arr docs to new FrankBook-Pro/ section (git mv, link-safe)
- Write active runbook bodies from ground truth (frank-large, frank-small)
- Add 3 research briefs + HTML report: Local TTS and Voice Cloning, AI Job Search and Resume Tools, Most Popular Self-Hosted AI Apps (Jun-Sep 2026)
- Add upstream-version rows to ComfyUI/OpenWebUI/Hermes app docs
- All 336 tests pass; 136 pages, 0 unresolved wikilinks
2026-09-22 02:09:41 -07:00

9.2 KiB

type, description, tags, timestamp
type description tags timestamp
reference RomM (ROM Manager) is a self-hosted ROM library manager and player.
dankserver
romm
2026-09-03

RomM

RomM (ROM Manager) is a self-hosted ROM library manager and player. It scans a ROM collection, enriches it with metadata and cover art from multiple providers, and serves it through a clean web interface. RomM also supports browser-based emulation via EmulatorJS and native emulator streaming.

Host: Dankserver — Access: romm.franksdank.cloud guarded by the Anubis → Authentik chain (Caddy routes it post-auth to 192.168.0.235:8085) — Docs: https://docs.romm.app

Facts

Item Value
Running image ghcr.io/rommapp/romm:latest (rolling tag — no pin; the version claims on this page were true at research time; verify against the live container before relying on them)
Port 8085 (host) → 8080 (container)
Database MariaDB (default); PostgreSQL optional
Cache / Queue Redis or Valkey (required for task queue)
Frontend React SPA
Backend FastAPI / Node
Metadata providers IGDB, Screenscraper, MobyGames, Hasheous, Playmatch, LaunchBox, Flashpoint, HowLongToBeat, SteamGridDB, RetroAchievements, TGDB, ES-DE gamelist
Emulator player EmulatorJS (WebAssembly RetroArch cores)
Emulator streaming Native containers (PCSX2, Dolphin, Xemu) → browser

Architecture

Current RomM releases require MariaDB plus Redis (or Valkey) for the task queue; this deployment runs redis (REDIS_HOST=redis in the live unit), not valkey.

graph LR
    U[User] --> C[Caddy :80/:443]
    C --> R[RomM :8085]
    R --> DB[(MariaDB)]
    R --> Cache[(Redis)]
    R --> Lib[/romm/library]
    R --> Res[/romm/resources]

Configuration

Environment Variables

Variable Required Description
ROMM_USERNAME Yes Initial admin username
ROMM_PASSWORD Yes Initial admin password (set on first boot)
ROMM_AUTH_SECRET_KEY Yes JWT signing key. Generate with openssl rand -hex 32. Replaces the old ROMM_SECRET_KEY.
DB_HOST Yes MariaDB hostname (e.g. mariadb)
DB_NAME Yes Database name (e.g. romm)
DB_USER Yes Database user
DB_PASSWD Yes Database password
REDIS_HOST Yes Redis hostname (e.g. redis)
DISABLE_SETUP_WIZARD No Set to true to skip the first-run wizard
OIDC_ENABLED No Enable OpenID Connect authentication
OIDC_CLIENT_ID No OIDC client ID
OIDC_CLIENT_SECRET No OIDC client secret
OIDC_REDIRECT_URI No OIDC redirect URI
STREAMING_BROKER_SECRET No Secret for native emulator streaming
STREAMING_SAVE_TIMEOUT No Timeout for save states during streaming
KIOSK_MODE No Enable kiosk mode
ROMM_SESSION_SECURE_COOKIE No Secure cookie flag for sessions

Metadata Provider Credentials

These are set via environment variables or in config.yml:

Variable Provider Notes
IGDB_CLIENT_ID / IGDB_CLIENT_SECRET IGDB (Twitch OAuth2) Create app at Twitch Developer Portal. Free tier: ~10 req/sec.
SCREENSCRAPER_USER / SCREENSCRAPER_PASSWORD Screenscraper Account credentials (not API key). Free, community-driven.
MOBYGAMES_API_KEY MobyGames Paid hobbyist API. Note: RomM recommends Screenscraper as free alternative.
RETROACHIEVEMENTS_API_KEY RetroAchievements Hash-based achievements via bundled RAHasher binary.
STEAMGRIDDB_API_KEY SteamGridDB Custom cover art via the search cover button.
HASHEOUS_API_ENABLED Hasheous Set to true in the live unit env file. Free, hash-based, proxies IGDB data. Fast scans.
PLAYMATCH_API_ENABLED Playmatch Set to true. Multi-provider hash matching (IGDB, SS, SteamGridDB, RA).

Config File

RomM uses config.yml for scan settings, available through the admin UI (Scan Settings). Place the file at /home/dank/Containers/romm/config/config.yml on the host.

Key scan config options:

scan:
  priority:
    metadata:
      - igdb
      - ss        # Screenscraper
    artwork:
      - igdb
      - ss
    region:
      - us
      - eu
      - jp
    region_mode: prefer_rom_tags   # or prefer_config
  media:
    - box2d
    - screenshot
    - manual
  gamelist:
    export: true    # Export ES-DE compatible gamelist.xml

Deployment (Quadlet)

Since 2026-09-01 the trio runs as repo-tracked quadlet units, deployed with ./scripts/deploy.sh dankserver --service romm (any of romm, romm-mariadb, romm-redis triggers the full ordered cutover):

  • Units: dankserver/romm/quadlet/{romm,romm-mariadb,romm-redis}.container → generated romm.service etc., enabled via the quadlet generator's default.target.wants (is-enabled reports generated).
  • Secrets: host-local /home/dank/Containers/romm/env (0600, 15 app vars — compose-provided keys only; image-baked vars like HOME/PATH must never enter it, they poison the podman client's service environment).
  • Network: dankserver_appnet with aliases mariadb/redis (replaces compose service discovery; DB_HOST/REDIS_HOST still resolve).
  • Publish: 8085:8080 (PublishPort=, see the seam test on published ports).

Volumes

The live unit mounts one root bind — Volume=/home/dank/Containers/romm:/romm — so /romm/config, /romm/library, /romm/resources, and /romm/assets all resolve inside a single host-side data root:

Container path Host path
/romm/* (single root bind) /home/dank/Containers/romm/*
/var/lib/mysql (romm-mariadb) /home/dank/Containers/romm/mariadb (mapped subuid owner — never chown)
/data (romm-redis) /home/dank/Containers/romm/redis (mapped subuid owner)

The cutover rescued RomM's anonymous /romm volume (assets, plus empty mountpoint stubs that shadowed nothing) into the data root before first unit start — the mechanism behind the original "RomM data wiped" incident is now structurally impossible: the units declare bind mounts only.

Docker Compose (reference — retired 2026-09-01, superseded by the quadlet units above)

services:
  romm:
    image: ghcr.io/rommapp/romm:latest
    container_name: romm
    restart: unless-stopped
    environment:
      ROMM_USERNAME: "${ROMM_USERNAME}"
      ROMM_PASSWORD: "${ROMM_PASSWORD}"
      ROMM_AUTH_SECRET_KEY: "${ROMM_AUTH_SECRET_KEY}"
      DB_HOST: mariadb
      DB_NAME: romm
      DB_USER: "${ROMM_DB_USER}"
      DB_PASSWD: "${ROMM_DB_PASSWD}"
      REDIS_HOST: redis
    ports:
      - "8085:8080"
    volumes:
      - /opt/romm/library:/romm/library
      - /opt/romm/resources:/romm/resources
      - /opt/romm/config:/romm/config
    depends_on:
      mariadb:
        condition: service_healthy
      redis:
        condition: service_healthy

  mariadb:
    image: docker.io/mariadb:11
    container_name: romm-mariadb
    restart: unless-stopped
    environment:
      MARIADB_ROOT_PASSWORD: "${MARIADB_ROOT_PASSWORD}"
      MARIADB_DATABASE: romm
      MARIADB_USER: "${ROMM_DB_USER}"
      MARIADB_PASSWORD: "${ROMM_DB_PASSWD}"
    volumes:
      - /opt/romm/mariadb:/var/lib/mysql
    healthcheck:
      test: ["CMD", "mariadb-admin", "ping", "-h", "localhost"]
      interval: 10s
      timeout: 5s
      retries: 3

  redis:
    image: docker.io/redis:7-alpine
    container_name: romm-redis
    restart: unless-stopped
    volumes:
      - /opt/romm/redis:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

Healthcheck

healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
  interval: 30s
  timeout: 10s
  retries: 3

Gotchas

  • First login overwrites env credentials. The ROMM_PASSWORD env var sets the initial password. After first login, the admin password is controlled in the UI. The env var only applies on first boot.
  • MariaDB and Redis are required. RomM 5.2.0 no longer supports SQLite-only deployments. Both MariaDB and Redis must be running.
  • 5.3.0 breaking change (2026-09-21). filesystem.roms_folder / firmware_folder are removed; the scan root must be expressed via filesystem.structure in config.yml (see the Config File section above). New env vars: SCAN_WORKERS, WEB_SERVER_CONCURRENCY, DB_POOL_RECYCLE_SECONDS. The rolling :latest tag will pick this up on the next pull — migrate config.yml before redeploying, or the scan root silently goes empty.
  • Reverse proxy cache stale index.html. Purge Caddy proxy cache after RomM version bumps to avoid serving a stale frontend after an upgrade.
  • RAHasher build time. Enabling RetroAchievements hashing increases the first image build. Skip unless you need achievement data.
  • MobyGames is paid. The hobbyist API has strict rate limits. Screenscraper is the recommended free alternative.
  • OIDC requires additional services. Authentik, Keycloak, or another OIDC provider must be running before enabling OIDC_ENABLED.

See Also