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.
Docker Compose (recommended)¶
Clone the repository and bring the stack 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/orbon Docker Hub if you would rather not build locally — point your own compose file'sappservice at it withimage: alexbruun/orbinstead of thebuild:block.
First run¶
- Open
http://localhost:3000. The first visit lands on a one-time setup page — the account you create here becomes the admin. - Mount your media into the
appcontainer and point Orb at it. Edit thevolumes:block incompose.yamlto 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. - 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:
Linux + Docker¶
Install nvidia-container-toolkit
and configure the Docker runtime, then in compose.yaml replace:
with:
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:
- 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.
- 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.
- 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
- Windows 11 (or Windows 10 21H2+) with WSL2 enabled.
- Docker Desktop 4.0+ with the WSL2 backend selected (Settings → General → "Use the WSL 2 based engine" is checked).
- Up-to-date NVIDIA Windows driver (Game Ready / Studio R470 or later).
No CUDA toolkit and no
nvidia-container-toolkitinstall required — Docker Desktop bundles the integration. - Verify the GPU is visible to the Docker Desktop WSL distro:
You should see your GPU listed. If
nvidia-smiis 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)¶
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.