LibrePhotos is an open-source, self-hosted alternative to Google Photos: a Python/Django API backend paired with a React frontend, backed by Postgres for storage and Redis for background ML task queuing. It provides automatic face recognition, object detection, location mapping, and timeline views — entirely on your own hardware, without sending photos to any cloud service. Because LibrePhotos is a multi-service application, failures are rarely obvious: the React UI may load fine while the Django API is down, or the API may respond while the Huey ML workers have stalled and face clustering has silently stopped. Vigilmon monitors each layer: the nginx/React frontend, the Django backend, the Redis cache, SSL certificate validity, and a heartbeat that confirms ML jobs are processing rather than accumulating.
What You'll Set Up
- HTTP monitor for the LibrePhotos React web UI (port 3000)
- HTTP monitor for the Django API backend health endpoint
- TCP monitor for Redis cache availability (port 6379)
- SSL certificate expiry alerts for HTTPS LibrePhotos deployments
- Heartbeat monitor that confirms Huey ML workers are processing background jobs
Prerequisites
- LibrePhotos deployed and accessible (Docker Compose is typical; frontend on port 3000, Django API on port 8001)
- A LibrePhotos user account for authenticated API checks
- A free Vigilmon account
Step 1: Monitor the LibrePhotos Web UI
The LibrePhotos React frontend is served by nginx on port 3000. A GET / returns the React SPA HTML shell — a 200 response confirms nginx is running and the frontend is being served. This is the entry point every user hits first.
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your LibrePhotos URL:
http://your-server:3000(orhttps://photos.yourdomain.comif reverse-proxied). - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Under Response body check, enter
LibrePhotosorreact-rootto confirm the SPA shell loaded rather than an nginx error page. - Click Save.
If your LibrePhotos instance redirects unauthenticated visitors to a login page, enable Follow redirects and check for Login in the response body to confirm the application is rendering correctly.
Step 2: Monitor the Django API Backend
The LibrePhotos Django backend runs on port 8001 and handles all data queries, photo indexing, and ML task dispatch. The /api/health/ endpoint (available in recent versions) returns a JSON health status — or /api/user/ with a valid session token returns user profile data confirming both the Django ORM and Postgres database are healthy.
- Click Add Monitor in Vigilmon.
- Set Type to
HTTP / HTTPS. - Enter the API URL:
http://your-server:8001/api/health/- If your version does not expose
/api/health/, usehttp://your-server:3000/api/health/(nginx proxies/api/to the Django backend on port 8001).
- If your version does not expose
- Set Expected HTTP status to
200. - Under Response body check, enter
"status"to confirm a JSON health response. - Set Check interval to
2 minutes. - Click Save.
A healthy response looks like:
{"status": "ok"}
If Django cannot connect to Postgres, it will return a 500 error or a non-JSON response — the status code check will catch either failure.
Step 3: Monitor Redis with a TCP Probe
LibrePhotos uses Redis as the task queue for Huey background workers. When Redis is unavailable, all ML tasks — face clustering, object detection, thumbnail generation, and photo geolocation — stop queuing immediately. The workers themselves also lose their queue connection and halt. A TCP probe to Redis confirms it is accepting connections before any Huey worker attempts to connect.
- Click Add Monitor in Vigilmon.
- Set Type to
TCP. - Enter your server address:
your-server - Set Port to
6379. - Set Check interval to
2 minutes. - Click Save.
If Redis is only accessible inside the Docker network (the default LibrePhotos Docker Compose configuration), expose the Redis port in docker-compose.yml for monitoring:
services:
redis:
image: redis:7-alpine
ports:
- "127.0.0.1:6379:6379" # bind to localhost only for security
This exposes Redis for a localhost TCP probe without making it publicly accessible. Adjust your-server to localhost or 127.0.0.1 accordingly.
Step 4: SSL Certificate Alerts for HTTPS Deployments
LibrePhotos is commonly reverse-proxied behind nginx or Caddy, which handles TLS termination for the React frontend. An expired certificate blocks every user login and API client.
- Open the HTTPS monitor for your LibrePhotos domain (created in Step 1).
- Enable Monitor SSL certificate under the SSL settings.
- Set Alert when certificate expires in less than
21 days. - Click Save.
Verify that your reverse proxy's certificate renewal is working:
# Check current certificate expiry
openssl s_client -connect photos.yourdomain.com:443 -servername photos.yourdomain.com \
</dev/null 2>/dev/null | openssl x509 -noout -enddate
# For Caddy (automatic HTTPS, check Caddy log)
journalctl -u caddy --since "1 hour ago" | grep -i tls
# For nginx + certbot
certbot renew --dry-run
Step 5: Heartbeat Monitoring for ML Worker Health
Redis being reachable does not confirm that Huey workers are actually processing jobs. The LibrePhotos jobs API at /api/jobs/ (authenticated) returns the current background job queue status — including pending, running, and completed jobs. A growing pending count with no completions indicates workers have stopped.
Create the heartbeat monitor first:
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set Expected ping interval to
60 minutes. - Copy the heartbeat URL (e.g.
https://vigilmon.online/heartbeat/abc123).
Then create a script to authenticate and check the job queue on the LibrePhotos host:
#!/bin/bash
# /etc/cron.hourly/librephotos-heartbeat
LIBREPHOTOS_URL="http://localhost:3000"
USERNAME="your-username"
PASSWORD="your-password"
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/abc123"
# Authenticate and get a token
TOKEN=$(curl -s -X POST "${LIBREPHOTOS_URL}/api/auth/token/obtain/" \
-H "Content-Type: application/json" \
-d "{\"username\":\"${USERNAME}\",\"password\":\"${PASSWORD}\"}" \
| grep -o '"access":"[^"]*"' | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then
echo "LibrePhotos auth failed" >&2
exit 1
fi
# Check the job queue — confirm jobs are completing
JOBS=$(curl -s -H "Authorization: Bearer ${TOKEN}" \
"${LIBREPHOTOS_URL}/api/jobs/")
# Ping heartbeat if API responded with job data
if echo "$JOBS" | grep -q '"results"'; then
curl -s "${VIGILMON_HEARTBEAT}" > /dev/null
fi
Make the script executable:
chmod +x /etc/cron.hourly/librephotos-heartbeat
If the Huey workers have crashed and the job queue is accumulating without progress, the API will still respond — but you can extend the script to check that pending jobs are not growing unboundedly by comparing job counts across heartbeat runs.
Step 6: Configure Alert Channels
- Go to Alert Channels in Vigilmon and add Slack, email, or a webhook.
- For the frontend and API monitors, set Consecutive failures before alert to
2— Django container restarts can cause brief unavailability. - For the Redis TCP probe, set Consecutive failures before alert to
1— Redis loss immediately halts all ML processing and warrants instant alerting. - For the heartbeat, set Grace period to
0.
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| React web UI | http://your-server:3000/ | nginx down, frontend not serving |
| Django API | /api/health/ | Django down, Postgres unreachable |
| Redis TCP | your-server:6379 | Redis down, ML task queue broken |
| SSL certificate | LibrePhotos domain | Reverse proxy certificate expiry |
| Cron heartbeat | Heartbeat URL | Huey workers stalled, ML processing halted |
LibrePhotos processes face recognition and object detection in the background long after photos are uploaded — a stalled worker means your photo library stops getting organized while everything looks fine from the outside. With Vigilmon watching the nginx frontend, the Django backend, Redis, and a heartbeat that proves jobs are flowing through the queue, you'll catch worker failures before your photo timeline falls months behind.