Docker and environment¶
See the quick start for the compose one-liner. The
default command is serve - a persistent GUI, not a one-shot job.
Everything Coldarr persists (coldarr.yaml, the encrypted connection
store + its key, move history) lives under one bind-mounted /config
directory. To run one-shot CLI commands (or a cron job) against that same
volume instead of the GUI, see the
CLI guide.
Environment variables¶
The image understands these variables directly. Everything else (tiers,
tags, thresholds) goes through coldarr.yaml, which supports ${VAR}
substitution against whatever environment variables you pass to the
container.
Container¶
PUID/PGID- The uid/gid the process runs as, so it can read your bind mounts. Same
convention as Radarr/Sonarr/Jellyfin images. Default
1000/1000. Ignored if the container is already started as non-root (docker run --user, composeuser:, a rootless runtime, or a Kubernetes securityContext) - the entrypoint skips straight to running as whatever user it was given. TZ- Container timezone, mostly cosmetic for log timestamps.
COLDARR_CONFIG- Path to the config file. Default
/config/coldarr.yaml(via the image's/configworking directory).
Web server¶
COLDARR_LISTEN_ADDR- Address
servelistens on, in Go'shost:portform - a bare port number is normalized to:port(all interfaces), but anything else must include the colon yourself, e.g.0.0.0.0:8555or127.0.0.1:8555. Default:8478. COLDARR_TLS_CERT_FILE/COLDARR_TLS_KEY_FILE- Certificate and private-key paths. Set both to make
coldarr servelisten with HTTPS directly. COLDARR_TRUSTED_REVERSE_PROXIES_CIDR(TRUSTED_REVERSE_PROXIES_CIDR)- Comma-separated proxy CIDRs whose
Forwarded/X-Forwarded-Proto/X-Forwarded-Hostheaders should be trusted. Headers from other remote IPs are ignored. Coldarr refuses form submissions from other sites, which over plain HTTP it checks by comparing the page's address with theHostheader. A plain-HTTP proxy that rewritesHosttherefore needs to be listed here and sendX-Forwarded-Host, or saving settings fails with a 403.
Sign-in¶
COLDARR_PASSWORD- Password that gates the GUI whenever OIDC is disabled. If unset (and
COLDARR_PASSWORD_FILEisn't either), a random 64-character password is generated on every start and printed to the container's console log, with a warning that it won't survive a restart - set this to keep it stable. Irrelevant once OIDC is enabled. COLDARR_PASSWORD_FILE- Path to a file containing the password (its contents win over
COLDARR_PASSWORDif both are set) - point this at a Docker secret or any file you bind-mount into the container. COLDARR_OIDC_ENABLED/COLDARR_OIDC_ISSUER_URL/COLDARR_OIDC_CLIENT_ID/COLDARR_OIDC_CLIENT_SECRET- OIDC auth overrides. When any are set, env values win over GUI-saved
values. Set
COLDARR_OIDC_ENABLED=falseto disable OIDC entirely for troubleshooting. COLDARR_OIDC_REDIRECT_URL/COLDARR_OIDC_REQUIRED_GROUP/COLDARR_OIDC_GROUPS_CLAIM- Optional OIDC details. Required group defaults to
coldarr; groups claim defaults togroups. COLDARR_OIDC_AUTO_LOGIN- Set to
true/falseto skip straight to the IdP instead of showing a login button, overriding the GUI-saved Settings > Auth checkbox. The login page shown right after signing out stays manual, so logging out doesn't sign you straight back in. COLDARR_OIDC_CLIENT_SECRET_POST- Set to
truefor providers whose client registration usestoken_endpoint_auth_method: client_secret_post(common with Authelia). The GUI exposes this as a checkbox under Settings > Auth.
Connections¶
RADARR_URL/RADARR_API_KEY(SONARR_*,LIDARR_*,JELLYFIN_*,JELLYFIN_ENABLED)- Connection overrides - see Connections.
QBITTORRENT_URL/QBITTORRENT_API_KEY/QBITTORRENT_USERNAME/QBITTORRENT_PASSWORD- qBittorrent connection overrides. The URL alone is enough when qBittorrent's WebUI skips authentication for Coldarr's address; otherwise set an API key (qBittorrent 5.2+) or a username and password.
Move timing¶
COLDARR_SETTLE_CHECK_INTERVAL/COLDARR_SETTLE_STABLE_CHECKS/COLDARR_SETTLE_MAX_WAIT- Tune how long
applywaits for a move to actually land on disk before starting the next one queued for the same volume (Go duration strings, e.g.5s/6h). Defaults suit typical local disks; raiseMAX_WAITfor very large files on slow/network storage. COLDARR_JELLYFIN_RESOLVE_TIMEOUT/COLDARR_JELLYFIN_RESOLVE_INTERVAL- How long
applywaits, after the moves finish, for Jellyfin to index each item at its new path so its artwork can be refreshed (Go duration strings; defaults15m/10s, the interval backing off to a minute between polls). Raise the timeout if you seeno Jellyfin item appeared at ... withinin the logs - see Jellyfin.
Media paths¶
Tier paths must be bind-mounted at the same path Radarr/Sonarr use internally - Coldarr compares its own disk checks and the root folder paths the Arr APIs report as literal strings, so a mismatched mount looks like a misplaced or unavailable path.
Downloads tiers follow the same rule with qBittorrent: mount the download
drive and seed storage at the same paths qBittorrent uses (if it saves to
/downloads and seeds from /seed, so does Coldarr). Coldarr spots a
download folder mounted from the wrong drive - qBittorrent lists finished
downloads there that Coldarr can't see - and won't move anything to or from
it. Read-only mounts are fine, unless you mark a downloads tier as not
read-only to delete orphaned files in it: then that folder has to be mounted
read-write. See Downloads and seeding.
Example compose file¶
Download the
docker-compose.example.yml
and edit the paths before starting Coldarr. The repository also includes an
.env.example
for optional environment overrides.
Complete compose example
# Example Coldarr deployment. Copy to docker-compose.yml and adjust paths.
#
# Coldarr's default command is `serve` - a persistent web GUI on port 8478 for
# configuring connections/tiers, previewing plans, and applying them by
# hand. If you'd rather script it, override `command` to a one-shot CLI
# call instead (see the commented block below) and drive it from the
# host's own scheduler (cron/systemd timer):
# 0 4 * * * docker compose run --rm coldarr apply --yes
#
# The GUI can view connection status and trigger real moves, so it's
# never reachable unauthenticated: with no OIDC configured (the default),
# it falls back to a single shared password instead - see COLDARR_PASSWORD
# below. Enable OIDC in Settings -> Auth (or with COLDARR_OIDC_* env vars)
# for real identity-provider-backed login and group-based access instead.
#
# Connections (Radarr/Sonarr/Jellyfin URL + API key) can be configured
# either through the GUI (stored encrypted in ./config) or via env vars
# below - env vars always win if both are set. Secrets here come from a
# .env file next to this compose file - see .env.example.
services:
coldarr:
image: ghcr.io/voc0der/coldarr:latest
container_name: coldarr
ports:
- "8478:8478"
# Optional - start the container already as a specific uid:gid instead
# of the default root-then-drop-to-PUID/PGID flow (useful for rootless
# runtimes or policies that forbid containers starting as root, e.g. a
# Kubernetes securityContext). When set, PUID/PGID below are ignored -
# make sure this uid:gid already owns ./config.
# user: "1000:1000"
environment:
PUID: "1000"
PGID: "1000"
TZ: ${TZ:-Etc/UTC}
# Optional - serve HTTPS directly from Coldarr instead of plain HTTP.
# COLDARR_TLS_CERT_FILE: /certs/fullchain.pem
# COLDARR_TLS_KEY_FILE: /certs/privkey.pem
# Optional - trust X-Forwarded-Proto/Host only from these proxy CIDRs.
# COLDARR_TRUSTED_REVERSE_PROXIES_CIDR: 172.18.0.0/16,10.0.0.0/8
# Optional - fixed password for when OIDC is disabled (below). Left
# unset, one is generated and printed to `docker logs coldarr` on
# every start, but won't survive a restart. COLDARR_PASSWORD_FILE
# (path to a Docker secret or bind-mounted file, inside the
# container) overrides this if both are set.
# COLDARR_PASSWORD: ${COLDARR_PASSWORD}
# COLDARR_PASSWORD_FILE: /run/secrets/coldarr_password
# Optional - OIDC auth. These env vars override GUI-saved auth values.
# COLDARR_OIDC_ENABLED: "true"
# COLDARR_OIDC_ISSUER_URL: https://auth.example.com
# COLDARR_OIDC_CLIENT_ID: coldarr
# COLDARR_OIDC_CLIENT_SECRET: ${COLDARR_OIDC_CLIENT_SECRET}
# COLDARR_OIDC_REDIRECT_URL: https://coldarr.example.com/auth/callback
# COLDARR_OIDC_REQUIRED_GROUP: coldarr
# COLDARR_OIDC_GROUPS_CLAIM: groups
# COLDARR_OIDC_CLIENT_SECRET_POST: "true" # Authelia often wants this.
# COLDARR_OIDC_AUTO_LOGIN: "false"
# Optional - omit these and use the GUI's Connections page instead.
# RADARR_URL: http://radarr:7878
# RADARR_API_KEY: ${RADARR_API_KEY}
# SONARR_URL: http://sonarr:8989
# SONARR_API_KEY: ${SONARR_API_KEY}
# JELLYFIN_URL: http://jellyfin:8096
# JELLYFIN_API_KEY: ${JELLYFIN_API_KEY}
# Optional - download tiering (see the docs' "Downloads and seeding").
# The URL alone works if qBittorrent's WebUI skips authentication for
# Coldarr's address; otherwise an API key (qBittorrent 5.2+) or a login.
# QBITTORRENT_URL: http://qbittorrent:8080
# QBITTORRENT_API_KEY: ${QBITTORRENT_API_KEY}
# QBITTORRENT_USERNAME: admin
# QBITTORRENT_PASSWORD: ${QBITTORRENT_PASSWORD}
# LIDARR_URL: http://lidarr:8686
# LIDARR_API_KEY: ${LIDARR_API_KEY}
volumes:
# Everything Coldarr persists lives here: coldarr.yaml, the
# encrypted connection store + its key, and the move-history log.
- ./config:/config
# Optional - if COLDARR_TLS_CERT_FILE / COLDARR_TLS_KEY_FILE point here.
# - ./certs:/certs:ro
# Tier paths: mount at the SAME path Radarr/Sonarr use internally,
# not just the same host path - Coldarr matches Arr API root folder
# paths against these mounts literally. Coldarr only ever reads them
# (disk usage checks, sizing candidates for a plan) - the actual
# move is a moveFiles: true call to Radarr/Sonarr's own API, executed
# by their containers against their own (separate, read-write) mount
# of the same paths. :ro here costs Coldarr nothing and guarantees
# it can't touch your media even if it tried.
- /data/media:/data/media:ro
- /mnt/sat1:/mnt/sat1:ro
- /mnt/sat2:/mnt/sat2:ro
# Optional - download tiering: the download drive and seed storage, at
# the SAME paths qBittorrent uses. qBittorrent does the moving, so :ro
# is fine - unless you mark a downloads tier as not read-only to delete
# orphaned files from the Orphaned Storage page.
# - /mnt/ssd/downloads:/downloads:ro
# - /mnt/seed:/seed:ro
restart: unless-stopped
# If radarr/sonarr/jellyfin are containers in this same compose
# project, put coldarr on their network instead of using service
# names that only resolve there:
# networks:
# - arr-stack
# To run Coldarr as a one-shot CLI instead of the GUI, override the
# command (and drop `ports`/`restart` above, or leave them - they're
# harmless on a short-lived `run`):
# command: ["apply", "--yes"]