BGPVR Operator guide
Operator guide

Installation

BGPVR runs as a Docker container. The application is stateless — everything that matters lives in the volumes you mount.

On this page
  1. Minimal compose file
  2. Volumes — the container paths are the contract
  3. Update BGPVR to the latest version
  4. Hardware
  5. NVIDIA persistence mode

Minimal compose file

services:
  bgpvr:
    image: ghcr.io/bgpvr/bgpvr:latest
    container_name: bgpvr
    restart: unless-stopped
    network_mode: host
    environment:
      - BGPVR_DATA=/data
      - WEB_PORT=8095
    volumes:
      - /srv/bgpvr/data:/data
      - /srv/bgpvr/recordings:/data/dvr
      - /srv/bgpvr/picons:/data/picons
    devices:
      - /dev/dvb:/dev/dvb          # DVB tuners
      # - /dev/bus/usb:/dev/bus/usb  # USB smartcard readers
      # - /dev/dri:/dev/dri          # Intel/AMD hardware transcoding

For NVIDIA hardware transcoding add runtime: nvidia and NVIDIA_DRIVER_CAPABILITIES=compute,utility,video.

Behind a reverse proxy: list it in BGPVR_TRUSTED_PROXIES

Login limits and the other per-address limits count each visitor by the address your reverse proxy passes in X-Forwarded-For. Tell BGPVR which proxy is yours in the compose environment: BGPVR_TRUSTED_PROXIES=127.0.0.1/32 for nginx on the same host, BGPVR_TRUSTED_PROXIES=<its IP>/32 for a proxy elsewhere on your network, or BGPVR_TRUSTED_PROXIES=none when there is no proxy. An admin can set the same list in the trusted_proxy_cidrs setting through the settings API; the environment variable wins. The start-up log line “Client address: …” shows what is in force, and BGPVR logs a hint naming a proxy that is not listed yet.

Volumes — the container paths are the contract

Host paths are yours to choose, but the container paths must match exactly, and every BGPVR service must see the same ones.

Container pathHolds
/dataDatabase, settings, HLS, logs — the one you cannot lose
/data/dvrRecordings (often NAS-backed)
/data/vodVOD library and promoted recordings
/data/piconsChannel logos
/data/ai_outputThumbnails, subtitles, AI reports
Never use Docker named volumes for /data

Use a bind mount to a real host directory. Named volumes make backup, inspection and migration far harder than they need to be.

Verify after deploying

Open Monitor → Technical → Storage in the console. Every required path must show as visible. If one says “Needs Mount”, fix the compose mapping before relying on DVR post-processing, thumbnails or VOD scans.

Upgrade only when nothing is recording

Before you pull a new image and recreate the container, check that no recording is running (DVR shows what is recording) and that no AI job is processing (Monitor → Technical → AI Queue, or the Processing count under Settings → AI Processing → Processing Queue). Queued jobs survive a restart. A recording cut by a restart resumes as a second file, with a gap. The first start on 2.9.275 or later moves the guide data into its own database (epg.db), so allow a few minutes of downtime for that one.

Update BGPVR to the latest version

An update means pulling the new images and recreating the containers. Everything BGPVR keeps (settings, subscribers, channels, recordings) lives in the folders you mounted, so it stays as it is. Do it at a quiet time.

  1. Make sure nothing is recording. Check DVR and the AI queue, as the warning above describes.
  2. Take a backup. In the console open Backup and press Backup now (how), then Download the new file to another computer (how). The backup holds the database and the two secrets. Recordings, VOD files and picons are not in it.
  3. Note your version. The suite version is the small line at the bottom of the sidebar, under Sign Out.
  4. Pull and restart. On the server, in the folder with your docker-compose.yml and .env files, run:
    docker compose pull
    docker compose up -d
    The first command downloads the latest images of every service in the file, the second recreates the containers that changed. If your file names a version tag instead of latest, change the tag first.
  5. Wait, then sign in. The server restarts, so live streams stop for a moment, and a recording that is running then resumes as a second file, with a gap. After an update the first start can take a little longer while BGPVR brings its database up to date.
  6. Confirm. The line at the bottom of the sidebar shows the new version, and License shows your plan as before.

Remote nodes update from the console: a node whose agent is older than the one on this server shows Update agent on the Nodes page (how). Tuner settings and recordings on a node are never touched.

