Setup guide

Install putiorr beside your *arr apps.

The production shape is simple: keep SQLite state on persistent storage, use one shared download target mount, and put putiorr on the same Docker network as Radarr, Sonarr, and Lidarr.

Storage layout

Use a persistent config directory for SQLite state and a shared download target that putiorr and each importer can see at the same container path. An SSD or other fast disk is recommended for local copy speed, but path identity is the hard requirement.

Host path Purpose Container path
/volume1/docker/putiorr-config SQLite state and UI-stored put.io credentials /data/putiorr-config
/volume/downloads Download target imported by Radarr, Sonarr, and Lidarr /downloads
/volume/media/movies Final Radarr library /movies
/volume/media/series Final Sonarr library /series
/volume/media/music Final Lidarr library /music

The important rule is path identity. If putiorr reports /downloads/sonarr, the Sonarr container must also see /downloads/sonarr. Mount the same host folder into putiorr and every *arr container at the same target path to avoid custom Remote Path Mapping.

Compose service

Run the release image on the same Docker network as the *arr stack. A host port mapping is optional for browser access; it is not required for Radarr, Sonarr, or Lidarr when they share the Docker network and use putiorr:9091.

services:
  putiorr:
    image: ghcr.io/ptheofan/putiorr:latest
    restart: unless-stopped
    environment:
      TZ: Europe/Athens
      PUTIORR_LISTEN_HOST: 0.0.0.0
      PUTIORR_LISTEN_PORT: 9091
      PUTIORR_STATE_PATH: /data/putiorr-config/putiorr.sqlite
      PUTIORR_TARGET_DIR: /downloads
      PUTIORR_WORKERS: "4"
      PUTIORR_CLEANUP_REMOTE_FILES: "true"
    volumes:
      - /volume1/docker/putiorr-config:/data/putiorr-config
      - /volume/downloads:/downloads

*arr mounts

Each importer needs the shared download target mount plus its own final library mount. The examples below show only the relevant volumes.

services:
  radarr:
    volumes:
      - /volume/downloads:/downloads
      - /volume/media/movies:/movies

  sonarr:
    volumes:
      - /volume/downloads:/downloads
      - /volume/media/series:/series

  lidarr:
    volumes:
      - /volume/downloads:/downloads
      - /volume/media/music:/music

Connect put.io

Hosted OAuth relay

Hosted relay mode is the default. Open the putiorr web UI, choose Connect with put.io, and complete the browser authorization. The relay only returns the token to the user's putiorr instance.

The hosted callback is https://ptheofan.github.io/putiorr/putio-oauth-relay.html.

Direct token

Manual token paste is available in the same connection dialog. Use it when OAuth is not appropriate or when rotating a token explicitly.

Self-hosted redirect

For a private OAuth app, set PUTIORR_PUBLIC_URL to the externally reachable putiorr base URL and register https://your-putiorr-host/api/oauth/callback with put.io. Set PUTIORR_PUTIO_OAUTH_RELAY_URL empty when using direct self-hosted callbacks.

Key environment variables

Variable Default Use
PUTIORR_LISTEN_PORT 9091 HTTP and Transmission RPC port inside the container.
PUTIORR_TARGET_DIR ./downloads Default local download root; production examples use /downloads.
PUTIORR_STATE_PATH ./data/putiorr.sqlite SQLite state database path.
PUTIORR_WORKERS 4 Concurrent local file downloads.
PUTIORR_RPC_USERNAME unset Optional HTTP basic auth username for dashboard and RPC access.
PUTIORR_RPC_PASSWORD unset Optional HTTP basic auth password.