tutorial

Monitoring Pinry with Vigilmon

Pinry is a self-hosted Pinterest alternative built on Python/Django with Celery image processing. Here's how to monitor its web server, database, Celery workers, Redis queue, image storage, and SSL certificates with Vigilmon.

Pinry is a private, self-hosted image bookmarking and pinboard application — a Python/Django backend with a React frontend that lets you pin images from the web or upload your own, organise them into boards, and search them later. Unlike Pinterest, every image you pin stays on your server. Vigilmon keeps watch over your Pinry stack: Django web server, PostgreSQL database, Celery image-processing workers, Redis queue broker, image storage, and TLS certificates — so you know the moment something goes wrong.

What You'll Set Up

  • HTTP uptime monitor for the Pinry web interface (port 80/443)
  • PostgreSQL database connectivity check via a dedicated health endpoint
  • Django application server health check
  • Celery worker heartbeat (image processing: thumbnail generation, metadata extraction)
  • Redis queue broker TCP connectivity check
  • Image storage backend accessibility check
  • Image proxy and thumbnail service response-time monitor
  • User authentication service check
  • Cron heartbeat for scheduled image re-processing jobs
  • SSL/TLS certificate expiry alert

Prerequisites

  • Pinry running and accessible over HTTP or HTTPS
  • PostgreSQL, Redis, and Celery all deployed as part of your Pinry stack
  • A free Vigilmon account

Step 1: Monitor the Pinry Web Interface

The first check confirms that Django and your reverse proxy are both serving requests.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter your Pinry URL: https://pinry.yourdomain.com.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

If you run Pinry behind nginx or Caddy, this single check covers both the proxy layer and the gunicorn/uwsgi Django application server.


Step 2: Add a Django Health Check Endpoint

Pinry's default deployment doesn't expose a /health route, but you can add one in minutes using the django-health-check package or a minimal custom view:

# pinry/health_views.py
from django.http import JsonResponse
from django.db import connection

def health(request):
    try:
        connection.ensure_connection()
        db_ok = True
    except Exception:
        db_ok = False
    status = 200 if db_ok else 503
    return JsonResponse({"db": db_ok}, status=status)
# urls.py
from django.urls import path
from . import health_views

urlpatterns = [
    path("health/", health_views.health),
    # ... existing urls
]

Now add a Vigilmon monitor for https://pinry.yourdomain.com/health/ with expected status 200. A 503 means Django is up but the database is unreachable — a different failure mode than a 502 proxy error.


Step 3: Monitor PostgreSQL Connectivity

The health endpoint from Step 2 already covers the database from Django's perspective. For a lower-level check, add a TCP monitor directly to the PostgreSQL port:

  1. Click Add MonitorTCP Port.
  2. Enter your database server hostname and port (default 5432).
  3. Set Check interval to 1 minute.
  4. Click Save.

A TCP failure on port 5432 that the health endpoint doesn't catch means the issue is network-level (firewall rule change, container restart) rather than application-level.


Step 4: Monitor Celery Worker Health

Pinry uses Celery to process images asynchronously — generating thumbnails, extracting metadata, and re-fetching updated images. If Celery workers die, new pins queue up silently and users see broken or missing thumbnails.

The cleanest way to monitor Celery workers is a dedicated heartbeat task. Add this to your Celery beat schedule:

# celery_config.py or settings.py
from celery.schedules import crontab

CELERYBEAT_SCHEDULE = {
    "vigilmon-heartbeat": {
        "task": "pinry.tasks.send_vigilmon_heartbeat",
        "schedule": crontab(minute="*/5"),  # every 5 minutes
    },
}
# pinry/tasks.py
import requests
from celery import shared_task

@shared_task
def send_vigilmon_heartbeat():
    requests.get("https://vigilmon.online/heartbeat/YOUR_CELERY_ID", timeout=5)

In Vigilmon:

  1. Click Add MonitorCron Heartbeat.
  2. Set Expected interval to 5 minutes.
  3. Copy the heartbeat URL and paste it into YOUR_CELERY_ID above.