If something fails

  • The console opens but shows wrong data or settings: restore the backup from step 2. Open Backup, press Restore on its row and type RESTORE (how). This rewinds the database, not your recordings.
  • The console does not open: on the server run docker compose ps and docker compose logs --tail 100 bgpvr, then contact BGPVR support and send what they print.

Hardware

  • Tuners: DVB-C/T/S adapters via /dev/dvb. Verified example: Hauppauge WinTV-dualHD (Si2168), 2 tuners.
  • Transcoding: NVIDIA NVENC, or Intel/AMD VAAPI/QSV via /dev/dri. Optional — CPU works.
  • Storage speed matters more than size. Slow disks under /data cause the writers to stall, which shows up as high load and iowait rather than an obvious disk error.

There is no formal minimum spec. As a reference point, a production install caps AI post-processing at 6 of 16 cores so it can never starve live streaming, and each live web viewer needs roughly 40 MB of RAM for its segments (see Settings → Tuners & Sources → Web Player Quality → Segment storage).

Images and the watchdog

The images ghcr.io/bgpvr/bgpvr, bgpvr-ai and bgpvr-node pull without a login. The operator terms are at bgpvr.com/terms. The bgpvr-watchdog container polls the app every minute and alerts through Settings → Notifications. After 3 missed checks and a 45-second confirmation it restarts the bgpvr container, at most once every 30 minutes, but only if /var/run/docker.sock is mounted into the watchdog; without that mount it only alerts. Opt out with the watchdog_self_heal setting.

NVIDIA persistence mode

Without it, the NVIDIA driver shuts a card down whenever no program is using it and starts it again for the next one: each Light recording stream (and the card check before it) then waits about a second longer. The console shows it per card under Monitor → Technical → Exposed Hardware (Persistence mode: On ✓ or Off) and, when a card is off, the command below. It is a setting of the host's NVIDIA driver: the BGPVR container only reads it.

Check, on the server itself (the host, not inside the container):

nvidia-smi --query-gpu=index,name,persistence_mode --format=csv

The quick way: the script BGPVR ships (Ubuntu, Debian, Proxmox and other hosts with systemd and the NVIDIA driver). It turns persistence mode on now and after every reboot, and prints each card before → after. Take it from the BGPVR image (not from the running container, whose files the app could change) and read it before you run it with sudo:

docker run --rm --entrypoint cat "$(docker inspect -f '{{.Image}}' bgpvr)" \
    /app/scripts/host/gpu_persistence.sh > gpu_persistence.sh
less gpu_persistence.sh             # read it first
sudo bash gpu_persistence.sh enable     # status: show it · disable: undo

The same by hand (Ubuntu / Debian with the NVIDIA driver):

  1. On now: sudo nvidia-smi -pm 1
  2. On after every reboot: create /etc/systemd/system/nvidia-persistenced.service.d/bgpvr-persistence.conf with
    [Service]
    ExecStart=
    ExecStart=/usr/bin/nvidia-persistenced --user nvidia-persistenced --persistence-mode --verbose
    The empty ExecStart= clears the distribution's own line (Ubuntu's says --no-persistence-mode). Leave out --user nvidia-persistenced when getent passwd nvidia-persistenced prints nothing.
  3. Load it: sudo systemctl daemon-reload && sudo systemctl enable nvidia-persistenced && sudo systemctl restart nvidia-persistenced
  4. Verify: the check above says Enabled for every card, also after a reboot; the console shows On ✓.
  5. Undo: sudo rm /etc/systemd/system/nvidia-persistenced.service.d/bgpvr-persistence.conf, then sudo systemctl daemon-reload && sudo systemctl restart nvidia-persistenced (the service's own default comes back; Ubuntu's is off)

Other systems

  • Unraid has no systemd: run nvidia-smi -pm 1 once and add that line to /boot/config/go, which runs at every boot.
  • TrueNAS SCALE resets its system files on updates: add nvidia-smi -pm 1 as a Post Init command under System → Advanced → Init/Shutdown Scripts.
  • Proxmox and virtual machines: do it where the NVIDIA driver runs: inside the VM when the card is passed through to it, on the Proxmox host when containers share the card.
  • Synology DSM: untested. Where nvidia-smi works over SSH, a boot-time task in Control Panel → Task Scheduler running nvidia-smi -pm 1 as root may do it; otherwise leave it off (the light version still works, about a second slower to start).
  • Docker Desktop and Windows (WSL): the Windows driver manages the card; nothing to do here.