Underground 2 Revived
Play Need for Speed: Underground 2 (2004) in Chrome and Firefox with WebGPU graphics, Web Audio, up to 120 fps widescreen, controller support, free roam and Online races with friends. Fan project, not
Game library manager for PC and retro consoles - metadata scraping, indexer search, download automation and browser-based emulation. Sonarr/Radarr for games.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Think Radarr/Sonarr, but for video games. RetroArr scans your library, fetches metadata, organizes files, searches indexers, and automates downloads across PC, retro consoles, handhelds, and arcade platforms. One tool, one UI.
# docker-compose.yml
services:
retroarr:
image: ghcr.io/riddix/retroarr:latest
container_name: retroarr
ports:
- "2727:2727" # HTTP
- "2728:2728" # HTTPS (optional, self-signed cert)
volumes:
- ./config:/app/config
- /your/games/path:/media
- ./savestates:/app/savestates
environment:
- PUID=1000
- PGID=1000
- RETROARR_HTTPS_PORT=2728 # remove to disable HTTPS
restart: unless-stopped
docker compose up -d
Open http://your-ip:2727 (or https://your-ip:2728), then Settings → Metadata and paste your IGDB credentials (free, Twitch dev account).
Both are served by the same container. Pick what fits your setup:
:2727: fine for localhost, or when you already have a reverse proxy (SWAG, Traefik, Caddy, nginx) handling TLS:2728: auto-generated self-signed cert on first start, stored in config/certs/retroarr.pfx. Required for threaded emulator cores (PSP, NDS, N64, Saturn, 3DO) when you access the UI from a LAN IP, because browsers only expose SharedArrayBuffer on secure originsIf you only plan to proxy through SWAG with a real cert, drop the 2728 line from ports: and the RETROARR_HTTPS_PORT env var.
Library & scanning
PlatformDefinitions.cs: PC, every PlayStation, every Xbox, Nintendo NES through Switch 2, Sega from SG-1000 to Dreamcast, Atari, NEC, Arcade (MAME, FBNeo, CPS, Neo Geo), ScummVM, DOSBox, plus a pile of obscure handhelds and 8-bit computers.cue + .bin, .m3u for multi-disc, .gdi tracks, folder-based PS3/Wii U, .chd, .nsz/.xczDownloads & indexers
LanCache
*-lancache-prefill), driven from the UI with a live log. See LanCache & PrefillLaunching
.desktop file generation/usr/bin/open, delegates to Whisky/CrossOver when presentEmulation
/app/config/bios, whitelisted filenames served to EmulatorJS on demand/app/savestatesUI & integrations
Storage & deployment
HEALTHCHECK, works on amd64 + arm64Security
localhost/loopback Host, no proxy headers, not a cross-site browser request) are unauthenticated, LAN and remote clients need X-Api-Key. X-Forwarded-For never counts as "local". A proxy on the same host must send X-Forwarded-For (nginx proxy_set_header, SWAG and Traefik do by default), otherwise its clients count as local. Key is shown and rotatable in Settings → API access/emulator/player page are exempt from auth, since browsers can't attach API keys to <script src> or iframe loads. ROMs, local media and file downloads use short-lived signed links instead of the API key, and rotating the key revokes them/api/v3/system/status (the Docker healthcheck) only answers {"status":"ok"}Deeper reads: Linux Gaming · Plugins · Scanner Logic · Updates & DLC · Launcher Specs · Installer Logic · LanCache & Prefill
See Quick Start. HTTP on 2727, optional HTTPS on 2728.
App Store → Custom Install → Import, then paste:
services:
RetroArr:
image: ghcr.io/riddix/retroarr:latest
container_name: RetroArr
network_mode: bridge
ports:
- "2727:2727"
- "2728:2728"
volumes:
- /DATA/AppData/RetroArr/config:/app/config
- /DATA/Media:/media
environment:
- DOTNET_RUNNING_IN_CONTAINER=true
- RETROARR_HTTPS_PORT=2728
- PUID=1000
- PGID=1000
restart: unless-stopped
x-casaos:
architectures: [amd64, arm64]
main: RetroArr
icon: https://raw.githubusercontent.com/RiDDiX/RetroArr/main/frontend/src/assets/app_logo.png
title:
en_us: RetroArr
Container Manager → Project → Create, import the compose template from _synology/docker-compose.yml, adjust paths, done.
Community Applications template: _unraid/retroarr.xml. Or add the container by hand with image ghcr.io/riddix/retroarr:latest and both ports mapped (2727 + 2728).
Proxy your HTTPS domain to http://retroarr:2727. The container doesn't need its own HTTPS in this case, so drop the 2728 port mapping and the RETROARR_HTTPS_PORT env var.
Make sure the proxy forwards WebSocket upgrades (/hubs/progress), SignalR needs them. Upgrade and Connection headers must pass through.
A ready-made SWAG subdomain config ships in _swag/retroarr.subdomain.conf. Drop it into /config/nginx/proxy-confs/ in your SWAG container, point a CNAME at your domain, and restart SWAG.
Grab the build for your OS from Releases:
| OS | File |
|---|---|
| Windows | RetroArr-Setup.exe (installer) or portable .exe |
| macOS | RetroArr.app, universal (Apple Silicon + Intel) |
| Linux | Generic x64 binary |
Desktop mode uses ports 5002-5005 and stores config in {AppData}/RetroArr/config. Photino wraps the same Kestrel server in a native window.
Needs .NET 8 SDK and Node.js 20+.
git clone https://github.com/RiDDiX/RetroArr.git
cd RetroArr
# Everything in one shot
docker build -t retroarr:local .
# Or piece by piece
npm install && npm run build
cd src && dotnet build RetroArr.sln -c Release
Everything lives under config/ (Docker: /app/config) as JSON files. Nothing needs editing by hand, just use the Settings UI.
| Setting | Where | What |
|---|---|---|
| IGDB | Settings → Metadata | Twitch Client ID + Secret (required) |
| ScreenScraper | Settings → Metadata | Optional fallback for retro and arcade |
| Steam | Settings → Steam | API Key + Steam ID for library sync |
| GOG | Settings → GOG | OAuth for GOG Galaxy library |
| Prowlarr / Jackett | Settings → Connections | Indexer URL + API key |
| Download clients | Settings → Download Clients | qBit, Transmission, Deluge, SABnzbd, NZBGet |
| Media library | Settings → Media | Root path to your games |
| Webhooks | Settings → Notifications | Endpoints for library events |
| Database | Settings → Database | Pick SQLite, PostgreSQL or MariaDB, run the migration |
| Cache | Settings → Cache | Redis URL and TTL |
| Logging | Settings → Logging | Levels, rotation, redaction rules |
| LanCache | Settings → LanCache | Cache host/port, reachability check, Steam reconcile, and Steam/Battle.net/Epic prefill (guide) |
| Monitoring | Settings → Monitor | Poll interval, score thresholds, and auto-download behavior for monitored games |
Environment variables
| Variable | Default | Description |
|---|---|---|
PUID / PGID | 1000 | User and group IDs RetroArr runs as. The container starts as root, hands its config, savestate and prefill folders to this user and then drops to it. Your library and downloads are never chowned. Set PUID=0 to keep running as root; user: 0 alone no longer does that. With cap_drop: ALL the switch isn't possible; use user: "1000:1000" there instead (the LanCache prefill tools only work with 1000 in that mode) |
RETROARR_HTTP_PORT | 2727 | HTTP listen port |
RETROARR_HTTPS_PORT | unset | HTTPS listen port. If unset, HTTPS is disabled |
RETROARR_CERT_SAN | unset | Extra SAN entries (comma-separated) for the auto-generated HTTPS cert, e.g. IP:192.168.1.10,DNS:retroarr.lan |
RETROARR_TRUSTED_PROXIES | RFC1918 + loopback | Comma-separated CIDR ranges of reverse proxies whose X-Forwarded-* headers should be trusted. Affects the client IP, scheme and host only, never the API key check. Invalid entries are skipped; if none is valid, only loopback is trusted |
RETROARR_KEYS_DIR | <config>/keys | Where the Data Protection keys that encrypt stored credentials live. Point it at a separate volume so a copy of the config folder alone can't decrypt them. On first start the existing keys are copied there; delete <config>/keys afterwards |
ASPNETCORE_ENVIRONMENT | Production | Standard .NET environment flag |
RETROARR_EMULATORJS_CDN | https://cdn.emulatorjs.org/latest/data | Base URL EmulatorJS assets/cores are pulled from on cache-miss. Override to pin a version or use a mirror |
RETROARR_STEAMPREFILL_BIN / RETROARR_BATTLENETPREFILL_BIN / RETROARR_EPICPREFILL_BIN | bundled /opt/*prefill/* | Override the path to a prefill binary (advanced; the image bundles them by default) |
Docker volumes
| Path | Description |
|---|---|
/app/config | All config, database, logs, EmulatorJS assets, certs, and prefill-tool sessions/state |
/media | Your game library root |
/app/savestates | EmulatorJS save states (optional, separate volume keeps them out of backups) |
/downloads | Where download clients drop files (optional) |
External database (PostgreSQL / MariaDB)
SQLite needs no setup. For PostgreSQL or MariaDB, create an empty database owned by (or fully granted to) the RetroArr user; RetroArr creates its tables on first start.
-- PostgreSQL. On 15+ "GRANT ALL ON DATABASE" is not enough, the user needs CREATE on schema public.
CREATE ROLE retroarr LOGIN PASSWORD 'change-me';
CREATE DATABASE retroarr OWNER retroarr;
-- MariaDB / MySQL
CREATE DATABASE retroarr CHARACTER SET utf8mb4;
CREATE USER 'retroarr'@'%' IDENTIFIED BY 'change-me';
GRANT ALL PRIVILEGES ON retroarr.* TO 'retroarr'@'%';
To move an existing library: Settings → Database, pick the type, fill in the connection, Test Connection, then Migrate and restart. Save alone switches to the new database empty. The SQLite file stays as it was (plus a backup next to it), so switching back to SQLite returns you to the state before the migration.
The settings live in config/database.json. Type is 0 (SQLite), 1 (PostgreSQL) or 2 (MariaDB), the names work too:
{ "Type": 1, "Host": "postgres", "Port": 5432, "Database": "retroarr", "Username": "retroarr", "Password": "change-me", "UseSsl": false }
If the database can't be set up at startup, the reason is shown under Settings → Database and in config/logs/app.log.
npm run lint # Frontend lint
npm run build # Frontend build
cd src && dotnet build RetroArr.sln -c Release # Backend build
cd src && dotnet test RetroArr.Core.Test -c Release # NUnit test suite
docker build -t retroarr:local . # Full image
src/
├── RetroArr.Host # Kestrel server + Photino desktop wrapper
├── RetroArr.Api.V3 # REST controllers (33 of them)
├── RetroArr.Core # Business logic, services, models
├── RetroArr.Core.Test # NUnit tests
├── RetroArr.Common # Shared utilities
├── RetroArr.Http # HTTP client helpers
├── RetroArr.SignalR # Real-time hub
└── RetroArr.UsbHelper # Switch USB transfer helper
frontend/
├── src/pages/ # React pages
├── src/components/ # Reusable components
└── src/i18n/ # Translations (7 languages)
Bug, idea, feature request? Open an issue. PRs welcome.
RetroArr is free and open source. If it is useful to you, you can support its development:
MIT, see LICENSE.
RetroArr is for personal library management and educational use. Not affiliated with any game platform, publisher, or metadata provider. You're responsible for complying with local copyright law. See DISCLAIMER.md.