tutorial

Monitoring MotionEye with Vigilmon

MotionEye is the go-to web frontend for Raspberry Pi security cameras — but the Motion daemon can stall silently. Here's how to monitor MotionEye's web UI, camera API, Motion control port, and frame capture health with Vigilmon.

MotionEye is a popular open-source web frontend for the Motion motion-detection daemon, built on Python and Flask. It runs on Raspberry Pi, Linux, and Docker, providing a clean interface for managing multiple cameras, configuring motion detection zones, scheduling recordings, setting up email and webhook alerts, and browsing captured media. It's the most common solution for home security camera setups using Raspberry Pi hardware. But when the underlying Motion daemon stalls, a camera disconnects, or disk space runs out, MotionEye typically continues showing its web UI normally while silently failing to capture frames. Vigilmon gives you external verification that MotionEye's web UI, camera API, and Motion daemon are all healthy — and alerts you before an unmonitored failure means missing footage during an incident.

What You'll Set Up

  • HTTP uptime monitor for the MotionEye web UI (port 8765)
  • REST API health check for the MotionEye camera list endpoint
  • TCP port monitor for the Motion daemon control port (7999)
  • SSL certificate alerts for HTTPS-proxied MotionEye deployments
  • Cron heartbeat to confirm camera frames are actively being captured

Prerequisites

  • MotionEye installed and running (Raspberry Pi, Linux, or Docker) on port 8765
  • At least one camera configured and active in MotionEye
  • Motion daemon running with its control port enabled (default: 7999)
  • A free Vigilmon account

Step 1: Monitor the MotionEye Web UI

MotionEye's web interface listens on port 8765. The login page is the primary availability indicator — if the Python/Flask process exits or the Raspberry Pi runs out of memory, the page will time out or return a connection refused error.

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

On Raspberry Pi deployments, MotionEye can become unresponsive under high CPU load from motion detection processing. A 1-minute check interval catches these hangs within 60 seconds, giving you time to SSH in and restart the service before the issue compounds.


Step 2: Check the MotionEye Camera API

MotionEye exposes a REST API for querying camera configuration and status. The /api/camera/ endpoint returns a JSON list of configured cameras, confirming that the application layer is healthy and camera configurations are loaded.

http://your-motioneye-host:8765/api/camera/

A typical response includes each camera's ID, name, and enabled status:

[
  {"id": 1, "name": "Front Door", "enabled": true, ...},
  {"id": 2, "name": "Back Yard",  "enabled": true, ...}
]

Add a Vigilmon HTTP monitor for this endpoint:

  1. Click Add MonitorHTTP / HTTPS.
  2. Enter http://your-motioneye-host:8765/api/camera/.
  3. Set Check interval to 2 minutes.
  4. Under Response body check, enter "enabled" to confirm the JSON response contains camera data.
  5. Set Expected HTTP status to 200.
  6. Click Save.

Note: The MotionEye API may require a cookie-based session token for some endpoints. If /api/camera/ returns a redirect to the login page, use the MotionEye admin credentials in a cookie-authenticated request, or monitor a public static asset at http://host:8765/static/main.css as an alternative application-layer health signal.


Step 3: TCP Port Monitor for the Motion Control Port

MotionEye controls the underlying Motion daemon through its control port (default TCP 7999). This port accepts HTTP-style commands for starting, stopping, and querying camera processes. Monitoring it at the TCP layer confirms that Motion's control interface is alive and accepting connections.

  1. Click Add MonitorTCP Port.
  2. Enter your MotionEye host address.
  3. Set Port to 7999.
  4. Set Check interval to 1 minute.
  5. Click Save.

If you have configured Motion with a non-default control port (set in /etc/motioneye/motion.conf as webcontrol_port), use that port number instead.

A TCP failure on port 7999 indicates the Motion daemon has crashed or exited — this can happen on Raspberry Pi when the SD card is full, when a USB camera is disconnected, or when a motion detection workload exceeds available RAM.


Step 4: SSL Certificate Alerts for HTTPS Deployments

MotionEye doesn't handle TLS natively, so HTTPS deployments typically use Nginx as a reverse proxy with a Let's Encrypt certificate. Certificate expiry is a common silent failure on long-running Raspberry Pi setups where automatic renewal may break when the Pi loses internet connectivity or when a port 80 challenge is blocked.

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

  1. Open the MotionEye 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 Nginx configuration for a MotionEye reverse proxy:

server {
    listen 443 ssl;
    server_name cameras.yourdomain.com;

    ssl_certificate     /etc/letsencrypt/live/cameras.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cameras.yourdomain.com/privkey.pem;

    location / {
        proxy_pass         http://localhost:8765;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_read_timeout 60s;
    }
}

The proxy_read_timeout is important — MotionEye can be slow to respond under high CPU load on Raspberry Pi, and a default 60-second Nginx timeout prevents premature gateway errors from appearing as false downtime.

A 21-day alert window gives you enough time to diagnose renewal failures on the Pi and manually renew:

sudo certbot renew --force-renewal

Step 5: Heartbeat Monitoring for Frame Capture

A healthy web UI and Motion control port don't guarantee cameras are actually capturing frames. Motion detection can be disabled, a camera feed can silently disconnect, or the capture thread can stall while the process remains running. Use Vigilmon's cron heartbeat to periodically confirm that MotionEye is producing frame data.

MotionEye provides a picture frame API endpoint that returns the latest captured image from a camera. If frames are being captured, this endpoint returns a JPEG image; if capture has stalled, it may return a cached last-known-good frame or an error.

A more reliable approach is to check the filesystem timestamp of the most recent captured image:

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

Create a script on the MotionEye host that checks for recent image files:

#!/bin/bash
# /usr/local/bin/check-motioneye-capture.sh

MEDIA_DIR="/var/lib/motioneye"  # Adjust to your MotionEye media path
HEARTBEAT_URL="https://vigilmon.online/heartbeat/abc123"
MAX_AGE_SECONDS=300  # Alert if no image captured in 5 minutes

# Find the most recent captured image across all cameras
LATEST=$(find "$MEDIA_DIR" -name "*.jpg" -newer /tmp/.motioneye-last-check 2>/dev/null | head -1)

if [ -n "$LATEST" ]; then
  curl -sf "$HEARTBEAT_URL" > /dev/null
  touch /tmp/.motioneye-last-check
fi

Make it executable and schedule it:

chmod +x /usr/local/bin/check-motioneye-capture.sh
touch /tmp/.motioneye-last-check  # Initialize the reference timestamp

Add to crontab:

*/5 * * * * /usr/local/bin/check-motioneye-capture.sh

For setups where cameras only capture on motion (not continuously), adjust the expected heartbeat interval to a longer window that matches typical motion frequency in your environment, or switch to monitoring the Motion control port API instead of filesystem activity:

# Alternative: query Motion's built-in status page
STATUS=$(curl -sf "http://localhost:7999/0/detection/status" | grep -c "active")
if [ "$STATUS" -gt "0" ]; then
  curl -sf "$HEARTBEAT_URL" > /dev/null
fi

Step 6: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and connect email or a webhook — on Raspberry Pi setups, a Slack notification is often more visible than an email when something goes wrong at 3am.
  2. Set Consecutive failures before alert to 2 on the web UI and API monitors to avoid false alerts during Pi reboots or brief network drops.
  3. For the heartbeat monitor, keep the alert threshold at 1 missed ping — a single missed 5-minute heartbeat means your cameras may not be recording.

Summary

| Monitor | Target | What It Catches | |---|---|---| | Web UI | http://host:8765 | Python/Flask crash, Pi out of memory | | Camera API | http://host:8765/api/camera/ | App layer fault, config failure | | TCP Port (Motion) | Host port 7999 | Motion daemon crash, SD card full | | SSL Certificate | https://cameras.yourdomain.com | Let's Encrypt renewal failure | | Cron Heartbeat | Vigilmon heartbeat URL | Stalled capture, camera disconnect |

MotionEye running on a Raspberry Pi is a remarkably capable home security camera system for its cost — but Raspberry Pi hardware introduces failure modes that server-grade hardware doesn't have: SD card corruption, thermal throttling, USB camera disconnects, and memory pressure from simultaneous capture threads. With Vigilmon watching MotionEye's health from the outside, you'll know within minutes when your Pi stops recording, not after an incident when the footage isn't there.

Monitor your app with Vigilmon

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

Start free →