How to Deploy Prowlarr: Unified Torrent and Usenet Indexer Management with Docker Compose

Prowlarr is a centralized indexer and tracker proxy for Sonarr, Radarr, and the *arr ecosystem that eliminates redundant indexer configuration. Learn how to deploy Prowlarr using Docker Compose, secure owner authentication, add public or private trackers, and automatically sync indexers across downstream PVR apps.

How to Deploy Prowlarr: Unified Torrent and Usenet Indexer Management with Docker Compose

Prowlarr is an open-source indexer and tracker management proxy built on the popular \*arr technology stack, licensed under the GNU General Public License v3.0 (GPL-3.0). Homelab operators running media management stacks (such as Sonarr, Radarr, Lidarr, and Readarr) frequently face a maintenance challenge: configuring the same BitTorrent trackers and Usenet Newznab providers across every application individually. When an indexer domain changes, credentials rotate, or API rate limits require tuning, administrators must replicate those adjustments manually across each downstream service.

Prowlarr Multi-Indexer Search Payoff

Prowlarr eliminates this operational overhead by serving as a unified gateway and central proxy for all indexers. Rather than configuring each PVR app separately, you configure your torrent trackers and Usenet indexers once in Prowlarr. Prowlarr translates requests across disparate indexer protocols, manages rate limits, tests upstream connectivity, and automatically provisions downstream applications over their native REST APIs.

Core Capabilities and Architecture

  1. Unified Indexer & Tracker Gateway: Supports Usenet natively across 24+ built-in presets (plus generic Newznab compatibility) and BitTorrent across more than 650 trackers via Cardigann YML definitions (plus generic Torznab endpoints).
  2. Automated Downstream Application Sync: Synchronizes indexers, search priorities, category mappings, and download profiles directly to Sonarr, Radarr, Lidarr, Readarr, and Mylar3 via their REST APIs. Changes made in Prowlarr automatically push downstream.
  3. Cardigann Definition Engine: Utilizes dynamic YAML tracker definitions that parse JSON, XML, and HTML endpoints without requiring core application recompilation.
  4. Aggregated Multi-Indexer Search: Provides a centralized search interface that fans out queries concurrently to all active indexers, aggregates results, standardizes release metadata, and dispatches release grabs directly to download clients (such as qBittorrent, Transmission, Deluge, and SABnzbd).
  5. Modern Stack Architecture: Engineered on an ASP.NET Core Kestrel backend running .NET 8, backed by an embedded SQLite database (with optional PostgreSQL support), and paired with a responsive React single-page application.
  6. Programmatic REST API: Exposes a full-featured /api/v1 REST interface secured via cryptographic X-Api-Key headers for automated health checks, indexer provisioning, and remote search operations.

---

Prerequisites

Before deploying Prowlarr, ensure your host environment meets the following requirements:

  • Operating System: Linux (Ubuntu 22.04/24.04 LTS, Debian 12+, Rocky Linux, Fedora, Arch Linux), macOS, or Windows with WSL2.
  • Container Runtime: Docker Engine 20.10+ with Docker Compose v2 (docker compose version v2.24+ recommended).
  • Hardware Resources:

- CPU: 1 to 2 vCPU cores. Prowlarr is resource-efficient and typically runs at negligible CPU utilization outside of active multi-tracker searches. - Memory: 1 GB RAM minimum, 2 GB recommended (sufficient to support Prowlarr alongside companion downstream apps like Sonarr). - Storage: 5 GB+ free disk space for container images, persistent application state, and SQLite database storage.

  • Network Ports:

- Prowlarr Web UI and REST API: Host port 3000 (or default 9696). - Downstream companion (Sonarr): Host port 8989.

  • User Permissions: Non-root user ID and Group ID (PUID=1000, PGID=1000) for correct ownership of bind-mounted host storage.

---

Exact Install Steps

The deployment uses Docker Compose to run the official upstream-endorsed LinuxServer image (lscr.io/linuxserver/prowlarr:latest) alongside a companion Sonarr container (lscr.io/linuxserver/sonarr:latest) on an isolated Docker bridge network (arr).

Step 1: Create Deployment Directory Structure

Create an isolated directory on your host to store configuration files and persistent application databases:

mkdir -p prowlarr/config prowlarr/sonarr
cd prowlarr

Step 2: Configure Environment Variables (.env)

Generate cryptographically secure 16-byte (32-character) hexadecimal API tokens for both Prowlarr and Sonarr, and write the .env configuration file:

# Generate 32-character hexadecimal API tokens
API_KEY=$(openssl rand -hex 16)
SONARR_KEY=$(openssl rand -hex 16)

cat > .env <<EOF
COMPOSE_PROJECT_NAME=prowlarr-stack
PROWLARR_PORT=3000
SONARR_PORT=8989
PUID=1000
PGID=1000
TZ=Etc/UTC
API_KEY=${API_KEY}
SONARR_KEY=${SONARR_KEY}
EOF

chmod 600 .env

Step 3: Create Docker Compose Configuration (compose.yml)

Create the compose.yml file defining both Prowlarr and Sonarr services with health checks and persistent bind mounts:

cat > compose.yml <<'EOF'
services:
  prowlarr:
    container_name: prowlarr-app
    image: lscr.io/linuxserver/prowlarr:latest
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    ports:
      - "${PROWLARR_PORT}:9696"
    volumes:
      - ./config:/config
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:9696/ping || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 20s
    networks:
      - arr

  sonarr:
    container_name: sonarr-app
    image: lscr.io/linuxserver/sonarr:latest
    restart: unless-stopped
    environment:
      - PUID=${PUID}
      - PGID=${PGID}
      - TZ=${TZ}
    ports:
      - "${SONARR_PORT}:8989"
    volumes:
      - ./sonarr:/config
    healthcheck:
      test: ["CMD-SHELL", "curl -fsS http://127.0.0.1:8989/ping || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 12
      start_period: 20s
    networks:
      - arr

networks:
  arr:
    name: arr-network
EOF

Step 4: Pre-Seed Application Configuration (config.xml)

Pre-seeding config.xml establishes the known API key, disables external update alerts (since updates are managed via Docker image tags), disables telemetry, and allows seamless programmatic bootstrapping without manual setup prompts:

cat > config/config.xml <<EOF
<Config>
  <BindAddress>*</BindAddress>
  <Port>9696</Port>
  <ApiKey>${API_KEY}</ApiKey>
  <AuthenticationMethod>None</AuthenticationMethod>
  <Branch>master</Branch>
  <LogLevel>info</LogLevel>
  <UrlBase></UrlBase>
  <InstanceName>Prowlarr</InstanceName>
  <AnalyticsEnabled>False</AnalyticsEnabled>
  <LaunchBrowser>False</LaunchBrowser>
  <UpdateMechanism>Docker</UpdateMechanism>
</Config>
EOF

cat > sonarr/config.xml <<EOF
<Config>
  <BindAddress>*</BindAddress>
  <Port>8989</Port>
  <ApiKey>${SONARR_KEY}</ApiKey>
  <AuthenticationMethod>None</AuthenticationMethod>
  <Branch>main</Branch>
  <LogLevel>info</LogLevel>
  <UrlBase></UrlBase>
  <InstanceName>Sonarr</InstanceName>
  <AnalyticsEnabled>False</AnalyticsEnabled>
  <LaunchBrowser>False</LaunchBrowser>
  <UpdateMechanism>Docker</UpdateMechanism>
</Config>
EOF

chmod 600 config/config.xml sonarr/config.xml

Step 5: Start the Docker Compose Stack

Pull the container images and launch the services in the background:

docker compose pull
docker compose up -d

Step 6: Verify Service Health

Poll the internal /ping endpoints to confirm both daemons are initialized and responding:

until curl -sf http://localhost:3000/ping >/dev/null; do
  echo "Waiting for Prowlarr..."
  sleep 2
done
echo "Prowlarr is healthy: $(curl -s http://localhost:3000/ping)"

until curl -sf http://localhost:8989/ping >/dev/null; do
  echo "Waiting for Sonarr..."
  sleep 2
done
echo "Sonarr is healthy: $(curl -s http://localhost:8989/ping)"

Expected output:

Prowlarr is healthy: {"status":"OK"}
Sonarr is healthy: {"status":"OK"}

Step 7: Configure Owner Authentication via REST API

Secure Prowlarr immediately with Forms authentication so that unauthenticated visitors are redirected to a login prompt:

ADMIN_USER="admin"
ADMIN_PASS="ShortformDemo-2026!"

# Retrieve current host configuration and enable Forms authentication
CFG=$(curl -sf -H "X-Api-Key: $API_KEY" http://localhost:3000/api/v1/config/host)

UPDATED_CFG=$(python3 -I -c "
import sys, json
d = json.loads('''$CFG''')
d.update(
    authenticationMethod='forms',
    authenticationRequired='enabled',
    username='$ADMIN_USER',
    password='''$ADMIN_PASS''',
    passwordConfirmation='''$ADMIN_PASS''',
    analyticsEnabled=False
)
print(json.dumps(d))
")

curl -sf -X PUT http://localhost:3000/api/v1/config/host/1 \
  -H "X-Api-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "$UPDATED_CFG"

Verify that unauthenticated access now returns an HTTP 302 redirect:

curl -s -o /dev/null -w "%{http_code} -> %{redirect_url}\n" http://localhost:3000/

Expected output:

302 -> http://localhost:3000/login?returnUrl=%2F

---

Browser Setup

Once the stack is initialized and authenticated, access Prowlarr through your web browser to manage indexers, connect downstream apps, and run aggregated searches.

1. Log In to Prowlarr

Navigate to http://localhost:3000 in your web browser. You will be redirected to the Forms login page.

Prowlarr Forms Authentication Login Screen

Enter your configured administrative username (admin) and password, then click Login.

2. The Indexers Dashboard

Upon authenticating, Prowlarr opens the Indexers dashboard.

Prowlarr Configured Indexers

This view lists all active trackers and indexers, indicating their protocol (Torrent or Usenet), privacy status (Public, Semi-Private, or Private), configured tags, and operational health status.

3. Add Indexers from the Built-In Catalog

Click Add Indexer from the top toolbar to browse the catalog of over 650 built-in definitions.

Prowlarr Add Indexer Modal Catalog

  1. Use the search bar to locate an indexer (e.g. Internet Archive, LinuxTracker, or TorrentsCSV).
  2. Click on the desired indexer card to open its settings dialog.
  3. Configure tags (e.g. linux, archive), review query categories, and click Test to verify that Prowlarr can reach the tracker endpoint.
  4. Click Save to enable the indexer.

4. Connect Downstream Applications (Sonarr Sync)

To configure automated indexer synchronization to downstream PVR applications:

  1. Navigate to Settings ▸ Apps in the left sidebar.
  2. Click the + (Add Application) button and select Sonarr.

Prowlarr Settings Applications Sync

  1. Fill in the connection parameters using internal container hostnames on the shared arr network:

- Name: Sonarr - Sync Level: Select Full Sync (Prowlarr will automatically add, update, and remove indexers in Sonarr). - Prowlarr Server: http://prowlarr:9696 (the internal Docker network address Sonarr uses to query Prowlarr). - Sonarr Server: http://sonarr:8989 (the internal Docker network address Prowlarr uses to communicate with Sonarr). - ApiKey: The Sonarr API key generated during installation.

  1. Click Test. Once the test passes, click Save.
  2. Prowlarr immediately triggers an ApplicationIndexerSync task, pushing compatible indexers into Sonarr.

5. Verify Synced Indexers in Sonarr

Open Sonarr in a separate browser tab at http://localhost:8989. Navigate to Settings ▸ Indexers.

Sonarr Indexers Synced from Prowlarr

Notice that the indexer Internet Archive (Prowlarr) is now present in Sonarr automatically. Sonarr queries this indexer through Prowlarr's internal Torznab proxy endpoint (http://prowlarr:9696/1/api).

6. Execute an Aggregated Multi-Tracker Search

Return to Prowlarr and click Search in the navigation bar.

  1. Enter a search query such as ubuntu.
  2. Select categories or leave blank to query all categories.
  3. Click Search.

Prowlarr Multi-Indexer Search Payoff

Prowlarr fans out the query concurrently across all configured indexers. Click on the Peers column header to sort by seeders descending. The results aggregate releases across all trackers—such as ubuntu-26.04-desktop-amd64.iso from LinuxTracker with over 132,000 seeders—with direct download and client dispatch icons.

---

Verification

You can verify the entire deployment and its API integration using standard terminal commands.

1. Verify Running Containers and Ports

docker compose ps

Expected output:

NAME           IMAGE                                COMMAND   SERVICE    CREATED         STATUS                   PORTS
prowlarr-app   lscr.io/linuxserver/prowlarr:latest  "/init"   prowlarr   2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:3000->9696/tcp
sonarr-app     lscr.io/linuxserver/sonarr:latest    "/init"   sonarr     2 minutes ago   Up 2 minutes (healthy)   0.0.0.0:8989->8989/tcp

2. Query System Status and Version

curl -sf -H "X-Api-Key: $API_KEY" http://localhost:3000/api/v1/system/status | python3 -m json.tool

Key fields in output:

{
    "appName": "Prowlarr",
    "version": "2.7.0.5723",
    "runtimeVersion": "8.0.27",
    "osName": "alpine",
    "databaseType": "sqLite",
    "authentication": "forms"
}

3. Check Configured Indexers

Verify active indexers via the REST API:

curl -sf -H "X-Api-Key: $API_KEY" http://localhost:3000/api/v1/indexer | python3 -I -c "
import sys, json
for i in json.load(sys.stdin):
    print(f'#{i[\"id\"]} {i[\"name\"]: <20} protocol={i[\"protocol\"]} enabled={i[\"enable\"]}')
"

Expected output:

#1 Internet Archive     protocol=torrent enabled=True
#2 LinuxTracker         protocol=torrent enabled=True
#3 TorrentsCSV          protocol=torrent enabled=True

4. Verify Downstream App Sync Status

Check which indexers Sonarr has received from Prowlarr:

curl -sf -H "X-Api-Key: $SONARR_KEY" http://localhost:8989/api/v3/indexer | python3 -I -c "
import sys, json
for i in json.load(sys.stdin):
    base_url = [f['value'] for f in i['fields'] if f['name'] == 'baseUrl'][0]
    print(f'Sonarr Indexer: {i[\"name\"]: <28} -> {base_url}')
"

Expected output:

Sonarr Indexer: Internet Archive (Prowlarr)   -> http://prowlarr:9696/1/

5. Execute Multi-Tracker Search via CLI

Test Prowlarr's concurrent search capabilities from the command line:

curl -sf -H "X-Api-Key: $API_KEY" -G "http://localhost:3000/api/v1/search" \
  --data-urlencode "query=ubuntu" \
  -d "type=search" \
  -d "limit=5" | python3 -I -c "
import sys, json
results = json.load(sys.stdin)
print(f'Total releases returned: {len(results)}')
for r in sorted(results, key=lambda x: -(x.get('seeders') or 0))[:5]:
    size_mb = (r.get('size') or 0) / 1048576
    print(f'  {r[\"indexer\"]: <16} {r.get(\"seeders\", 0): >6} seeds  {size_mb: >8.1f} MB  {r[\"title\"][:50]}')
"

Expected output:

Total releases returned: 150
  LinuxTracker     132733 seeds    6246.4 MB  ubuntu-26.04-desktop-amd64.iso
  LinuxTracker       1420 seeds    2457.6 MB  ubuntu-26.04-live-server-amd64.iso

6. Verify System Health and Indexer Stats

Confirm there are no unresolved warnings or failed queries:

curl -sf -H "X-Api-Key: $API_KEY" http://localhost:3000/api/v1/health | python3 -m json.tool

Expected output:

[]

---

Troubleshooting

Symptom / ErrorRoot CauseRemediation Step
Downstream app sync completes but Sonarr lists 0 indexersCategory mismatch. Sonarr only synchronizes indexers configured with TV categories (IDs 5000–5090). Indexers advertising only PC (4000) or Other (8000) are intentionally omitted.Ensure at least one enabled indexer supports TV categories (e.g. Internet Archive), or add general-purpose trackers that carry TV release taxonomies.
Application connection test fails with ECONNREFUSED or timeoutUsing localhost or 127.0.0.1 inside container configuration. In Docker bridge networking, localhost refers to the container itself.Use internal Docker network service names: set Prowlarr Server to http://prowlarr:9696 and Sonarr Server to http://sonarr:8989. Ensure both services share the arr network.
Host port conflict: bind: address already in use on port 3000 or 9696Another service or development server is bound to the target host port.Update PROWLARR_PORT=3002 (or another unused port) in .env and recreate containers using docker compose up -d.
Indexer connectivity test fails with Http request timed outUpstream tracker is slow, rate-limiting requests, or experiencing transient DNS issues.Prowlarr enforces strict HTTP request timeouts during connectivity tests. Retry the test after a moment, or verify tracker status in an external browser.
Indexer returns HTTP 403 Forbidden or Cloudflare challenge pageThe tracker is protected by Cloudflare Turnstile, DDoS mitigation, or geo-blocking.Configure a FlareSolverr proxy container on your network and assign it under Prowlarr Settings ▸ Indexers ▸ Proxies.
UI prompts with "Authentication Required" first-run wizard unexpectedlyContainer was started without pre-seeding config.xml or credentials were not saved to SQLite.Complete the web wizard to set admin credentials, or update config/config.xml with <AuthenticationMethod>Forms</AuthenticationMethod> and restart the container.
Permission denied errors writing to config/prowlarr.dbBind-mounted directory permissions do not match the container's internal UID/GID.Set PUID=1000 and PGID=1000 in .env matching the host user, and execute chown -R 1000:1000 config/ on the host directory.
Database locked or disk I/O errors on SQLiteStoring /config on network-attached storage (NFS or SMB) that lacks POSIX byte-range locking.Mount SQLite database directories strictly on local block storage (ext4, XFS, APFS, or ZFS local pools) rather than network shares.

---

Assumptions & Decisions

  • Container Image Selection: Deployed the official lscr.io/linuxserver/prowlarr:latest image running Prowlarr v2.7.0.5723 (.NET 8.0.27). Upstream Servarr documentation directly endorses LinuxServer images for production container deployments.
  • Companion Downstream Service: Deployed a companion Sonarr container (lscr.io/linuxserver/sonarr:latest) on the shared arr network. Prowlarr's primary architectural purpose is automated indexer synchronization into downstream PVR applications; including Sonarr provides real end-to-end validation of the synchronization engine.
  • Legal Public Indexers for Testing: Seeded public, freely accessible indexers (Internet Archive, LinuxTracker, TorrentsCSV) rather than private trackers or Cloudflare-gated sites. This ensures deterministic, reproducible connectivity tests without requiring external credentials or risking IP bans.
  • Category-Aware Sync Behavior: Identified that Sonarr strictly filters synced indexers against TV category IDs (5000–5090). Trackers offering only PC or general software (such as LinuxTracker) do not push into Sonarr by design. Internet Archive was included specifically to validate full end-to-end sync.
  • Automated Configuration Bootstrapping: Pre-seeded config.xml with known API keys and configured Forms authentication via PUT /api/v1/config/host/1. This eliminates manual first-run wizards, ensures reproducible deployments, and avoids exposing unauthenticated admin dashboards.
  • Payoff Screen Selection: Selected the aggregated multi-indexer search view (final.png) as the primary hero image. Demonstrating a single query returning 150 releases across multiple trackers with six-figure seeder counts visually highlights Prowlarr's core value proposition.
  • Ghost Grid Compatibility: Formatted all troubleshooting guides as GitHub-flavored Markdown tables. Ghost lacks native pipe table rendering, but the downstream ghost-draft pipeline converts GFM tables into Ghost HTML cards automatically.