RomM: Self-Hosted Game ROM Manager
If you have a collection of retro game ROMs, RomM is the cleanest way to organize and access them. Think of it as Plex for ROMs: it fetches metadata and cover art from IGDB and MobyGames, provides a polished web UI sorted by platform and game, and lets you play directly in the browser via EmulatorJS.
Photo by Liam Briese on Unsplash
What RomM Does
- Metadata enrichment: Matches games against IGDB and MobyGames to add cover art, descriptions, genres, and release dates
- Platform organization: Groups games by console (NES, SNES, N64, GBA, PS1, etc.)
- Web-based browser: Browse your collection with box art, search, filter by genre or platform
- In-browser play: Launch games directly in the browser using EmulatorJS
- Multi-user: User accounts with separate game saves
- Save state management: Sync save states across browser sessions
- Controller support: Browser gamepad API support
Docker Compose Setup
RomM needs a database (MariaDB), Redis, and your ROM storage mounted:
services:
romm:
image: rommapp/romm:latest
container_name: romm
restart: unless-stopped
environment:
DB_HOST: romm-db
DB_NAME: romm
DB_USER: romm-user
DB_PASSWD: change-this
ROMM_AUTH_SECRET_KEY: change-this-to-random-string
IGDB_CLIENT_ID: your-igdb-client-id
IGDB_CLIENT_SECRET: your-igdb-client-secret
MOBYGAMES_API_KEY: your-mobygames-key
volumes:
- ./romm-config:/romm/config
- ./romm-resources:/romm/resources # Metadata, covers
- ./romm-redis:/romm/redis-data # Redis persistence
- /path/to/your/roms:/romm/library # Your ROM files
- ./romm-assets:/romm/assets
ports:
- 8080:8080
depends_on:
romm-db:
condition: service_healthy
romm-db:
image: mariadb:latest
container_name: romm-db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: change-root-password
MARIADB_DATABASE: romm
MARIADB_USER: romm-user
MARIADB_PASSWORD: change-this
volumes:
- romm-db-data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
retries: 5
volumes:
romm-db-data:
Navigate to http://your-server:8080. Create the admin account on first launch.
Getting API Credentials
RomM uses IGDB (Twitch) and MobyGames for metadata. Both require free API keys:
IGDB (via Twitch):
- Go to dev.twitch.tv
- Create application → select IGDB as client type
- Note Client ID and generate Client Secret
MobyGames (optional, for older platforms):
- Create account at mobygames.com
- Request an API key via their API page
Both are free for personal use.
ROM Library Structure
RomM expects your library organized by platform folder. The platform folder names should match IGDB platform slugs:
/roms/
├── n64/
│ ├── Super Mario 64 (USA).z64
│ └── Ocarina of Time (USA).z64
├── snes/
│ ├── Chrono Trigger (USA).sfc
│ └── Final Fantasy VI (USA).sfc
├── gba/
│ ├── Pokemon FireRed (USA).gba
│ └── Advance Wars (USA).gba
├── psx/
│ └── Final Fantasy VII Disc1.bin
│ └── Final Fantasy VII Disc1.cue
├── nes/
│ └── Super Mario Bros. (World).nes
└── gb/
└── Pokemon Red (USA).gb
Common platform slugs: n64, snes, nes, gba, gb, gbc, psx, ps2, genesis, sega-saturn, nds, 3ds, switch, arcade
See RomM docs for the full list of supported platform slugs.
Scanning Your Library
After uploading ROMs to the library directory:
- Administration → Platforms → Scan (or scan on first login)
- RomM matches files against IGDB by filename
- Cover art and metadata downloads
The scanner uses fuzzy matching, so filenames don't need to be perfect. Clean region-tagged filenames like Chrono Trigger (USA).sfc match reliably.
For unmatched games: manual search by title in the RomM interface.
In-Browser Gaming with EmulatorJS
RomM ships with EmulatorJS for direct browser play:
- Click any game in the library
- "Play" button launches it in the browser
- No browser extension needed — pure JavaScript emulation
- Controller support via Web Gamepad API
Supported emulators in RomM/EmulatorJS:
- NES (FCEUX)
- SNES (Snes9x)
- N64 (Mupen64Plus)
- GBA (mGBA)
- GB/GBC (Gambatte)
- Game Gear, Sega Genesis, Master System
- PS1 (PCSX-ReARMed) — requires BIOS files
- NDS (DeSmuME)
- Arcade (MAME)
For PS1 emulation, provide BIOS files in the RomM configuration directory.
Save States and Multiplayer
RomM saves game progress (save files and save states) per user. Multiple users can have independent saves on the same ROM.
Network play: EmulatorJS supports local multiplayer (two controllers on one device) but not real-time network multiplayer.
Mobile Access
RomM's web UI is mobile-responsive. Play with a Bluetooth controller connected to your phone via the browser — works well for handhelds and simpler games. N64 and PS1 emulation in a mobile browser may be slower depending on device.
File Access for External Emulators
Some users prefer desktop emulators (RetroArch, mGBA, etc.) over browser emulation. RomM doesn't restrict access — your ROMs are on a regular filesystem path. You can mount the library via NFS or Samba to other machines for use with any emulator.
Resource Usage
- Idle: ~200-400MB RAM
- During scan (downloading metadata/covers): moderate CPU and network
- Storage: Proportional to ROM collection size + ~500MB-2GB for covers
For a large collection (thousands of games), the initial scan can take 30-60 minutes due to API rate limits on IGDB/MobyGames. Subsequent syncs are incremental and fast.
The repository is at rommapp/romm with active development. Combined with a reverse proxy for HTTPS, it becomes an accessible retro gaming library from any device on your network.
