Architecture
ChannelWatch runs as one container with two managed Python processes. The monitoring core follows each DVR; the FastAPI web process serves the app and its APIs. Supervisor starts and monitors both.
Follow an event
Section titled “Follow an event”- Channels DVR
The core reads events and API details for each enabled server.
- Alert handler
Enabled alert settings and per-DVR session state decide what to report.
- Notification route
Routing, delivery limits, and provider settings select the destinations.
- Local records
Activity and delivery results appear through FastAPI in the Dashboard, Watch History, and Notification Logs.
This is monitoring of Channels DVR. ChannelWatch does not record or serve the video itself.
Monitoring core
Section titled “Monitoring core”The core’s asyncio entry point creates concurrent work for enabled DVRs. Some monitoring work uses internal threads. A disconnect on one DVR does not require every other DVR to reconnect.
The core owns event subscriptions, metadata caches, disk checks, alert handlers, notification delivery, session state, and watchdog snapshots. Health endpoints are served by the separate web process using those persisted snapshots.
Web process
Section titled “Web process”The frontend is built with Next.js and exported as static files. FastAPI serves that export and the API on port 8501. The release container does not need a Node.js web server.
The web process handles:
- Dashboard, Watch History, and notification delivery history
- DVR discovery and connection settings
- alert settings, templates, providers, and routing
- local sign-in, sessions, and permission checks
- diagnostics, logs, health probes, and metrics
- backup, restore, debug bundles, and Update Center
Supervisor control stays inside the container through a local Unix socket. It is not a public administrative endpoint.
Local state
Section titled “Local state”One container owns one writable /config volume.
| State | Main location |
|---|---|
| DVRs, alerts, providers, routing, and security settings | /config/settings.json |
| Activity history, delivery records, users, and sessions | /config/channelwatch.db |
| Alert continuity for each DVR | /config/session_state_<dvr_id>.json |
| Monitoring freshness | /config/watchdog_status.json |
| Rotating logs | /config/channelwatch.log |
| Safety backups | /config/backups/ |
| In-app update generations and metadata | /config/channelwatch-runtime/ |
The app watches supported settings changes and reloads affected monitors. Some process-level changes still require a restart. See Hot Reload before assuming every setting changes immediately.
Backups include settings, the database, per-DVR session files, and key material when present. Downloaded update bundles are separate from a normal backup ZIP.
Delivery and extensions
Section titled “Delivery and extensions”Most named notification destinations use Apprise. Standard Discord webhooks and configured signed custom webhooks also have direct HTTP delivery paths. Routing controls the destinations for each DVR and alert type.
Provider plugins load from /config/plugins/notifications/ once at startup. They register delivery implementations; they do not replace routing or dynamically add alert sources or UI panels. Plugins run as trusted Python code inside the container. See Notification Provider Plugins for the actual interface and restart requirement.
Security and update boundaries
Section titled “Security and update boundaries”Fresh installs choose secure local sign-in or trusted-network no-auth before DVR setup. Upgraded installs can retain a legacy shared API key. That shared key has full access, including when it remains as a fallback beside user sessions.
The app encrypts per-DVR API keys and protected custom webhook URL/secret fields using /config/encryption.key. Other settings can still contain sensitive values. Protect the whole config volume and its backups.
The container first starts an image-owned launcher. It can select a verified compatible application bundle from /config, and newer compatible launchers can select a signed Python package generation. Python itself, system libraries, and image-owned tools remain part of the container image. Updating ChannelWatch explains the supported paths without conflating the app version and image version.
Scaling limit
Section titled “Scaling limit”ChannelWatch supports multiple DVRs inside one instance. It does not support multiple replicas writing the same config volume. Keep the Helm chart at one replica; distributed ownership and high availability remain future work.
Related pages
Section titled “Related pages”- Dashboard and Watch History — using the visible app
- Health probes and Per-DVR Health — process health versus DVR monitoring
- Privacy — local records and outbound requests
- Users and permissions — authentication boundaries