Mechanical identity rename across the knowledge base, AGENTS.md, README, the
hermes config example, and homepage services.json. No behavior change; served
aliases on the LLM endpoints change with the deploy of commit 69f87c8.
221 lines
8.6 KiB
Markdown
221 lines
8.6 KiB
Markdown
# 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.
|
|
|
|
```mermaid
|
|
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:
|
|
|
|
```yaml
|
|
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)
|
|
|
|
```yaml
|
|
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
|
|
|
|
```yaml
|
|
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
|
|
|
|
- [[Dankserver Stack]]
|
|
- [[RomM-Scraping]] — metadata providers, cover art, naming conventions, emulator integration
|
|
- [[Calibre-Web]] — sibling library web UI
|