Skip to content

Installation

Orb ships as a single Go binary that serves everything — the web UI, the JSON API, the Subsonic endpoint, DLNA, and the Chromecast proxy — on one port. It needs two companion services to run: PostgreSQL (the database) and Valkey (a Redis-compatible key-value store for sessions, queues, and live features). The bundled Docker Compose stack wires all three together for you.

Clone the repository and bring the stack up:

git clone https://github.com/alexander-bruun/orb.git
cd orb
make docker-up

make docker-up is a thin wrapper around docker compose up -d --build --force-recreate. The compose file (compose.yaml) builds the unified Orb image, generates the database password and JWT signing key as Docker secrets on first run, and starts Postgres and Valkey alongside the app. Everything is exposed to the host on port 3000 by default.

Host port Service
3000 Web UI + API + Subsonic + DLNA HTTP + Cast proxy

A prebuilt multi-architecture image is also published as alexbruun/orb on Docker Hub if you would rather not build locally — point your own compose file's app service at it with image: alexbruun/orb instead of the build: block.

First run

  1. Open http://localhost:3000. The first visit lands on a one-time setup page — the account you create here becomes the admin.
  2. Mount your media into the app container and point Orb at it. Edit the volumes: block in compose.yaml to map your folders (the defaults map /movies, /shows, /music, /audiobooks, and /comics), then register each one as a library under Admin → Libraries. Libraries are managed entirely from the UI — see Your library.
  3. Add metadata-provider credentials where needed (TMDB for movies/TV, Comic Vine for comics, and so on) under Admin → Plugins and Admin → Settings → Integrations. See Metadata plugins.

The first scan starts as soon as a library is created; progress shows in the top bar.

Hardware acceleration (video transcoding)

The container ships jellyfin-ffmpeg7 with NVENC/NVDEC, VAAPI, QSV, and AMF enabled. The host must expose its GPU to the container for hardware decode/encode of 4K HEVC/HDR content; without it, video falls back to software encoding (~0.3× realtime on a single core).

This is not just a speed difference — it sets the quality ceiling for browser playback. With no reachable GPU, a software transcode of a >1080p source can't keep realtime, so the player's quality menu caps the default at 720p and flags the 1080p/2160p rungs with a ⚠ ("server has no GPU"). Pass a GPU through and the full 2160p/1080p/720p/480p ladder is offered warning-free. The Direct (source) entry in the quality menu always plays the original file untouched regardless of server hardware — it's the GPU-free path to full resolution/HDR, but only on a client that can decode the source (the desktop native player handles HDR/HEVC the browser can't).

The shipped compose.yaml is configured for Podman + CDI by default (see the comment block in the app service). For Docker — including Docker Desktop on Windows — replace the devices: - nvidia.com/gpu=0 line with the snippet for your platform below.

Family Platforms Section
nvenc (NVIDIA) Linux (Docker, Podman), Windows (Docker Desktop / WSL2) NVIDIA
vaapi (Intel/AMD) Linux Intel / AMD VAAPI
qsv (Intel) Linux Intel / AMD VAAPI
amf (AMD) Windows (host-only, see note)
videotoolbox macOS (host-only, see note)

Set VIDEO_HWACCEL in the app service's environment: block to force a family (nvenc, vaapi, qsv, amf); the server otherwise auto-detects. On startup the API logs the detected pipeline as video: hwaccel family=nvenc h264=h264_nvenc hevc=hevc_nvenc tonemap=tonemap_cuda — check this line to verify the GPU is actually being used.

NVIDIA

Linux + Podman (default in compose.yaml)

Install the NVIDIA Container Toolkit, then generate a CDI spec on the host:

sudo dnf install nvidia-container-toolkit   # or apt / pacman equivalent
sudo nvidia-ctk cdi generate --output=/etc/cdi/nvidia.yaml

compose.yaml already references nvidia.com/gpu=0. If your podman-compose silently ignores the devices: key (older versions do), drop compose and run via the raw command:

podman run --device nvidia.com/gpu=all <image>

Linux + Docker

Install nvidia-container-toolkit and configure the Docker runtime, then in compose.yaml replace:

    devices:
      - nvidia.com/gpu=0

with:

    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Equivalent for docker run: --gpus all.

Windows — Docker Desktop

Docker Desktop on Windows has two backends, and only the WSL2 backend can pass an NVIDIA GPU into a Linux container:

Backend NVIDIA GPU passthrough Notes
WSL2 ✅ Supported Windows driver is exposed automatically.
Hyper-V ❌ Not supported MobyLinuxVM has no GPU access — see workarounds.

