Configuration File
RomM reads config.yml from /romm/config/config.yml inside the container. The whole file is optional: any section you omit falls back to the defaults. You can edit config.yml directly on disk or through Library → Library Management in the settings dropdown, which is a two-way view of the same file.
Start from the config.example.yml upstream. Two larger fully-worked examples for frontend-integration scenarios:
Only set what you need
Any omitted section uses the default. Don't copy the full example and then strip sections. Just add what you want to change.
exclude
Control what the scanner ignores.
exclude.platforms
Skip entire platform folders. Values are platform slugs, not folder names (see system.platforms if your folders are named differently).
exclude.roms.single_file.extensions
Drop files with these extensions before matching, only for files that aren't inside a multi-file folder.
Default: ["db", "ini", "tmp", "bak", "lock", "log", "cache", "crdownload"]
exclude.roms.single_file.names
Unix-glob file-name patterns to skip.
Default: [".DS_Store", ".localized", ".Trashes", ".stfolder", "@SynoResource", "gamelist.xml"]
exclude.roms.multi_file.names
Skip whole folders. Used for multi-disc/multi-file games you want invisible.
Default: ["@eaDir", "__MACOSX", "$RECYCLE.BIN", ".Trash-*", ".stfolder", ".Spotlight-V100", ".fseventsd", ".DocumentRevisions-V100", "System Volume Information"]
exclude.roms.multi_file.parts.names
Files inside a multi-file ROM folder to ignore (e.g. .nfo, ._* macOS attributes, similar noise from multi-disc sets).
Default: [".DS_Store", ".localized", ".Trashes", ".stfolder", "@SynoResource", "gamelist.xml"]
exclude.roms.multi_file.parts.extensions
Extensions to ignore inside a multi-file ROM folder.
Default: ["db", "ini", "tmp", "bak", "lock", "log", "cache", "crdownload"]
system
Customise how your filesystem layout is interpreted, and how platforms are identified.
system.platforms
Map your folder names to supported platform slugs.
system:
platforms:
gc: "ngc" # treat "gc/" folder as GameCube
psx: "ps" # treat "psx/" folder as PlayStation
super_nintendo: "snes"
system.versions
Associate a platform with its "main" IGDB version, for platforms that have multiple IGDB entries you want collapsed into one (e.g. NAOMI → Arcade).
filesystem
filesystem.roms_folder
Override the default ROMs folder name (roms).
filesystem.firmware_folder
Override the default BIOS/firmware folder name (bios).
filesystem.skip_hash_calculation
Skip hashing on low-power devices. You lose hash-based matching (RetroAchievements, Hasheous, PlayMatch) but scans run much faster.
Default: false
scan
scan.priority.metadata
Order metadata providers are queried during a scan. First match wins for descriptive fields (title, description, release date, etc.).
Default: ["igdb", "moby", "ss", "ra", "launchbox", "gamelist", "hasheous", "flashpoint", "hltb"]
Values are the provider slugs. Full list:
| Slug | Provider |
|---|---|
igdb |
IGDB |
moby |
MobyGames |
ss |
ScreenScraper |
ra |
RetroAchievements |
launchbox |
LaunchBox |
gamelist |
gamelist.xml importer |
hasheous |
Hasheous |
flashpoint |
Flashpoint |
hltb |
HowLongToBeat |
tgdb |
TheGamesDB |
libretro |
Libretro metadata |
See Metadata Providers for context on each.
scan.priority.artwork
Same idea, for cover art and screenshots. Defaults to the same order as scan.priority.metadata but can differ.
scan.priority.cover, scan.priority.screenshot, scan.priority.manual
Optional per-field overrides that let you prioritise sources differently for each artwork type. Any field you omit falls back to the shared scan.priority.artwork order, so only set the ones you want to diverge.
scan:
priority:
cover: # Cover art only
- "igdb"
- "ss"
screenshot: # Screenshots only
- "ss"
- "igdb"
manual: # Game manuals only
- "launchbox"
scan.priority.region
Preferred region for titles, cover art, and regional variants. ScreenScraper uses this directly, and other providers respect it where possible.
Default: ["us", "wor", "ss", "eu", "jp"]
scan.priority.region_mode
Controls how ScreenScraper applies scan.priority.region when picking regional media. With the default prefer_rom_tags, the region tags in the ROM's own filename win and scan.priority.region only reorders those tags. With prefer_config, the configured regions come first, so you can pull the FR box for an (Europe) dump even when fr is not in the filename, then fall back to the ROM's tags when a preferred region has no media.
Default: prefer_rom_tags
scan.priority.language
Preferred localisation language.
Default: ["en", "fr"]
scan.media
Which media types to fetch during a scan, primarily for ScreenScraper and the gamelist.xml importer.
This controls the UI Boxart styles
The gallery's Boxart style picker (2D Box, 3D Box, Physical, Mix Image) only changes what the cards displayg. Styles other than 2D Box need their media type added here, then a rescan, or the cards fallback to 2D Box. See Boxart styles and media types for the full mapping and steps.
| Type | Description |
|---|---|
box2d |
Normal 2D cover art. Always enabled. |
box2d_back |
Back cover art. |
box2d_side |
2D side/spine box art. |
box3d |
3D box art. |
miximage |
Composite image (box + screenshot + logo). |
miximage_v2 |
Newer composite-image layout. |
physical |
Physical media (disc, cartridge). |
screenshot |
In-game screenshot. Enabled by default. |
title_screen |
Title-screen capture. |
marquee |
Transparent logo. |
logo |
Clear/wheel logo art. |
fanart |
Community-uploaded fan art. |
bezel |
EmulatorJS-compatible bezel. |
manual |
PDF manual. Enabled by default. |
video |
Gameplay video (big files, watch your disk). |
video_normalized |
Loudness-normalised gameplay video. |
scan.gamelist.export
Generate a gamelist.xml in each platform folder, compatible with ES-DE/Batocera.
scan.pegasus.export
Export metadata in Pegasus-frontend format (metadata.pegasus.txt).
emulatorjs
These keys tune the in-browser EmulatorJS player for every user on your instance. The end-user side lives in In-Browser Play → EmulatorJS. To disable EmulatorJS altogether (e.g. when running headless with companion apps only), set DISABLE_EMULATOR_JS=true in your env vars.
emulatorjs.debug
Log available EmulatorJS options to the browser console for debugging.
Default: false
emulatorjs.cache_limit
Per-ROM cache limit in bytes. null = unlimited.
emulatorjs.disable_batch_bootup
DOS-specific knob that skips the autorun.bat step. Toggle if DOS games won't boot.
emulatorjs.disable_auto_unload
By default, EmulatorJS stops the emulator when you leave its page. Disable to keep it running across navigation.
emulatorjs.netplay
Toggle Netplay and configure STUN/TURN servers. Google's public STUN servers are fine for most setups. Run your own coturn or use Metered's free tier if you need TURN (symmetric NAT).
emulatorjs:
netplay:
enabled: true
ice_servers:
- urls: "stun:stun.l.google.com:19302"
- urls: "stun:stun1.l.google.com:19302"
- urls: "stun:stun2.l.google.com:19302"
- urls: "turn:openrelay.metered.ca:80"
username: "openrelayproject"
credential: "openrelayproject"
- urls: "turn:openrelay.metered.ca:443"
username: "openrelayproject"
credential: "openrelayproject"
Nightly CDN caveat
With Netplay enabled, EmulatorJS loads some assets (localisations included) from its nightly CDN (https://cdn.emulatorjs.org/nightly/...). Occasional 404s or untranslated strings can appear when the nightly has a transient mismatch, which usually self-heals by the next image update.
emulatorjs.settings
Per-core emulator options. Use default to apply to every core.
Core names must match the EmulatorJS core identifier exactly. To discover core names and per-core option keys, turn on debug: true, load a game in that core, open the browser console, filter for "option", and copy the keys you care about. Upstream reference is available in EmulatorJS core options.
emulatorjs.controls
Map keyboard and controller buttons per core, per player.
emulatorjs:
controls:
snes9x:
0: # player 1
0: # button slot
value: x # keyboard key
value2: BUTTON_2 # controller button
1: # player 2
0:
value: /
value2: BUTTON_2
See the EmulatorJS control-mapping docs for the button-slot reference. Users can override these defaults in-game via Menu → Controls, the config.yml setting only sets the starting point.
Worked example: 2-player SNES
emulatorjs:
settings:
snes9x:
snes9x_region: ntsc
controls:
snes9x:
0: # P1 on keyboard (WASD cluster)
0: { value: ",", value2: "BUTTON_2" } # B
1: { value: ".", value2: "BUTTON_3" } # A
2: { value: "l", value2: "BUTTON_1" } # Y
3: { value: "p", value2: "BUTTON_4" } # X
1: # P2 on arrows + numpad
0: { value: "/", value2: "BUTTON_2" }
1: { value: "'", value2: "BUTTON_3" }
Operator-level vs per-user
Most settings under emulatorjs.settings and emulatorjs.controls can be overridden by users in-game (Menu → Settings, Menu → Controls). Per-user values take precedence, the config.yml setting is the fallback.
| Where the setting lives | Who it affects | Survives upgrades? |
|---|---|---|
Operator: config.yml/env vars |
Everyone, as default | Yes |
| Per-user: in-game Menu → Settings | Just that user | Yes |
| Per-user: in-game Menu → Controls | Just that user | Yes |
streaming
Configure emulator streaming, which lets you launch games in native emulator containers and stream them to the browser. The end-user side and full setup walkthrough live in Using RomM → Emulator Streaming.
streaming.enabled
Default: false
streaming.containers
One entry per emulator container, where each entry maps a platform slug to the container that streams it.
| Key | Required | Purpose |
|---|---|---|
platform |
Yes | Platform slug this container serves (e.g. ps2, ngc, xbox, switch) |
host |
Yes | Browser-facing Selkies web UI (must be reachable from clients and served over HTTPS) |
broker_host |
No | Server-side broker API (derived from host if omitted) |
label |
Yes | Text shown on the play action (e.g. PCSX2) |
broker_secret |
No | Per-container override for the STREAMING_BROKER_SECRET env var, for brokers that use a different secret |
streaming:
enabled: true
containers:
- platform: ps2
host: https://192.168.1.51:3001 # browser-facing, must be HTTPS
broker_host: http://192.168.1.51:8000 # server-to-container, HTTP ok
label: PCSX2
- platform: ngc # ngc/wii/wiiu can share one Dolphin container
host: https://192.168.1.51:3002
broker_host: http://192.168.1.51:8001
label: Dolphin
Related
- Folder Structure: how the filesystem shape interacts with
config.yml - Metadata Providers: per-provider detail for the
scan.priority.*slugs - Emulator Streaming: the full setup guide for the
streamingblock