Skip to content

Installation

60plus edited this page Jul 7, 2026 · 12 revisions

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.example to .env, change the four passwords, run docker compose up -d, and open http://localhost:8080. Everything below is the detail behind those four steps.


Contents


Requirements

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.


Step 1: Get the files

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 .env

There are two ways to run the app container itself:

Option A - prebuilt image from Docker Hub (recommended)

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 line

Available 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.

Option B - build from source

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.


Step 2: Configure .env

Open .env. At minimum, change every password before the instance is reachable by anyone but you. Here is every variable:

Paths and ports

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.

Database (MariaDB)

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_PASSWD is applied once, on the very first start of the MariaDB container, and baked into its data volume. Changing it in .env later does not change it in an existing database. Set a strong value before the first start.

Generate strong values with:

openssl rand -hex 24

Cache / queue (Redis / Valkey)

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.

Auth secret key

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-production or 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_key safe. 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.

Metadata API keys (all optional)

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.

Optional token expiry

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 days

Step 3: Start the stack

docker compose up -d

This 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.


First boot: what happens

The first start does more work than later ones, and it is normal for the web UI to be unavailable for 60-120 seconds:

  1. The database schema is created and migrated.
  2. 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.
  3. ROM platform directories are created under data/games/roms/.
  4. If GD_AUTH_SECRET_KEY was left at its default, a secret key is generated and written to data/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.


The setup wizard

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:

  1. Welcome - pick your interface language (8 available).
  2. Admin account - create the first administrator (username, email, password).
  3. GOG account - optionally connect a GOG account for library sync (can be done later in Profile).
  4. Scrapers - enter IGDB, RAWG, ScreenScraper, SteamGridDB keys (all optional, changeable later).
  5. Preferences - default library view, theme, and related options.
  6. Review - confirm your choices.
  7. 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.


Post-install steps

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) and 51413 (peers) through your firewall.
  • ROMs: place ROM files in GD_BASE_DIR/data/games/roms/{platform}/ (for example roms/snes/, roms/n64/), then use Scan ROMs in the Emulation library. See ROMs & Emulation.

Where your data lives

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.


Running as a non-root user (PUID/PGID)

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    # -> PGID

Put those into .env:

PUID=1000
PGID=1000

Then 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.


Updating

If you use the prebuilt image (Option A)

docker compose pull gamesdownloader
docker compose up -d gamesdownloader

If you build from source (Option B)

git pull
docker compose build gamesdownloader
docker compose up -d gamesdownloader

Database 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 of latest if you prefer to review release notes before each upgrade.


Verifying the install

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 gamesdownloader

A healthy stack shows all three containers Up and the app (healthy) once the first-boot window has passed.


Resetting / uninstalling

To stop the stack but keep your data:

docker compose down

To 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, everything

To 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.

Clone this wiki locally