Your Koel music server stopped syncing new tracks weeks ago and you only noticed when a fresh album you added never appeared in your playlists. The Laravel API was healthy, nginx was running, but the koel:sync cron job had quietly died after a server upgrade. For self-hosters who want a Spotify-like experience from their own hardware, silent sync failures are the most insidious kind.
Koel is an open-source, self-hosted personal music streaming service built with a PHP/Laravel backend and a polished Vue.js SPA frontend. It serves your entire music collection through a sleek modern interface with smart playlists, Last.fm scrobbling, and collaborative features. Vigilmon gives you the external monitoring that catches Koel failures before they interrupt your listening — covering the Vue.js frontend, Laravel API health, authentication service, SSL certificates, and media scanner heartbeats.
This tutorial walks you through monitoring Koel end-to-end with Vigilmon.
What You'll Build
- A Vigilmon HTTP monitor on the Koel Vue.js SPA (port 80/443)
- A Laravel API ping monitor
- An authentication service health monitor
- SSL certificate expiry alerts for HTTPS deployments
- A heartbeat monitor for the Koel media scanner (koel:sync)
- Alert channels for immediate notification
Prerequisites
- A running Koel instance (nginx-proxied on port 80/443)
- A Koel user account with a known password (for API authentication checks)
- A free account at vigilmon.online
Step 1: Monitor Koel Web Application Availability
Koel serves its Vue.js SPA through nginx on port 80/443. A GET request to / returns the compiled HTML shell that loads the Koel frontend application. A 200 response confirms nginx and the Koel web app are serving correctly.
Test it from your terminal:
curl -I https://music.yourdomain.com/
Expected response:
HTTP/2 200
Set up the Vigilmon monitor:
- Log in to Vigilmon and click New Monitor → HTTP.
- Set URL to
https://music.yourdomain.com/. - Set Check interval to 60 seconds.
- Set Expected status code to
200. - Under Advanced → Keyword check, configure:
- Keyword present:
Koel
- Keyword present:
- Save the monitor.
The Koel SPA HTML includes the application name in its title. If the frontend assets are missing, nginx returns a 404, or the build artifacts were accidentally deleted, the keyword check fails even if the port is open.
Step 2: Monitor the Koel Laravel API
The Vue.js frontend could serve correctly while the Laravel backend API is broken — a failed database migration, a missing .env value, or a PHP-FPM crash can take down the API while nginx keeps serving cached static files.
Koel exposes a /api/ping endpoint that confirms the Laravel API layer is responding:
curl https://music.yourdomain.com/api/ping
Expected response:
{"success": true}
A 200 response with success: true confirms the Laravel application is booted, its service container is initialized, and the database connection is healthy (Laravel validates the database connection on startup).
Set up the monitor in Vigilmon:
- Click New Monitor → HTTP.
- Set URL to
https://music.yourdomain.com/api/ping. - Set Expected status code to
200. - Under Advanced → JSON body assertion, add:
- Path:
success - Operator:
equals - Value:
true
- Path:
- Save.
This separates static asset delivery from backend application health — a critical distinction for SPAs where the shell HTML can be cached independently of the API.
Step 3: Monitor Koel Authentication Service Health
The authentication system is the gateway to everything in Koel — if the auth service is broken, users cannot log in even if the API health endpoint is green. Authentication depends on the database user table, JWT token generation, and the session configuration being correct.
Use POST /api/me to verify the full authentication stack:
curl -X POST https://music.yourdomain.com/api/me \
-H "Content-Type: application/json" \
-d '{"email": "monitor@yourdomain.com", "password": "yourpassword"}'
Expected response:
{
"token": "eyJ...",
"audio-token": "...",
"id": 1,
"name": "Monitor User"
}
A successful response with a JWT bearer token confirms the auth system, MySQL/PostgreSQL database, and user table are all operational.
Set up the monitor in Vigilmon:
- Click New Monitor → HTTP.
- Set Method to
POST. - Set URL to
https://music.yourdomain.com/api/me. - Under Advanced → Request headers, add:
Content-Type: application/json
- Under Advanced → Request body, set:
{"email": "monitor@yourdomain.com", "password": "yourpassword"} - Set Expected status code to
200. - Under Advanced → Keyword check:
- Keyword present:
token
- Keyword present:
- Save.
Create a dedicated low-privilege Koel user for monitoring. Avoid using your main account credentials in an automated monitor.
Step 4: SSL Certificate Monitoring
Koel is served over HTTPS through nginx with Let's Encrypt certificates. An expired SSL certificate breaks the web app for all users — browsers block access with a security warning, and Koel's mobile clients refuse to connect.
Vigilmon monitors SSL certificate validity automatically for HTTPS monitors. To configure dedicated expiry alerts:
- Open your HTTPS Koel monitor in Vigilmon.
- Go to Settings → SSL.
- Enable Alert when certificate expires within 14 days.
- Optionally enable Alert when certificate expires within 30 days for early warning.
You'll receive alerts like:
⚠️ SSL Warning: music.yourdomain.com
Certificate expires in 13 days (2026-07-26)
Certbot auto-renewal can fail after system upgrades, nginx config changes, or when the webroot path changes. Vigilmon's certificate monitor catches renewal failures before your certificate lapses.
Step 5: Heartbeat Monitor for Koel Media Scanner
Koel requires php artisan koel:sync to index new music files into its MySQL/PostgreSQL database. This command is typically run as a cron job every 30 minutes. If the cron job stops executing — after a system reboot, a crontab edit, or a PHP version upgrade — new music is silently excluded from your library while the existing catalog remains intact.
Use an authenticated GET to /api/songs as a heartbeat that tracks library activity:
First, obtain a token using the authentication step above, then:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
"https://music.yourdomain.com/api/songs?page=1"
Expected response excerpt:
{
"data": [...],
"links": {...},
"meta": {
"total": 5241
}
}
The meta.total field reflects the current song count in the Koel database. A stagnant count over days when you know you've been adding music indicates the sync cron has stopped.
Set up the heartbeat monitor in Vigilmon:
- Click New Monitor → HTTP.
- Set URL to
https://music.yourdomain.com/api/songs?page=1. - Set Expected status code to
200. - Under Advanced → Request headers, add:
Authorization: Bearer YOUR_JWT_TOKEN
- Under Advanced → JSON body assertion, add:
- Path:
meta.total - Operator:
greater than - Value:
0
- Path:
- Save.
The meta.total > 0 assertion confirms Koel has at least one indexed song — an empty library indicates a broken sync or a fresh database with no initial scan completed.
For tracking sync cron health specifically, also verify the cron is configured:
crontab -l
# Should contain something like:
# */30 * * * * cd /var/www/koel && php artisan koel:sync >> /var/log/koel-sync.log 2>&1
Step 6: Alert Channels
Go to Notifications → New Channel in Vigilmon and configure your preferred alert delivery:
- Email — immediate alerts to your inbox
- Webhook — forward to Discord, Slack, or ntfy.sh for push notifications on mobile
For Discord, paste your server webhook URL. A Koel downtime alert looks like:
🔴 DOWN: music.yourdomain.com/api/ping (HTTP 500)
Koel Laravel API health check failed
Region: EU-West
Triggered: 2026-01-15 18:37 UTC
Recovery notification:
✅ RECOVERED: music.yourdomain.com/api/ping
Downtime: 31 minutes
Step 7: Status Page
Go to Status Pages → New Status Page in Vigilmon. Add your Koel monitors — SPA frontend, API ping, and auth health — and publish. Share with household members so they can check music server status without bothering you.
What You've Built
| Scenario | How Vigilmon catches it |
|---|---|
| nginx stops serving | Web UI monitor returns connection refused or non-200 |
| SPA assets missing or corrupt | Keyword Koel absent from homepage HTML |
| Laravel API crash (PHP-FPM down) | /api/ping returns non-200 |
| MySQL/PostgreSQL database unavailable | /api/ping returns 500 (Laravel DB check fails) |
| Auth system broken (user table issue) | POST /api/me fails or returns non-200 |
| SSL certificate expired or expiring | SSL expiry alert triggers at threshold |
| koel:sync cron stopped (no new music) | /api/songs total stagnates; meta.total assertion fails if zero |
Koel gives you a Spotify-grade listening experience on your own hardware — but without external monitoring, you're the last to know when the backend breaks or the sync cron dies. Vigilmon watches from outside your network, from multiple regions, with no agents to install.
Start monitoring your Koel server today — register free at vigilmon.online.