tutorial

Monitoring ZoneMinder with Vigilmon

ZoneMinder is the most established open-source CCTV platform — but its PHP daemons can fail silently. Here's how to monitor ZoneMinder's web UI, REST API, daemon health, and scheduled event capture with Vigilmon.

ZoneMinder is the oldest and most established open-source CCTV and NVR platform — over 20 years of active development, GPL-licensed, self-hosted on Linux and Ubuntu. It handles RTSP/RTMP cameras, zone-based motion detection, event archival, PTZ control, and advanced filtering, making it the go-to open-source alternative to commercial DVR systems for businesses, schools, and homeowners who need a mature, feature-complete solution. But ZoneMinder's PHP/Perl architecture means its daemons (zmdc.pl, zmc, zma) can silently exit while the web UI remains accessible on a cached page, and scheduled event archiving jobs can stall without obvious error messages. Vigilmon gives you continuous external verification that ZoneMinder's web UI, REST API, and event capture pipeline are all functioning.

What You'll Set Up

  • HTTP uptime monitor for the ZoneMinder web UI login page
  • REST API health check for the /zm/api/host/getVersion.json endpoint
  • TCP port monitor for ZoneMinder's web server availability
  • SSL certificate alerts for HTTPS ZoneMinder deployments
  • Cron heartbeat to confirm events are actively being captured

Prerequisites

  • ZoneMinder installed and running on Linux (Apache/Nginx serving the /zm/ path)
  • At least one monitor configured and in recording or motion-detect mode
  • A free Vigilmon account

Step 1: Monitor the ZoneMinder Web UI

ZoneMinder's web interface is typically served at /zm/ on port 80 or 443. The login page at /zm/ is the primary availability signal — if Apache or the PHP application layer fails, this returns a non-200 response or times out.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter the URL: http://your-zoneminder-host/zm/
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

For HTTPS deployments:

https://cctv.yourdomain.com/zm/

This catches Apache crashes, PHP-FPM failures, and host-level network issues within the first minute they occur.


Step 2: Check the ZoneMinder REST API

ZoneMinder exposes a REST API (introduced in ZoneMinder 1.29) that provides programmatic access to monitors, events, and system information. The /zm/api/host/getVersion.json endpoint is the lightest-weight probe — it returns a JSON object with the ZoneMinder version and confirms that the API layer is functioning.

http://your-zoneminder-host/zm/api/host/getVersion.json

A successful response looks like:

{"version":"1.36.33","apiversion":"2.0"}

Add a Vigilmon HTTP monitor for this endpoint:

  1. Click Add MonitorHTTP / HTTPS.
  2. Enter http://your-zoneminder-host/zm/api/host/getVersion.json.
  3. Set Check interval to 2 minutes.
  4. Under Response body check, enter "version" to confirm the JSON response is valid.
  5. Set Expected HTTP status to 200.
  6. Click Save.

The API layer uses zmdc.pl daemon infrastructure. An API failure while the web UI is still returning 200 (serving a cached login page from Apache) is a common failure mode that this probe catches independently.


Step 3: TCP Port Monitor for Web Server Health

A TCP-level check on ZoneMinder's web server port confirms the service is accepting connections at the network layer, independent of HTTP application logic.

  1. Click Add MonitorTCP Port.
  2. Enter your ZoneMinder host address.
  3. Set Port to 80 (or 443 for HTTPS deployments).
  4. Set Check interval to 1 minute.
  5. Click Save.

TCP failures at this level indicate Apache is down, the port is blocked by a firewall rule change, or the host itself is unreachable — conditions that the HTTP probe catches as well, but the TCP check is faster and produces a clearer failure signal.


Step 4: SSL Certificate Alerts for HTTPS Deployments

Many ZoneMinder deployments are exposed over HTTPS using Let's Encrypt, either directly through Apache's mod_ssl or via an Nginx reverse proxy. Certificate renewal failures happen silently, and a browser HTTPS warning on a CCTV system often goes unnoticed until it causes issues with API clients or mobile viewers.