If you're on the Hyper-V backend (Settings → General → "Use the WSL 2 based engine" is unchecked), Docker Desktop cannot give the container access to your GPU at all. Your options:

  1. Switch Docker Desktop to the WSL2 backend (Settings → General → enable "Use the WSL 2 based engine", restart Docker Desktop). This is one toggle and does not require you to run anything else under WSL — Docker Desktop manages the WSL distro internally. Then follow the WSL2 instructions below.
  2. Run the API binary natively on Windows instead of in a container. The server detects NVENC (NVIDIA) and AMF (AMD) directly through the Windows ffmpeg build, no Docker involved. Postgres and Valkey can still run in Docker. See Running the API natively on Windows below.
  3. Accept software-only transcoding. The server will detect that no GPU is exposed and fall back to libx264 / libx265. On a modern desktop CPU this handles 1080p comfortably but stutters on 4K HEVC.

There is no compose-side trick that works around the Hyper-V backend — the limitation is in the VM, not in Docker.

Windows — Docker Desktop with WSL2 backend

Docker Desktop passes NVIDIA GPUs through the WSL2 backend with no separate Linux driver install — the Windows driver is exposed automatically.

Prerequisites

  1. Windows 11 (or Windows 10 21H2+) with WSL2 enabled.
  2. Docker Desktop 4.0+ with the WSL2 backend selected (Settings → General → "Use the WSL 2 based engine" is checked).
  3. Up-to-date NVIDIA Windows driver (Game Ready / Studio R470 or later). No CUDA toolkit and no nvidia-container-toolkit install required — Docker Desktop bundles the integration.
  4. Verify the GPU is visible to the Docker Desktop WSL distro:
    wsl -d docker-desktop -- nvidia-smi
    
    You should see your GPU listed. If nvidia-smi is not found, update the Windows NVIDIA driver and restart Docker Desktop.

Compose change

In compose.yaml's app service, replace the podman CDI line with the standard Docker Compose form:

    # devices:                          # ← remove the podman CDI line
    #   - nvidia.com/gpu=0
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: all
              capabilities: [gpu]

Keep the NVIDIA_DRIVER_CAPABILITIES: "compute,video,utility" environment variable — Docker Desktop honours it and it is what tells the runtime to expose the NVENC/NVDEC libraries inside the container (without it, only compute is exposed and ffmpeg -encoders | grep nvenc will be empty).

Volume mount caveat

The default compose.yaml mounts /data/Movies (a Linux path) into the container. On Windows, change those host paths to Windows-style mounts — e.g.:

    volumes:
      - app_data:/data
      - app_secrets:/run/secrets:ro
      - C:/Users/you/Videos/Movies:/movies:ro
      - C:/Users/you/Videos/Shows:/shows:ro
      - C:/Users/you/Music:/music:ro
      - C:/Users/you/Audiobooks:/audiobooks:ro

(Forward slashes are required in compose; backslashes break the YAML parser.)

Verify

After docker compose up -d app, confirm both the runtime and the encoders:

docker compose exec app nvidia-smi
docker compose exec app ffmpeg -hide_banner -encoders | Select-String nvenc

The first command should print a GPU table; the second should list h264_nvenc, hevc_nvenc, and (on Turing+) av1_nvenc. If the second is empty, NVIDIA_DRIVER_CAPABILITIES is not set to include video.

Running the API natively on Windows

If you're committed to the Hyper-V backend or don't want to involve Docker Desktop for the API at all, run Postgres and Valkey from compose but the API binary directly on the Windows host. The Windows build picks up NVENC (NVIDIA) and AMF (AMD) from the system ffmpeg:

# Start the stateful services in Docker
docker compose up -d postgres valkey

# Run the API on the host. Adjust paths and the build target as needed.
$env:DB_HOST       = "localhost"
$env:KV_ADDR       = "localhost:6379"
$env:STORE_ROOT    = "C:\OrbData"
$env:VIDEO_HWACCEL = "nvenc"   # or "amf" on AMD GPUs
go run .\services\cmd

This bypasses the Docker GPU layer entirely; ffmpeg talks to the Windows NVENC / AMF drivers directly. You'll need a ffmpeg binary on PATH with the relevant encoders (ffmpeg -hide_banner -encoders | findstr nvenc).

Intel Quick Sync / AMD VAAPI (Linux)

services:
  app:
    devices:
      - /dev/dri:/dev/dri
    group_add:
      - "video"
      - "render"

Quick Sync and VAAPI are not available on Docker Desktop (Windows or macOS) — the WSL2 / hypervisor layer does not pass /dev/dri through. Use a native Linux host or run the API outside the container.

Apple Silicon (host runs natively, not in Docker)

VideoToolbox is not available inside Linux containers. For macOS hosts, run the API binary directly rather than via Docker if you need hardware transcoding.

AMD AMF (Windows)

AMF is a Windows-host-only encoder; it is not reachable from inside a Linux container. On a Windows host, run the API binary directly to use AMF.

Next steps

  • Configuration — every environment variable and the settings managed from the admin UI.
  • Your library — register media roots and lay out your files so they index cleanly.