Your Plume instance had been publishing federated blog posts to readers across Mastodon and other ActivityPub platforms for months. Everything seemed fine — the web interface loaded, authors could write, and readers could comment. What nobody caught was that the background job processor had quietly died after a PostgreSQL connection pool timeout two weeks ago. Every article published since then had failed to deliver to federated followers. Hundreds of notifications that never arrived. Authors wondering why their Mastodon followers weren't seeing new posts.
Plume is an open source federated blogging platform built with Rust and the Rocket framework. It publishes long-form articles over ActivityPub, allowing Plume blogs to be followed directly from Mastodon, Misskey, and other Fediverse platforms. Keeping Plume healthy means ensuring the Rocket web server, PostgreSQL database, background job processor, ActivityPub federation endpoints, RSS feeds, and email delivery are all working. Vigilmon gives you external uptime monitoring and alerting to catch failures before your readers notice.
What You'll Set Up
- HTTP uptime monitor for the Plume web interface
- PostgreSQL database connectivity check
- Heartbeat monitor for background job processing service
- ActivityPub federation endpoint checks (blog post delivery)
- WebFinger discovery endpoint health monitor
- RSS feed generation service check
- Media upload and storage backend health monitor
- Email notification delivery heartbeat
- Scheduled federation crawl job heartbeat
- SMTP integration health check
- SSL certificate expiry alerts
Prerequisites
- A running Plume instance on port 7878 behind Nginx or Caddy
- PostgreSQL running and accessible
- A free Vigilmon account
Step 1: Monitor the Plume Web Interface
The Plume homepage confirms that the Rocket web server is handling requests and PostgreSQL is serving blog listing data.
Test it:
curl -I https://plume.yourdomain.com/
You should see 200 OK with Content-Type: text/html.
Set up the Vigilmon monitor:
- Log in to Vigilmon and click New Monitor → HTTP.
- Set URL to
https://plume.yourdomain.com/. - Set Check interval to
60 seconds. - Set Expected status code to
200. - Under Advanced → Keyword check, add keyword present:
Plume. - Save the monitor.
Step 2: Monitor PostgreSQL Database Connectivity
Plume stores all blog posts, authors, comments, user accounts, ActivityPub actor records, and federation state in PostgreSQL via Diesel ORM. A database connectivity failure causes the entire application to return errors — Rocket's connection pool will exhaust and requests will time out.
Plume exposes an instance metadata endpoint that queries the database:
curl https://plume.yourdomain.com/api/v1/instance
A successful response indicates both the Rocket server and PostgreSQL are healthy. In Vigilmon:
- Click New Monitor → HTTP.
- Set URL to
https://plume.yourdomain.com/api/v1/instance. - Set Expected status code to
200. - Under Keyword check, add keyword present:
name. - Save.
For a more targeted database check, you can add a minimal health endpoint to Plume's Rocket routes:
// src/routes/health.rs
#[get("/health/db")]
pub fn db_health(conn: DbConn) -> Result<Json<Value>, Status> {
conn.execute("SELECT 1")
.map(|_| Json(json!({"status": "ok"})))
.map_err(|_| Status::ServiceUnavailable)
}
When this monitor fails while the homepage passes, the problem is PostgreSQL connectivity or Diesel pool exhaustion.
Step 3: Heartbeat Monitor for Background Job Processing Service
Plume runs a background job processor (separate from the main Rocket web server) for outgoing ActivityPub delivery. When an author publishes a post, Plume queues delivery jobs to every federated follower's inbox. When the job processor stops — due to a crash, memory limit, or unhandled error — outgoing federation halts completely while the web interface keeps working.
Step 3a: Create a Vigilmon heartbeat monitor.
- Click New Monitor → Heartbeat in Vigilmon.
- Set Name to
Plume Background Job Processor. - Set Expected heartbeat interval to
5 minutes. - Save. Copy the Heartbeat URL shown (e.g.,
https://vigilmon.online/heartbeat/abc123).
Step 3b: Configure a system cron to verify the processor and ping Vigilmon.
Plume's job processor runs as a separate systemd service (plume-jobs). Check that it's running and ping Vigilmon:
# /etc/cron.d/plume-jobs-heartbeat
*/5 * * * * deploy systemctl is-active --quiet plume-jobs && \
curl -fsS https://vigilmon.online/heartbeat/YOUR_TOKEN
If plume-jobs has stopped, systemctl is-active returns non-zero, the curl is skipped, and Vigilmon alerts you after the expected interval passes without a ping. You'll know about the outage within 5 minutes rather than when a reader reports missing posts.
Step 4: Monitor ActivityPub Federation Endpoints
Plume's ActivityPub implementation exposes actor endpoints, inbox, and outbox for each blog. These endpoints are how remote Mastodon and Misskey users follow Plume blogs and receive new posts as ActivityPub activities.
Check the WebFinger discovery endpoint — Mastodon and other servers use this to resolve Plume blog handles to ActivityPub actors:
curl "https://plume.yourdomain.com/.well-known/webfinger?resource=acct:yourblog@plume.yourdomain.com"
In Vigilmon:
- Click New Monitor → HTTP.
- Set URL to
https://plume.yourdomain.com/.well-known/webfinger?resource=acct:admin@plume.yourdomain.com. - Set Expected status code to
200. - Under Keyword check, add keyword present:
subject. - Save.
Check the NodeInfo endpoint for federation capability advertisement:
- Click New Monitor → HTTP.
- Set URL to
https://plume.yourdomain.com/.well-known/nodeinfo. - Set Expected status code to
200. - Under Keyword check, add keyword present:
links. - Save.
Step 5: Monitor WebFinger Discovery Endpoint Health
WebFinger is the foundation of ActivityPub federation discovery. Remote servers call the WebFinger endpoint before every inter-server interaction — if it's slow or returning errors, new follows and federation handshakes will fail across all remote servers.
Monitor the WebFinger endpoint specifically for response time in addition to status code:
- Open the WebFinger monitor from Step 4.
- Under Advanced → Response time alert, set a threshold of
2000 ms. - Save.
A WebFinger endpoint responding in over 2 seconds typically indicates PostgreSQL query slowness on the actor lookup — a sign that database indexes may need attention or the connection pool is under pressure.
Step 6: Monitor RSS Feed Generation Service
Plume generates RSS and Atom feeds for each blog, allowing readers to subscribe through feed readers without using ActivityPub. RSS generation depends on PostgreSQL returning post data and the Rocket server being able to render the feed template.
Test a blog's RSS feed:
curl https://plume.yourdomain.com/@yourblog/feed.atom
In Vigilmon:
- Click New Monitor → HTTP.
- Set URL to
https://plume.yourdomain.com/@admin/feed.atom(replaceadminwith an existing blog slug). - Set Expected status code to
200. - Under Keyword check, add keyword present:
<feed. - Save.
Step 7: Monitor Media Upload and Storage Backend Health
Plume stores uploaded images and attachments either locally in a configured upload directory or via a configured S3-compatible backend. Storage failures cause image uploads to fail and existing post images to return 404 errors.
Test a static asset or a known uploaded file:
curl -I https://plume.yourdomain.com/static/images/plume.svg
For S3-backed storage, verify the storage bucket endpoint is reachable:
curl -I https://your-bucket.s3.yourdomain.com/
In Vigilmon:
- Click New Monitor → HTTP.
- Set URL to
https://plume.yourdomain.com/static/images/plume.svg. - Set Expected status code to
200. - Save.
If you're using local storage, also monitor available disk space through a sidecar health endpoint — a full disk causes upload failures without any web-visible error:
# /etc/cron.d/plume-disk-check
*/30 * * * * deploy df /var/plume/uploads | awk 'NR==2{exit ($5+0 > 90)}' && \
curl -fsS https://vigilmon.online/heartbeat/YOUR_DISK_TOKEN
Step 8: Monitor Email Notification Delivery
Plume sends email notifications for new comments, mentions, and account events. SMTP failures are silent from the user's perspective — they stop receiving email notifications without any error showing in the UI.
Create a cron job that verifies SMTP connectivity and pings a Vigilmon heartbeat:
# /etc/cron.d/plume-email-heartbeat
0 */6 * * * deploy curl -fsS --max-time 10 \
--url "smtp://localhost:25" --upload-file /dev/null \
&& curl -fsS https://vigilmon.online/heartbeat/YOUR_EMAIL_TOKEN
Or use a Python SMTP check script:
#!/usr/bin/env python3
import smtplib, sys, requests
try:
with smtplib.SMTP('localhost', 25) as s:
s.noop()
requests.get('https://vigilmon.online/heartbeat/YOUR_EMAIL_TOKEN', timeout=10)
except Exception:
sys.exit(1)
Create the heartbeat monitor first:
- Click New Monitor → Heartbeat in Vigilmon.
- Set Name to
Plume Email (SMTP) Delivery. - Set Expected heartbeat interval to
6 hours. - Save. Use the provided URL in the script above.
Step 9: Heartbeat Monitor for Scheduled Federation Crawl Jobs
Plume periodically crawls remote instances to update follower counts, refresh remote actor information, and clean up stale federation data. These cleanup jobs run on a schedule and keep your instance's view of the Fediverse current.
Create a dedicated heartbeat for scheduled maintenance job execution:
- Click New Monitor → Heartbeat in Vigilmon.
- Set Name to
Plume Federation Crawl Scheduler. - Set Expected heartbeat interval to
1 hour. - Save. Copy the heartbeat URL.
Add a system cron entry that pings this heartbeat when the maintenance cycle runs successfully:
# /etc/cron.d/plume-federation-crawl
0 * * * * deploy /opt/plume/bin/plume-cli federation-refresh \
&& curl -fsS https://vigilmon.online/heartbeat/YOUR_CRAWL_TOKEN
If plume-cli federation-refresh exits non-zero (database error, connection refused), the heartbeat ping is skipped and Vigilmon alerts you.
Step 10: Monitor SMTP/Sendmail Integration Health
If Plume is configured to use a local sendmail binary or MTA (Postfix, Exim) rather than SMTP directly, monitor the mail queue for growth — a sign that emails are being accepted but not delivered:
# Check for excessive mail queue depth
mailq | tail -1
Create a cron job that alerts if the queue grows beyond a threshold:
# /etc/cron.d/plume-mailq-check
*/15 * * * * deploy QSIZE=$(mailq | grep -c '^[0-9A-F]' 2>/dev/null || echo 0); \
[ "$QSIZE" -lt 50 ] && curl -fsS https://vigilmon.online/heartbeat/YOUR_MAILQ_TOKEN
Create the heartbeat monitor:
- Click New Monitor → Heartbeat in Vigilmon.
- Set Name to
Plume Mail Queue Health. - Set Expected heartbeat interval to
30 minutes. - Save.
Step 11: SSL Certificate Expiry Alerts
Plume must serve over HTTPS for ActivityPub federation. Remote servers verify your TLS certificate before accepting any federation handshake.
- Open the web UI monitor from Step 1.
- Enable Monitor SSL certificate.
- Set Alert when certificate expires in less than
21 days. - Save.
Alerting Configuration
Set up notification channels so you're alerted immediately on failures:
- In Vigilmon, go to Alerts → Notification Channels.
- Add an Email channel with your admin address.
- Optionally add a Slack webhook for your ops channel.
- Assign all Plume monitors to these notification channels.
Recommended alert thresholds:
| Monitor | Alert after | |---|---| | Web UI | 2 consecutive failures (2 min) | | PostgreSQL health | 1 failure (immediate) | | Background job processor heartbeat | 1 missed heartbeat (5 min) | | WebFinger discovery | 2 consecutive failures | | NodeInfo | 3 consecutive failures | | RSS feed | 3 consecutive failures | | Media storage | 3 consecutive failures | | Email delivery heartbeat | 1 missed heartbeat (6 hr) | | Federation crawl heartbeat | 1 missed heartbeat (1 hr) | | SMTP mail queue heartbeat | 1 missed heartbeat (30 min) | | SSL certificate | 21 days before expiry |
PostgreSQL and the background job processor are highest priority — a database failure causes immediate errors across all pages, and a stopped job processor means every published article silently fails to federate. RSS, media, and email monitors can have more tolerance as they affect secondary features.
Conclusion
A healthy Plume instance is more than just an accessible homepage. Federation depends on the background job processor staying alive. Reader experience depends on RSS feeds generating correctly. Author visibility on the Fediverse depends on WebFinger discovery responding reliably. Without external monitoring, any of these components can fail silently for days while articles continue to publish locally but never reach federated followers.
With Vigilmon watching your Plume web interface, PostgreSQL connectivity, background job processor, ActivityPub federation endpoints, WebFinger discovery, RSS feeds, media storage, email delivery, and federation crawl health, you'll know about failures within minutes rather than days.
Start monitoring your Plume instance for free at vigilmon.online.