If all Celery workers crash, the task never runs, the ping never arrives, and Vigilmon alerts after 5 minutes.


Step 5: Check Redis Queue Broker Connectivity

Celery uses Redis as its message broker. If Redis goes down, Celery workers stop receiving tasks even if they are still running.

  1. Click Add MonitorTCP Port.
  2. Enter your Redis server hostname and port (default 6379).
  3. Set Check interval to 1 minute.
  4. Click Save.

A Redis TCP failure combined with healthy Celery heartbeats (from a previous successful ping interval) tells you that new tasks are not being queued, but workers haven't died yet.


Step 6: Verify Image Storage Backend Accessibility

Pinry stores pinned and uploaded images on local disk or S3-compatible object storage. Monitor the storage path by checking whether Pinry can serve a known image file:

  1. Pin a test image and copy its direct URL (e.g. https://pinry.yourdomain.com/media/pins/test-image.jpg).
  2. Add an HTTP monitor for that URL with expected status 200.
  3. Label it Image storage.

If your storage backend (NFS mount, S3 bucket, or local disk) becomes unavailable, this monitor fails while the web interface monitor (Step 1) may still pass — catching the failure faster than user reports.


Step 7: Monitor Thumbnail Service Response Times

Pinry generates thumbnails for every pinned image. Slow thumbnails degrade the browsing experience even when the app is technically up.

  1. Open the image storage monitor from Step 6 (or create a new one for a known thumbnail URL like https://pinry.yourdomain.com/media/thumbnails/test_thumbnail.jpg).
  2. Enable Response time alerting.
  3. Set the alert threshold to 2000 ms.

Thumbnails above 2 seconds indicate storage I/O pressure or Celery processing backlog.


Step 8: Check the Authentication Service

Pinry's login endpoint must be healthy for users to access their boards.

  1. Add an HTTP monitor for https://pinry.yourdomain.com/accounts/login/.
  2. Set Expected status to 200.
  3. Label it Auth service.

Django's authentication middleware is part of the request cycle, so a broken auth service often surfaces as a 500 on the login page rather than on the home page.


Step 9: Heartbeat for Scheduled Image Re-Processing

Pinry can re-fetch and re-process pinned images on a schedule (updating metadata, refreshing broken image sources). Add a heartbeat for this job:

# crontab example
0 2 * * * cd /opt/pinry && python manage.py reprocess_images && curl -s https://vigilmon.online/heartbeat/YOUR_REPROCESS_ID

In Vigilmon, create a Cron Heartbeat with the expected interval matching your schedule (e.g. 1440 minutes for daily).


Step 10: SSL/TLS Certificate Expiry Alert

  1. Open the web-interface monitor from Step 1.
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

Pinry is typically deployed with Let's Encrypt. Renewal failures are silent until the certificate actually expires — the 21-day window gives you three renewal cycles to investigate.


Step 11: 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 all HTTP monitors — Django cold starts and container restarts can cause single-probe failures.
  3. Keep Consecutive failures at 1 for the Celery heartbeat and the scheduled re-processing heartbeat — a missed worker ping is always worth investigating.

Summary

| Monitor | Target | What It Catches | |---|---|---| | Web interface | https://pinry.yourdomain.com | App crash, proxy failure | | Django health | GET /health/ | DB connectivity from app | | PostgreSQL TCP | host:5432 | Network-level DB failure | | Celery heartbeat | Vigilmon heartbeat URL | Worker crash, task queue dead | | Redis TCP | host:6379 | Message broker down | | Image storage | Known media URL | Storage backend failure | | Thumbnail response time | Known thumbnail URL | Slow image processing | | Auth service | /accounts/login/ | Login flow broken | | Re-processing heartbeat | Vigilmon heartbeat URL | Scheduled job not running | | SSL certificate | pinry.yourdomain.com | TLS cert expiry |

Pinry gives you a private, ad-free image collection — but that privacy comes with full ownership of the stack. With Vigilmon watching every layer from the Django web server to the Celery workers and Redis broker, you catch failures before your pins start showing broken images.

Monitor your app with Vigilmon

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

Start free →