Skip to content

Install (Docker Compose)

ChannelWatch ships as a multi-arch Docker image and is designed to run as a single container managed by Docker Compose. This is the primary supported install path today.

  • Docker Engine with Docker Compose v2 (the docker compose plugin, not the legacy docker-compose binary)
  • A running Channels DVR server reachable from the Docker host
  • A local directory to store ChannelWatch configuration and logs (e.g. /opt/channelwatch/config)

The coderluii/channelwatch:latest image is a multi-platform manifest that automatically selects the right variant for your hardware:

Architecture Typical hardware
linux/amd64 Standard x86-64 servers, NAS devices, PCs
linux/arm64 Raspberry Pi 4/5, Apple Silicon Docker hosts, modern ARM servers

No flags or extra steps are needed. docker compose pull picks the correct image automatically.

Create a docker-compose.yml in a directory of your choice:

name: channelwatch
services:
channelwatch:
image: coderluii/channelwatch:latest
container_name: channelwatch
init: true
network_mode: host
volumes:
- /your/local/path:/config
environment:
TZ: "America/New_York"
restart: unless-stopped

Replace /your/local/path with the absolute path to your config directory. The TZ value should match your local timezone (IANA format, e.g. America/Chicago, Europe/London).

Terminal window
docker compose up -d

Then open http://your-server-ip:8501 in a browser. On a fresh install, ChannelWatch opens its first-run setup flow so you can add your Channels DVR server in the web UI.

ChannelWatch initial authentication setup card with Secure login selected, an alternative No authentication button, empty Admin username and Admin password fields, and disabled Finish setup
First screen after installationA fresh installation asks how to protect access before the DVR connection wizard opens. Continue with First-Run Configuration after choosing a mode. Captured from ChannelWatch v1.6.0 with safe demo data.View full-size screenshot

The container exposes port 8501 and the published image defines a built-in liveness check against http://127.0.0.1:8501/healthz/live.

Terminal window
docker logs -f channelwatch

The default compose file uses network_mode: host, which lets ChannelWatch reach your Channels DVR server using localhost or any LAN IP without extra configuration. This is the simplest option for most home lab setups.

This host-network example targets Linux Docker Engine. For Docker Desktop or a host where host networking is unavailable, use the bridge configuration below and enter the DVR’s reachable LAN address.

If you prefer bridge networking, for network isolation or port remapping, replace the network_mode line with explicit port mapping:

# Remove: network_mode: host
ports:
- "8501:8501"

ChannelWatch stores all persistent data under /config inside the container. The directory you mount there will contain:

Path Contents
/config/settings.json All configuration (DVR servers, alert toggles, notification providers)
/config/channelwatch.db SQLite activity history database
/config/encryption.key Managed key used to encrypt DVR API keys and custom webhook credentials
/config/logs/ Application logs
/config/backups/ Automatic pre-migration backups
/config/plugins/notifications/ Optional notification provider plugins

Most settings live in the web UI. A small set of environment variables are available for automation or headless deployments:

environment:
TZ: "America/New_York"
# User/group IDs (match your host user to avoid permission issues)
# PUID: "1000"
# PGID: "1000"
# Log verbosity: 0=minimal, 1=standard (default), 2=verbose
# CW_LOG_LEVEL: "1"
# Notification providers (can also be set in the web UI)
# CW_APPRISE_DISCORD: "<webhook-id>/<webhook-token>"
# CW_APPRISE_PUSHOVER: "<pushover-user-key>@<pushover-api-token>"
# CW_APPRISE_TELEGRAM: "<bot-token>/<chat-id>"
# CW_APPRISE_SLACK: "<token-a>/<token-b>/<token-c>"
# CW_APPRISE_GOTIFY: "<gotify-host>/<gotify-app-token>"
# CW_APPRISE_EMAIL: "<smtp-user>:<smtp-password>@smtp.example.com"
# CW_APPRISE_EMAIL_TO: "recipient@example.com"
# CW_APPRISE_MATRIX: "<matrix-user>:<matrix-password>@matrix.example.com/#room"
# CW_APPRISE_CUSTOM: "apprise://<service-specific-url>"
# First-start alert overrides (fresh defaults use Important Only)
# CW_ALERT_CHANNEL_WATCHING: "true"
# CW_ALERT_VOD_WATCHING: "true"
# CW_ALERT_DISK_SPACE: "true"
# CW_ALERT_RECORDING_EVENTS: "true"
# Disk space thresholds
# CW_DS_THRESHOLD_PERCENT: "10"
# CW_DS_THRESHOLD_GB: "50"
# CW_DS_ALERT_COOLDOWN: "3600"

PUID and PGID are most useful on NAS and appliance-style hosts such as Synology, Unraid, and TrueNAS SCALE, where the Docker daemon often writes mounted files as a non-login service user by default. Set both values to the UID and GID that should own the /config directory on the host if you see permission errors or root-owned files after first start.

Provider, alert, threshold, and log-level variables seed a fresh settings file. After setup, manage those values in the UI; changing them in Compose does not replace existing saved settings. TZ remains a startup override. For DVR variables and their separate runtime behavior, read Environment Bootstrap Config.

If your Channels DVR server is reachable by a short hostname, for example media-server instead of a full IP, you can configure DNS search domains:

dns_search: localdomain
# Tailscale users: add your Tailnet domain
# dns_search:
# - localdomain
# - tail12345.ts.net

For public names, you can configure reachable DNS servers explicitly:

dns:
- 1.1.1.1
- 8.8.8.8

Public resolvers cannot answer private LAN or Tailnet names. Use your local resolver when the DVR has a private hostname, and confirm the container can reach it.

ChannelWatch v1.6.5 installs from Settings > Updates on v1.4.0, v1.4.1, v1.4.5, v1.5.3, v1.6.0, v1.6.1, v1.6.2, v1.6.3, and v1.6.4 without recreating the container. The v1.4.x and protocol 3 v1.6.0/v1.6.1/v1.6.2/v1.6.3/v1.6.4 paths keep the existing image’s Python packages and system libraries; v1.5.3 and protocol 4 v1.6.0/v1.6.1/v1.6.2/v1.6.3/v1.6.4 install the complete signed runtime generation. To refresh the container image separately, keep the same /config mount and run:

Terminal window
docker compose pull
docker compose up -d

ChannelWatch migrates /config/settings.json automatically on startup. A timestamped backup is written to /config/backups/ before any migration step runs. Keep /config/encryption.key with the rest of /config; losing it prevents ChannelWatch from decrypting protected credentials. See Migrating from v0.7 for version-pinning, rollback, and downgrade caveats.

To prevent supervisor credentials from ever touching disk, mount /run/channelwatch as a tmpfs:

tmpfs:
- /run/channelwatch:mode=0750,uid=0,gid=1000