Docker Deployment¶
Gadarr runs as one container that serves the Fastify API and the built Vite UI. SQLite data lives under /config, the finished game library is mounted at /games, and download-client paths are exposed through /downloads and optional read-only /data.
Keep real hostnames, LAN IPs, usernames, share names, and private folder layouts out of public docs and screenshots. Use placeholders in examples, then put the real values only in local .env files, compose overrides, or password-manager notes.
Local Docker¶
Open http://localhost:9787.
The local compose file builds from source and tags the result as gadarr:local unless GADARR_IMAGE is changed.
Published Image¶
For installs that should pull a prebuilt image, set these values in the local .env used by Docker Compose:
Then pull and recreate the container while preserving the mounted /config volume:
Fresh installs start with a browser Forms setup screen. Create the Gadarr username and password there; integration API and calendar feed keys are generated behind the scenes unless GADARR_API_KEY or GADARR_CALENDAR_FEED_KEY are provided.
For first testing, keep Gadarr on LAN or VPN only. Do not expose it publicly until Forms auth, feed token, reverse proxy, backups, and restore workflow are verified.
Volumes¶
| Container path | Example host path | Purpose |
|---|---|---|
| Compose project | ./docker/gadarr |
Compose file, local .env, and project notes |
/config |
./docker/gadarr/config |
SQLite database, generated keys, settings, and backups |
/games |
/srv/games |
Writable finished game library |
/downloads |
/srv/downloads |
Download staging path shared with clients such as qBittorrent, Transmission, SABnzbd, or NZBGet |
/data |
/srv/downloads |
Optional read-only download-client root for reported completed paths |
Gadarr data must live in bind mounts, not inside the container. The default database path is /config/gadarr.db. Backups are stored in /config/backups, including SQLite sidecar files when present.
Replacing the container or pulling a new latest image should not remove the database, settings, library, or game folders when /config, /games, and /downloads are mounted to durable host paths.
Environment¶
| Variable | Required | Notes |
|---|---|---|
GADARR_IMAGE |
Prebuilt image installs | Use docker.io/bigbeardedman/gadarr:latest or ghcr.io/bigbeardedman/gadarr:latest |
GADARR_VERSION |
Prebuilt image installs | Human-readable version shown in runtime checks; use latest for the public Docker image path |
GADARR_PORT |
No | Host port, defaults to 9787 |
PUID / PGID |
Docker installs | Must match the owner of the mounted folders |
GADARR_AUTH_METHOD |
No | Defaults to forms; use external only behind a trusted reverse proxy |
GADARR_BASE_URL |
Reverse proxy subpath installs | Optional URL base for static UI, API, feed, and session routes, for example /gadarr |
GADARR_API_KEY |
No | Optional fixed integration token; generated during first-run setup when empty |
GADARR_CALENDAR_FEED_KEY |
No | Optional fixed /feed/calendar/gadarr.ics token; generated during first-run setup when empty |
GADARR_GAMES_DIR |
Docker installs | Host path mounted to /games; for example /srv/games |
GADARR_DOWNLOADS_DIR |
Docker installs | Host path mounted to /downloads; for example /srv/downloads |
GADARR_DATA_DIR |
Docker installs | Host path mounted read-only to /data so Gadarr can read completed paths reported by download clients |
PROWLARR_URL |
If using Prowlarr | http://prowlarr:9696 on the same compose network, or another private URL |
PROWLARR_API_KEY |
If using Prowlarr | Stays server-side |
PROWLARR_GAME_CATEGORIES |
No | Optional comma-separated category ids; empty uses game-safe defaults 1000,4000,4050, set all to disable filters |
Leave GADARR_API_KEY, GADARR_CALENDAR_FEED_KEY, and provider API-key variables empty unless you intentionally manage fixed integration tokens outside the repository.
Prowlarr And Download Clients¶
If Prowlarr is in the same compose project/network, set:
If Prowlarr is in another container stack or on another host, use its private URL:
For download clients, keep downloads separate from the final /games library. Gadarr monitors the configured category, destination, or provider-specific identifier, waits until the client reports the download as complete, then imports from the reported path into /games/<Game>/<Release>. For torrents, Gadarr tries to hardlink first so seeding can continue without duplicate disk usage, and falls back to copy if hardlinks are not available.
If a download client reports a host path that is not the same path inside the Gadarr container, add a mapping in Settings -> Download Clients -> Remote Path Mappings. For example:
| Host | Remote Path | Local Path |
|---|---|---|
qbittorrent |
/srv/downloads/gadarr/torrents |
/downloads/gadarr/torrents |
transmission |
/downloads/complete |
/data/complete |
sabnzbd |
/downloads/usenet/complete |
/downloads/usenet/complete |
This mirrors the Sonarr/Radarr Docker pattern: the download client can keep its own path, and Gadarr translates that reported path to the bind mount visible inside the Gadarr container before importing.
Import behavior is configurable in Settings -> Game Management. The default imports immediately with hardlink/copy fallback, verifies non-empty completed downloads, and keeps the download-client source path for seeding or external retention. Optional trust policy can compute and require an allowlisted SHA-256 checksum or a .gadarr.sig Ed25519 signature manifest before import. Dry-run mode stages imports for manual Apply, and Remove Completed can be enabled only when you intentionally want Gadarr to delete the completed download after import.
Activity -> Import can review a completed download path before staging it. Reviewing /downloads lists its immediate children with inferred games, target paths, replacement warnings, trust-policy results, and approval/rejection reasons. Approved rows can be staged or applied from the review table; staged rows can be rejected before they touch the library.
When Backup Target is enabled and an import replaces an existing file or folder, Gadarr records the old target as the import backup. Applied imports with a recorded backup can be rolled back from Activity -> Import; rollback restores the previous target and moves the imported artifact aside for manual inspection.
Signed manifests live either beside a file as <download>.gadarr.sig or inside a completed folder as .gadarr.sig. The signed payload is gadarr-import-v1\nsha256:<checksum>\n, and the manifest format is:
{
"algorithm": "ed25519",
"checksum": "sha256:<completed-download-sha256>",
"signature": "<base64-signature>"
}
Published Images¶
GitHub Actions publishes multi-arch images to GHCR and, when Docker Hub repository settings are present, Docker Hub. Public Docker installs should use:
docker.io/bigbeardedman/gadarr:latestghcr.io/bigbeardedman/gadarr:latest
The workflow also publishes traceability tags for maintainers and semver tags after release tags are created, but user-facing install docs should point to latest.
The Docker Hub job uses repository variable DOCKERHUB_REPOSITORY plus the DOCKERHUB_USERNAME and DOCKERHUB_TOKEN Actions secrets. Keep those values in GitHub Actions settings only; do not commit them to the repo or bake them into an image.
Linux servers, Portainer, Unraid, and other Compose-capable hosts should pull the image instead of building from source.
Backups And Updates¶
- Create backups from System -> Backups before updating.
- Backups are SQLite
.dbfiles under/config/backups. - Restore stages a selected backup as
/config/gadarr.db.restore-pending; restart the container to apply it before SQLite opens. - To update a Docker install, pull the newer image and recreate the container while preserving
/config. - If the container cannot write
/config, fix host folder ownership with the host file manager orchown.
Build Checks¶
Before publishing an image, run:
Documentation-only publishes should run the documentation agent. It verifies docs, screenshots, README screenshot embeds, source-backed claims, Sonarr parity scripts, and git diff --check without implying that the runtime changed:
After pushing a docs-only commit, prove GitHub has the same commit: