Getting Started

Prerequisites

You need Docker and Docker Compose installed on your server. Any Linux distribution with Docker CE works. Bazarr+ also runs on macOS and Windows via Docker Desktop, though Linux is recommended for production.

That is the whole requirement, because there are two ways to run Bazarr+. You can connect Sonarr, Radarr or Sportarr and have it fetch subtitles for the library you already have, or you can run it with no library at all and search any film or show by name. Both start from the same install below. If you do run a media stack, keep its host, port and API key to hand for the connection step.

One-liner install

The fastest way to get running. This script creates a directory (default: ./bazarr-plus), writes a docker-compose.yml, and starts the containers.

Shell
curl -fsSL https://lavx.github.io/bazarr/install.sh | bash

The script asks for optional movie, TV and sports folders, and whether to add FlareSolverr or the AI translator. It detects your timezone and user/group IDs automatically. Leave all media paths empty and skip library connections for standalone Discover. Connect Sonarr, Radarr or Sportarr later under Settings > Connections. You can review the script before running it.

Docker Compose setup

For a minimal standalone install, use the homepage Compose example. The example below includes FlareSolverr and the AI translator; remove either service if you do not need it. Uncomment only the movie, TV or sports mounts you use and replace their host paths. Standalone Discover needs only /config.

docker-compose.yml
services:
  bazarr:
    image: ghcr.io/lavx/bazarr:latest
    container_name: bazarr
    restart: unless-stopped
    ports:
      - 6767:6767
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=UTC
    volumes:
      - ./config:/config
      # Optional: uncomment only the media folders you use.
      # - /path/to/movies:/movies
      # - /path/to/tv:/tv
      # - /path/to/sports:/sports
    read_only: true
    tmpfs:
      - /tmp:size=512m
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETUID
      - SETGID
    security_opt:
      - no-new-privileges:true
    healthcheck:
      test: ["CMD-SHELL", "port=$$(cat /tmp/bazarr-supervisor.port 2>/dev/null || echo 6767); case \"$$port\" in \"\"|*[!0-9]*) exit 1 ;; esac; curl -sf \"http://localhost:$$port/_supervisor/status\" | grep -q '\"running\"'"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  # Recommended for the OpenSubtitles.org Provider Hub plugin: solves
  # Cloudflare browser challenges when the in-process scraper is itself
  # challenged. Set this container's /v1 URL in the plugin's FlareSolverr URL.
  flaresolverr:
    image: ghcr.io/flaresolverr/flaresolverr:latest
    container_name: flaresolverr
    restart: unless-stopped
    environment:
      - LOG_LEVEL=info
    healthcheck:
      test: ["CMD", "curl", "-sf", "http://localhost:8191/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 60s

  # AI translation via OpenRouter (free tiers available)
  # Configure the API key in Settings > AI Translator
  ai-subtitle-translator:
    image: ghcr.io/lavx/ai-subtitle-translator:latest
    container_name: ai-subtitle-translator
    restart: unless-stopped
    ports:
      - 8765:8765
    healthcheck:
      test: ["CMD", "curl", "-sf", "http://localhost:8765/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

Then start it:

Shell
docker compose up -d
Changing the port: Bazarr+ listens on the Port under Settings > General, 6767 unless you change it. A new port applies when the container restarts, and the container side of the ports mapping has to match it, for example 6868:6868. Two instances that share a network, with network_mode: host or behind one VPN container, each need a port of their own.

Container hardening

The hardening keys above (read_only, tmpfs, cap_drop, cap_add, security_opt) are what the image is built for. Bazarr+ owns its application tree as root and writes everything at runtime under /config, so freezing the rest of the filesystem costs nothing and keeps a provider plugin's worker process from rewriting the code Bazarr+ imports on its next restart. The /tmp tmpfs is what gives back the one writable path outside /config that is still needed: subtitle bundle downloads spill into it once they outgrow their in-memory buffer, the Provider Hub and sports workers put their per-request temporary directories there, and the alass shim falls back to it when the config cache cannot hold an executable. Extraction and the sync engines do not need it, they already work under /config/cache and beside the destination file. Keep the size= cap: an uncapped tmpfs may grow to half of host RAM, and it is charged to the host rather than to the container.

The three capabilities added back are the ones the startup needs while it is still root: CHOWN to hand /config to your PUID:PGID, and SETUID and SETGID to become that user. Bazarr+ itself, and every Provider Hub worker it starts, runs afterwards with no capabilities at all.

If you run the container with plain docker run instead of Compose, the same settings are:

Shell
docker run -d \
  --name bazarr \
  --read-only \
  --tmpfs /tmp:size=512m \
  --cap-drop ALL \
  --cap-add CHOWN --cap-add SETUID --cap-add SETGID \
  --security-opt no-new-privileges:true \
  -p 6767:6767 \
  -e PUID=1000 -e PGID=1000 -e TZ=UTC \
  -v ./config:/config \
  -v /path/to/movies:/movies \
  -v /path/to/tv:/tv \
  -v /path/to/sports:/sports \
  ghcr.io/lavx/bazarr:latest

Drop any -v /path/to/... line for a folder you do not use: Docker creates a host folder a mount names and does not find, so a copied line invents one on your host.

Developing against your own checkout? Mounting a source tree over /app/bazarr needs a writable filesystem, so drop read_only (or --read-only) for that container. Keep the rest.
OpenSubtitles.org: OpenSubtitles.org is a native Provider Hub plugin you install from the Marketplace. It scrapes the site in-process, so there is no separate scraper container. The FlareSolverr service above is recommended: set its /v1 URL (e.g. http://flaresolverr:8191/v1) in the plugin's FlareSolverr URL setting so it can solve Cloudflare challenges when needed. If you run Bazarr+ with host networking (network_mode: host), the flaresolverr hostname stops resolving: use http://localhost:8191/v1 and make port 8191 reachable on the host, either by adding a 8191:8191 ports mapping to the FlareSolverr service above or running it with host networking too.

First login

Open http://localhost:6767 in your browser. On a fresh install, a guided setup wizard opens automatically. The first thing it asks is what you want Bazarr+ to do: connect the Sonarr, Radarr or Sportarr library you already have, or run on its own with no library. That answer decides which steps it walks you through, so it never asks you for a service you do not run. Installing providers needs a restart to load them; the wizard handles that and resumes where you left off. You can leave it at any time with Set up later and configure everything from Settings instead. It does not come back on its own after that; Settings > General > Run first-time setup starts it again from the beginning.

Whichever path you take, these are the settings that matter:

  1. Set a password. Bazarr+ uses PBKDF2 with 600k iterations, a significant upgrade from upstream's MD5 hashing. Pick something strong.
  2. Choose your languages. Select the subtitle languages you want Bazarr+ to search for. You can set defaults per profile or override per series/movie later.
  3. Add subtitle providers. Enable built-in providers under Subtitle Hub > My Providers. You can also install providers from the Provider Hub Marketplace, which serves a versioned catalog of provider plugins. A catalog plugin can reuse a built-in id and replace the shipped provider, so the two collapse into a single card.
  4. Set provider priority. Use Subtitle Hub > My Providers to order providers. Bazarr+ can try them in priority order and stop early once it finds a match, saving time and API calls.
Startup auto-install: When an official catalog source is enabled, Bazarr+ installs the official-catalog version of your enabled built-in providers on startup. The supervisor reports this as an Installing providers stage, so the first boot after enabling a catalog can take a little longer. If you have no providers enabled yet, the Marketplace shows a nudge to add some.

Running with no library

Bazarr+ does not need Sonarr, Radarr or Sportarr to be useful. Since v2.7.0 it opens on Discover, which works on its own: type a film or show by name, or browse what is trending, what has reached digital and what aired recently, then pick a title, search the providers, preview the subtitle and download the one you want. Nothing has to be indexed first, and there is nothing to sign up for.

Discover authenticates with a metadata key the application carries, so a fresh install can search the moment it is up. If you would rather supply your own, store a TMDB key under Subtitle Hub > My Providers > TMDB.

To run this way, take the Discover path when the wizard asks at first login and connect nothing. The languages and providers from that same wizard are all Discover needs. The Provider Hub and Subtitle Processing guides apply unchanged, and the section below is for readers who do have a library. More on what Discover is and does is on the home page.

Connecting Sonarr, Radarr or Sportarr

Go to Settings > Connections, choose Sonarr, Radarr or Sportarr, and add an instance with:

  • Host and port of the instance, for example 192.168.1.10:8989
  • API key, found in that application's settings
  • Base URL, only needed when the application sits behind a reverse proxy with a path prefix

Click Test to verify the connection, then Save. Bazarr+ will sync that instance and start searching for missing subtitles on the next scheduled scan.

Tip: If the library application and Bazarr+ share the same Docker network, use the container name as the host, for example sonarr instead of an IP address. This avoids issues when IP addresses change.

Next steps