Files
serverAppConfigs/serverAppConfigs-docs/Dankserver/RomM.md
T
Frank 272ef6f0b0 docs: record quadlet standardization of dankserver media + dankclaw data roots
Phase 1/2 of the podman standardization plan: service pages updated to the
quadlet reality (units, Containers data roots, env-file secret convention,
the v1-generator findings each caught live), Storage Policy documents the
two rootless ownership regimes and the merge-move migration, Deployment
Flow's service-manager table no longer claims dankserver media is bare
inventory-only. Bundle change log entry added.
2026-09-01 13:57:33 -07:00

8.4 KiB

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 — Hostname: romm.dankserver.local — Docs: https://docs.romm.app

Facts

Item Value
Latest version 5.2.0 (released 2026-07-29)
Image ghcr.io/rommapp/romm:latest
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

RomM 5.2.0 requires three supporting services. The compose stack includes romm, mariadb, and redis (or 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. 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

Container path Host path
/romm/library /home/dank/Containers/romm/library
/romm/resources /home/dank/Containers/romm/resources
/romm/config /home/dank/Containers/romm/config
/var/lib/mysql /home/dank/Containers/romm/mariadb (mapped subuid owner — never chown)
/data (redis) /home/dank/Containers/romm/redis (mapped subuid owner)

The library volume contains ROM files and subdirectories per platform. The resources volume stores cached artwork, metadata, and the asset cache. The config volume holds config.yml and other configuration.

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.
  • 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