Enable SSL monitoring on the web UI monitor from Step 1:

  1. Open the ZoneMinder web UI monitor in Vigilmon.
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

Sample Apache VirtualHost for ZoneMinder HTTPS with Let's Encrypt:

<VirtualHost *:443>
    ServerName cctv.yourdomain.com
    DocumentRoot /usr/share/zoneminder/www

    SSLEngine on
    SSLCertificateFile    /etc/letsencrypt/live/cctv.yourdomain.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/cctv.yourdomain.com/privkey.pem

    Alias /zm /usr/share/zoneminder/www
    <Directory /usr/share/zoneminder/www>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

A 21-day alert window gives you enough time to diagnose renewal failures and manually renew before the certificate expires:

sudo certbot renew --force-renewal --apache

Step 5: Heartbeat Monitoring for Event Capture

ZoneMinder's core value is continuous event capture and archiving — motion-triggered recordings, scheduled archival jobs, and notification filters. A healthy web UI and API don't guarantee the event pipeline is working. The zm daemon stack (zmc for capture, zma for analysis, zms for streaming) can encounter process crashes or resource exhaustion while the web layer remains healthy.

Use ZoneMinder's events API to build a heartbeat that confirms events are actively being captured:

  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set the expected ping interval to 15 minutes.
  3. Copy the heartbeat URL (e.g. https://vigilmon.online/heartbeat/abc123).

Create a script on the ZoneMinder host that checks for recent events and pings Vigilmon only if events exist:

#!/bin/bash
# /usr/local/bin/check-zoneminder-events.sh

ZM_URL="http://localhost/zm"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/abc123"
# Check for events in the last 15 minutes
START_TIME=$(date -d '15 minutes ago' +%Y-%m-%dT%H:%M:%S)

RESPONSE=$(curl -sf "${ZM_URL}/api/events.json?startTime=${START_TIME}&limit=1")
EVENT_COUNT=$(echo "$RESPONSE" | jq -r '.pagination.count // 0')

if [ "$EVENT_COUNT" -gt "0" ]; then
  curl -sf "$HEARTBEAT_URL" > /dev/null
fi

Make it executable and schedule it:

chmod +x /usr/local/bin/check-zoneminder-events.sh

Add to crontab:

*/15 * * * * /usr/local/bin/check-zoneminder-events.sh

Note: On quieter sites where cameras rarely trigger events, adjust the script to instead check ZoneMinder daemon status via the API:

STATUS=$(curl -sf "http://localhost/zm/api/host/daemonCheck.json" \
  | jq -r '.result // 0')
if [ "$STATUS" = "1" ]; then
  curl -sf "$HEARTBEAT_URL" > /dev/null
fi

The /zm/api/host/daemonCheck.json endpoint returns {"result":1} when the ZoneMinder daemon is running and {"result":0} when it has exited.


Step 6: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and connect Slack, email, or a webhook.
  2. Set Consecutive failures before alert to 2 on the web UI and API monitors to absorb transient network blips during peak camera activity.
  3. For the heartbeat monitor, set the alert threshold to 1 missed ping — a single missed 15-minute heartbeat means at least 15 minutes of potentially uncaptured events.

Summary

| Monitor | Target | What It Catches | |---|---|---| | Web UI | http://host/zm/ | Apache crash, PHP failure | | REST API | /zm/api/host/getVersion.json | API layer fault, daemon issue | | TCP Port | Host port 80 or 443 | Web server down, firewall change | | SSL Certificate | https://cctv.yourdomain.com | Let's Encrypt renewal failure | | Cron Heartbeat | Vigilmon heartbeat URL | Event capture stalled, daemon crash |

ZoneMinder's 20+ years of development make it one of the most capable open-source CCTV platforms available — but self-hosting means the reliability monitoring is your responsibility. With Vigilmon watching the web UI, REST API, and event capture pipeline, you'll know the moment ZoneMinder's protection fails, not after an incident when you discover blank footage.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →