Selfoss is a self-hosted RSS, Atom, and JSON feed aggregator with a clean web interface and a REST API. It runs on PHP (with Apache or nginx + PHP-FPM) and stores feed data in SQLite, MySQL, or PostgreSQL. Self-hosting your RSS reader keeps your reading habits private and your subscriptions under your control — but it also means you're responsible for keeping the feed scheduler running, the database accessible, and the web interface available. Vigilmon covers every layer of your Selfoss stack, from the web server and PHP-FPM process to the cron-driven feed fetch scheduler.
What You'll Set Up
- HTTP uptime monitor for the Selfoss web interface
- PHP-FPM process health via a custom health endpoint
- Cron heartbeat for the feed fetch scheduler
- Database connectivity monitor (SQLite / MySQL / PostgreSQL)
- REST API endpoint response time monitor
- Feed parsing error rate alerting
- SSL certificate expiry alerts
Prerequisites
- Selfoss installed on a server with nginx or Apache + PHP-FPM
- A cron job configured for
php /path/to/selfoss/cliupdate.php - A free Vigilmon account
Step 1: Monitor the Selfoss Web Interface
Selfoss serves its single-page app and API from the same PHP application on port 80/443. Start with a basic HTTP monitor:
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter the URL:
https://rss.yourdomain.com/(or your Selfoss base URL). - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Click Save.
Selfoss's root page returns the main HTML shell. A 200 response confirms nginx is serving the application and PHP-FPM is handling the bootstrap PHP script.
Step 2: Monitor PHP-FPM Process Health
PHP-FPM runs as a separate process pool that nginx proxies to via a Unix socket or TCP port. PHP-FPM can crash, run out of worker processes, or become unresponsive while nginx continues serving its error pages with a 502 status — or, if you've misconfigured error handling, with a misleading 200.
Add a dedicated health endpoint in Selfoss's configuration:
Option A: Use the Selfoss API health endpoint
Selfoss exposes a REST API. Check the stats endpoint for a JSON response:
GET https://rss.yourdomain.com/api/stats
Add this as a Vigilmon monitor:
- Click Add Monitor → HTTP / HTTPS.
- URL:
https://rss.yourdomain.com/api/stats. - Expected status:
200. - Under Response body, add a contains check for
"total"to confirm valid JSON is returned. - Check interval:
2 minutes. - Click Save.
Option B: Add a standalone PHP health file
Create /var/www/selfoss/health.php:
<?php
header('Content-Type: application/json');
echo json_encode(['status' => 'ok', 'php' => PHP_VERSION]);
Monitor https://rss.yourdomain.com/health.php expecting 200 with body containing "status":"ok". This file bypasses Selfoss's routing and hits PHP-FPM directly.
Step 3: Monitor the Feed Fetch Scheduler
Selfoss fetches feeds via a CLI script run by cron: php /path/to/selfoss/cliupdate.php. This is the core function of the entire application — if the cron job stops running, your feeds go stale without any error showing in the UI.
Set up a Vigilmon cron heartbeat:
- Click Add Monitor → Cron Heartbeat.
- Set the expected interval to match your cron schedule (e.g.
30 minutesif you run updates every 30 minutes). - Copy the heartbeat URL.
- Add the heartbeat ping to your cron command:
# /etc/cron.d/selfoss
*/30 * * * * www-data php /var/www/selfoss/cliupdate.php && \
curl -s https://vigilmon.online/heartbeat/YOUR_HEARTBEAT_ID
The && ensures Vigilmon is only pinged on successful completion. If cliupdate.php exits with an error (database unreachable, PHP error, disk full), the heartbeat is skipped and Vigilmon alerts after one missed interval.
Step 4: Monitor Database Connectivity
Selfoss supports SQLite, MySQL, and PostgreSQL. Database downtime means every page load fails with a PHP error, and the feed scheduler can't write new items.
SQLite
If you use SQLite (the default), add a heartbeat that verifies the database file is readable and writable:
#!/bin/bash
# /opt/selfoss/db-health.sh
DB="/var/www/selfoss/data/selfoss.db"
sqlite3 "$DB" "SELECT COUNT(*) FROM items;" > /dev/null 2>&1 && \
curl -s https://vigilmon.online/heartbeat/DB_HEARTBEAT_ID
Schedule every 5 minutes via cron.
MySQL / MariaDB
For MySQL, add a TCP port monitor:
- Click Add Monitor → TCP Port.
- Host:
your-mysql-host. - Port:
3306. - Check interval:
1 minute. - Click Save.
PostgreSQL
For PostgreSQL:
- Click Add Monitor → TCP Port.
- Host:
your-postgres-host. - Port:
5432. - Check interval:
1 minute. - Click Save.
TCP checks confirm the database process is listening. Combine with the SQLite heartbeat pattern (adapted for mysql --execute or psql --command) for a write-level health check that catches permission and corruption issues.
Step 5: Monitor the REST API Endpoint Response Time
Selfoss's REST API powers both the web interface and any third-party clients (iOS/Android apps). Slow API responses degrade the reading experience even when the server is technically "up". Monitor response time with Vigilmon's threshold alerts:
- Open the
https://rss.yourdomain.com/api/statsmonitor. - Enable Response time alert.
- Set Alert when response time exceeds
3000 ms. - Click Save.
/api/stats performs a lightweight database COUNT query — if it's taking over 3 seconds, something is wrong with your database connection pool or PHP-FPM is under load. Catching this early prevents timeouts from cascading to all feed reads.
Step 6: Monitor Feed Parsing Error Rate
Selfoss logs feed parsing errors to its error log (configured in config.ini as logger_destination). High error rates indicate broken feed URLs, encoding issues, or network connectivity problems to external feed sources.
Create a heartbeat that checks recent error counts:
#!/bin/bash
# /opt/selfoss/error-rate-check.sh
LOG="/var/www/selfoss/data/logs/default.log"
# Count errors in the last 30 minutes
ERRORS=$(find "$LOG" -newer /tmp/selfoss_last_check 2>/dev/null | \
xargs grep -c "ERROR\|CRITICAL" 2>/dev/null || echo 0)
touch /tmp/selfoss_last_check
if [ "$ERRORS" -lt 20 ]; then
curl -s https://vigilmon.online/heartbeat/ERROR_RATE_HEARTBEAT_ID
fi
Create a Vigilmon heartbeat monitor with a 30 minute interval. If parsing errors spike (broken feed, DNS failure for a feed source), the heartbeat stops and Vigilmon alerts.
Step 7: Monitor SSL Certificate Expiry
Enable SSL monitoring on your HTTPS monitor:
- Open the
https://rss.yourdomain.com/monitor. - Enable Monitor SSL certificate.
- Set Alert when certificate expires in less than
21 days. - Click Save.
Selfoss is typically a personal-use tool accessed over HTTPS. A lapsed certificate means you can't log in to read your feeds — and browser security warnings can make it look like the site is compromised. A 21-day window gives you plenty of time to trigger a renewal:
# Certbot renewal
certbot renew --nginx
# Or if using Caddy (auto-renewal, verify it's working)
caddy reload --config /etc/caddy/Caddyfile
Step 8: Monitor OPML Import/Export Service
Selfoss's OPML import and export endpoints (/opml routes) are less frequently used but critical when migrating feeds or backing up your subscription list. A PHP misconfiguration that breaks file upload handling can silently break OPML import while leaving the rest of the application functional.
Add a lightweight check for the OPML export endpoint (GET, no authentication required for some configurations):
- Click Add Monitor → HTTP / HTTPS.
- URL:
https://rss.yourdomain.com/opml(requires authentication — if behind HTTP auth, skip to the heartbeat alternative below). - Expected status:
200or401(if authentication is required, a401confirms the endpoint is reachable). - Check interval:
10 minutes. - Click Save.
Step 9: Configure Alert Channels
- Go to Alert Channels in Vigilmon.
- Add email and/or a Slack/webhook channel for alerts.
- Set Consecutive failures before alert to
2on HTTP monitors — PHP-FPM restarts under OOM conditions can cause brief unavailability. - Set a quiet hours window if you don't want 3 AM feed-fetch failure alerts for non-critical feed parsing errors.
For a self-hosted notification setup, route Vigilmon webhook alerts to Gotify or Ntfy:
# Gotify webhook example
curl -X POST "https://gotify.yourdomain.com/message?token=YOUR_TOKEN" \
-F "title=Selfoss Alert" \
-F "message={{monitor_name}} is {{status}}"
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| Web interface (HTTP) | https://rss.yourdomain.com/ | nginx/PHP crash |
| PHP-FPM health (HTTP) | /api/stats or /health.php | PHP-FPM failure |
| Feed scheduler (Heartbeat) | cliupdate.php cron | Feeds going stale |
| Database (TCP / Heartbeat) | Port 3306 / 5432 / SQLite file | DB connectivity loss |
| API response time (HTTP) | /api/stats | Slow database queries |
| Feed error rate (Heartbeat) | Log-based script | Feed parse failures |
| SSL certificate | Selfoss domain | Certificate expiry |
| OPML service (HTTP) | /opml | Import/export failure |
Selfoss keeps your reading life private and your feeds under your control — but only when the PHP stack, database, and cron scheduler are all working together. With Vigilmon watching the web interface, PHP-FPM health, feed scheduler heartbeat, and database connectivity, you'll know the moment your RSS reader needs attention rather than discovering it when you open the app to catch up on your morning reading.