-
Notifications
You must be signed in to change notification settings - Fork 0
Installation
GamesDownloader ships as a set of Docker containers orchestrated by Docker Compose: the application itself, a MariaDB database, and a Redis-compatible cache/queue (Valkey). This page takes you from nothing to a running instance, explains every setting in the .env file, and covers first boot, updating, and resetting.
Just want the short version? Copy
.env.exampleto.env, change the four passwords, rundocker compose up -d, and openhttp://localhost:8080. Everything below is the detail behind those four steps.
- Requirements
- Step 1: Get the files
- Step 2: Configure
.env - Step 3: Start the stack
- First boot: what happens
- The setup wizard
- Post-install steps
- Where your data lives
- Running as a non-root user (PUID/PGID)
- Updating
- Verifying the install
- Resetting / uninstalling
| Requirement | Notes |
|---|---|
| Docker | Engine 24+ recommended. Install guide. |
| Docker Compose | v2 (the docker compose subcommand, not the legacy docker-compose). |
| Disk | The app image plus MariaDB and Valkey are modest, but your library, ROMs, downloads, and artwork can grow to hundreds of GB. Point GD_BASE_DIR at a roomy disk. First boot also pulls a ~150 MB LaunchBox metadata file and (optionally) ~300 MB of ClamAV virus definitions. |
| RAM | 2 GB is enough for a small library; 4 GB+ is comfortable once scraping and emulation are in use. |
| Architecture | Prebuilt images are published for linux/amd64 and linux/arm64 (Raspberry Pi 4/5, Apple Silicon under Linux VMs, etc.). |
| Ports |
8080 (web UI) is required. 9091 (Transmission WebUI) and 51413/tcp+udp (torrent peers) are only needed if you use torrents. |
GamesDownloader is designed to run happily LAN-only with no reverse proxy. HTTPS, a domain, and a proxy are optional and only relevant if you expose it beyond your local network - see Reverse Proxy & HTTPS.
You need two files: docker-compose.yml and your .env. The easiest way is to clone the repository:
git clone https://github.com/60plus/GamesDownloader.git
cd GamesDownloader
cp .env.example .envThere are two ways to run the app container itself:
No local build. Multi-arch images are published to Docker Hub. In docker-compose.yml, replace the app service's build: block:
gamesdownloader:
build: # <- remove these two lines
context: . # <-
dockerfile: Dockerfile # <-
image: 60plus/gamesdownloader:latest # <- add this lineAvailable tags: latest, the MAJOR.MINOR line (e.g. 1.0), and the exact MAJOR.MINOR.PATCH for each release (e.g. 1.0.16). Pin an exact version if you want reproducible upgrades.
Leave the build: block as-is. The first docker compose up will build the image locally (a multi-stage build: the Vue frontend is compiled, then the Python backend is assembled). This takes a few minutes but needs no Docker Hub access.
Open .env. At minimum, change every password before the instance is reachable by anyone but you. Here is every variable:
| Variable | Default | What it does |
|---|---|---|
GD_BASE_DIR |
/APPS/GamesDownloader |
Host directory under which all persistent data is stored. Point this at a large disk. |
GD_PORT |
8080 |
Host port mapped to the container's web UI. |
PUID / PGID
|
empty (root) | Optional. Run the container's processes as a specific user/group so files on the host are owned by you, not root. See below. |
GD_DEBUG |
false |
Verbose logging and relaxed checks. Never enable in production - among other things it downgrades the secret-key safety guard. |
| Variable | Default | What it does |
|---|---|---|
DB_NAME |
gamesdownloader |
Database name. |
DB_USER |
gd |
Application database user. |
DB_PASSWD |
change-me-strong-random |
Password for DB_USER. Change it.
|
DB_ROOT_PASSWD |
change-me-root-strong-random |
MariaDB root password. Change it. |
Important:
DB_ROOT_PASSWDis applied once, on the very first start of the MariaDB container, and baked into its data volume. Changing it in.envlater does not change it in an existing database. Set a strong value before the first start.
Generate strong values with:
openssl rand -hex 24| Variable | Default | What it does |
|---|---|---|
REDIS_PASSWORD |
change-me-redis-strong-random |
Password for the Valkey server (used for sessions, brute-force counters, job queue). Change it. |
| Variable | Default | What it does |
|---|---|---|
GD_AUTH_SECRET_KEY |
change-me-in-production |
Signs JWT session tokens and derives the key that encrypts secrets at rest (SMTP password, OAuth client secrets, scraper API keys). |
Behaviour:
- If you leave it at
change-me-in-productionor empty, the container auto-generates a 256-bit key on first start and saves it to/data/config/.secret_key(inside a mounted volume, so it survives rebuilds). This is the recommended path for most users. - If you set your own, use a long random string:
openssl rand -hex 32. -
Keep
/data/config/.secret_keysafe. Losing it invalidates every session and makes encrypted-at-rest secrets unrecoverable (you would have to re-enter your scraper keys and SMTP password). - A known-weak or empty key is refused at startup - the server will not sign tokens with an insecure secret.
These can be left blank and configured later in the setup wizard or Settings → Metadata. They are stored encrypted in the database; the env vars are only a convenience for pre-seeding.
| Variable | Service |
|---|---|
IGDB_CLIENT_ID, IGDB_CLIENT_SECRET
|
IGDB (Twitch developer app) |
RAWG_API_KEY |
RAWG.io |
STEAMGRIDDB_API_KEY |
SteamGridDB |
SCREENSCRAPER_USERNAME, SCREENSCRAPER_PASSWORD
|
ScreenScraper.fr |
RA_API_KEY |
RetroAchievements (optional) |
See Scrapers & Metadata for where to obtain each key and how title matching works.
Uncomment in .env to override defaults:
# GD_TOKEN_EXPIRE_MIN=60 # access-token lifetime in minutes
# GD_REFRESH_EXPIRE_DAYS=7 # refresh-token lifetime in daysdocker compose up -dThis starts three containers:
| Container | Image | Role |
|---|---|---|
GamesDownloader |
built or 60plus/gamesdownloader
|
The application (web UI, API, workers, ClamAV, Transmission). |
gd-mariadb |
mariadb:11.3 |
Database. |
gd-redis |
valkey/valkey:8 |
Cache, sessions, brute-force counters, job queue. |
The app waits for MariaDB and Valkey to report healthy before it starts (Compose depends_on with health conditions), so a clean up may take a moment before the app begins initialising.
The first start does more work than later ones, and it is normal for the web UI to be unavailable for 60-120 seconds:
- The database schema is created and migrated.
- The app downloads the LaunchBox metadata archive (~150 MB) and parses it into an on-disk SQLite index (used for ROM cover art and metadata). This happens before the API binds.
- ROM platform directories are created under
data/games/roms/. - If
GD_AUTH_SECRET_KEYwas left at its default, a secret key is generated and written todata/config/.secret_key.
Because of the LaunchBox step, the container's health check uses a 120 second start_period - the orchestrator will not mark it unhealthy during that window. If you watch docker compose logs -f gamesdownloader you will see the metadata parse progress, then a line indicating the API is listening on port 8080.
Open http://localhost:8080 (or http://<server-ip>:8080 from another device on your LAN). On first run you are greeted by a 7-step setup wizard, no shell access required:
- Welcome - pick your interface language (8 available).
- Admin account - create the first administrator (username, email, password).
- GOG account - optionally connect a GOG account for library sync (can be done later in Profile).
- Scrapers - enter IGDB, RAWG, ScreenScraper, SteamGridDB keys (all optional, changeable later).
- Preferences - default library view, theme, and related options.
- Review - confirm your choices.
- Finish - the wizard writes settings and drops you into the app.
Everything chosen here can be changed afterwards in Settings. The wizard only appears while no admin account exists.
A few features need a one-time nudge after install:
- ClamAV antivirus (optional): go to Settings → Security → ClamAV and click Update Definitions to download the virus database (~300 MB). The ClamAV daemon starts automatically once definitions are present. Until then, upload/download scanning is simply inactive - the app runs fine without it.
-
Transmission / torrents (optional): the Transmission daemon starts inside the container automatically. Enable it in Settings → Downloads → Transmission. If you want inbound peer connections, expose ports
9091(WebUI) and51413(peers) through your firewall. -
ROMs: place ROM files in
GD_BASE_DIR/data/games/roms/{platform}/(for exampleroms/snes/,roms/n64/), then use Scan ROMs in the Emulation library. See ROMs & Emulation.
Everything persistent sits under GD_BASE_DIR on the host. The most important directories:
| Path | Contents |
|---|---|
data/games/GOG |
Published GOG game files |
data/games/CUSTOM |
Custom game files (uploaded, torrent, scanned) |
data/games/roms/{platform} |
ROM files per platform |
data/downloads |
GOG installer staging (pre-publish) |
data/resources/... |
Downloaded artwork, save states, avatars, platform art |
data/config |
settings.yaml, the .secret_key, LaunchBox index, Transmission config |
data/plugins |
Installed plugins, one subdirectory each |
data/clamav |
ClamAV virus definitions |
data/db |
MariaDB data files |
data/redis |
Valkey persistence |
The full volume table (including per-user save-state and media paths) is on the Configuration page. Back up data/db and data/config at minimum - the database plus the secret key are what make your library and encrypted settings recoverable.
By default the container runs as root, so files it writes on the host are root-owned. To have them owned by your own user, find your IDs on the host:
id -u # -> PUID
id -g # -> PGIDPut those into .env:
PUID=1000
PGID=1000Then recreate the app container (docker compose up -d). New files will be owned by that user/group. If you switch this on an existing install, you may need to chown -R the GD_BASE_DIR once so previously root-owned files are readable.
docker compose pull gamesdownloader
docker compose up -d gamesdownloadergit pull
docker compose build gamesdownloader
docker compose up -d gamesdownloaderDatabase schema migrations run automatically on start. Your data volumes are untouched by an image rebuild. It is good practice to back up data/db before a major upgrade.
Tip: pin a specific image tag (e.g.
60plus/gamesdownloader:1.0.16) instead oflatestif you prefer to review release notes before each upgrade.
The app exposes a health endpoint that also reports the running version:
curl http://localhost:8080/api/health
# {"status":"ok","version":"1.0.16"}Check container status and logs:
docker compose ps
docker compose logs -f gamesdownloaderA healthy stack shows all three containers Up and the app (healthy) once the first-boot window has passed.
To stop the stack but keep your data:
docker compose downTo remove the containers and delete all data (this is destructive and irreversible):
docker compose down
rm -rf "$GD_BASE_DIR" # deletes the database, library, artwork, everythingTo reset just the application state (fresh setup wizard) while keeping your game files, remove data/db and data/redis but leave data/games in place. Note that this also discards users, settings, and scraped metadata.
Next: Configuration for the full settings tour, or Reverse Proxy & HTTPS if you plan to expose the instance beyond your LAN.
Getting Started
Configuration
Features
- Dashboard
- Library
- Collections
- Game Requests
- GOG Integration
- ROMs & Emulation
- Downloads & Torrents
- Users & Permissions
- Themes
Plugin Development
Reference