Deployment
NVR is one small static binary — pick the packaging that fits your box. All variants run the same daemon and the same config.yaml.
Docker#
The image ships the daemon plus ffmpeg and nothing else. It exposes port 8085 and uses three volumes:
| Path | What lives there |
|---|---|
/etc/nvrd | Your config.yaml (and license token file) |
/recordings | Footage — point this at your big storage |
/var/lib/nvrd | The index and daemon state — fast local disk is fine |
services:
nvrd:
image: ghcr.io/nvr/nvrd
restart: unless-stopped
ports:
- "8085:8085"
volumes:
- ./config.yaml:/etc/nvrd/config.yaml:ro
- /srv/nvr/recordings:/recordings
- nvrd-state:/var/lib/nvrd
volumes:
nvrd-state: The container runs as an unprivileged nvr user — make sure the recordings mount is writable by it.
For unattended container updates, follow :latest and use a labelled
Watchtower deployment (or a root-owned systemd timer that runs docker compose pull nvrd && docker compose up -d nvrd). Pin a release tag when restarts must
be scheduled deliberately. The full Compose example and security trade-offs
are in docs/linux-updates.md in the source distribution.
NAS and Proxmox#
Both are the Docker path above:
- NAS (Synology, TrueNAS, …) — run the container, bind-mount a recordings folder from your storage pool.
- Proxmox — an LXC or small VM with the container, or the plain Linux binary below. Give the recordings volume its own disk and pass it through.
Windows runs via Docker Desktop with the same image — there’s no native Windows build by design.
Linux, bare metal#
Download the static binary for your arch, put a config.yaml next to it, and run it under your service manager (systemd, OpenRC, …). No runtime dependencies — the binary is fully static; ffmpeg is only needed if you use the H.264 compatibility transcode.
./nvrd -config config.yaml
# UI: http://localhost:8085 Native Linux can opt into signed atomic updates under systemd with updates.linux_auto_update: true. It is off by default, keeps the prior binary
as a rollback target, and refuses unsigned or incorrectly signed artifacts.
See docs/linux-updates.md for the service layout and restart authorization.
macOS#
The signed .dmg from the download page installs NVR.app, which manages the daemon for you — it starts at login, keeps a menu-bar status item, and self-updates. Config lives in the app’s own location; edit it from Settings → Configuration in the web UI.
Updates#
Every build checks a signed manifest and shows an update notice in Settings. The macOS app updates through Sparkle; native Linux auto-install is explicit opt-in; Docker deployments update by pulling the image tag and recreating the container. Updates are free forever, licensed or not.