Shiori is a clean, self-hosted bookmark manager written in Go — a single binary that stores bookmarks with titles, excerpts, thumbnails, and full offline copies of the page. No cloud service, no tracking, and a REST API that works with scripts and mobile apps alike. But because Shiori quietly handles authentication and background page downloads in the same process, a broken database connection or stalled download worker can be invisible until you try to read a bookmark offline. Vigilmon watches Shiori's web UI, authentication API, and download worker health so problems surface immediately rather than silently accumulating.
What You'll Set Up
- HTTP monitor for the Shiori web UI (port 8080)
- HTTP monitor for the Shiori REST API authentication endpoint (
/api/v1/auth/login) - HTTP monitor for the authenticated tag API (
/api/v1/tags) - SSL certificate expiry alerts for HTTPS Shiori deployments
- Heartbeat monitor that confirms Shiori's background bookmark download worker is processing pages
Prerequisites
- Shiori running and accessible on port 8080 (or via a reverse proxy)
- Shiori admin credentials (username and password)
- A free Vigilmon account
Step 1: Monitor the Shiori Web UI
Shiori's Go HTTP server listens on port 8080 by default. A GET / returns the login page (or the bookmark list for authenticated sessions) — a 200 response confirms the Go server is up and the SQLite, MySQL, or PostgreSQL backend is connected.
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your Shiori URL:
http://your-server:8080(orhttps://shiori.yourdomain.comif reverse-proxied). - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Click Save.
If Shiori is configured with a base path (e.g. /shiori/), use the full path. The login page response confirms not just that Go is running but that the HTML templates and static assets are being served correctly.
Step 2: Monitor the REST API Authentication Endpoint
The Shiori REST API at /api/v1/auth/login accepts a POST with admin credentials and returns a JSON object containing an access_token field. This is the highest-signal health check available — it confirms the Go HTTP server is handling API routes, the authentication middleware is working, and the database is returning user records.
- Click Add Monitor in Vigilmon.
- Set Type to
HTTP / HTTPS. - Enter the login URL:
http://your-server:8080/api/v1/auth/login - Set HTTP method to
POST. - Set Request body to:
{"username": "your-admin-username", "password": "your-admin-password"} - Set Request headers:
Content-Type: application/json - Set Expected HTTP status to
200. - Under Response body check, enter
access_tokento confirm the token was issued. - Set Check interval to
5 minutes. - Click Save.
The access_token body check is essential — a misconfigured database connection causes Shiori to return a 500 or a 200 with an error JSON rather than a valid token.
Step 3: Monitor the Authenticated Tag API
The tag API at GET /api/v1/tags requires a valid Bearer token and returns the list of all tags in the Shiori database. Monitoring this endpoint confirms that authenticated API routes are accessible and the database is returning data beyond the authentication layer.
Because Shiori tokens expire, this monitor is best implemented as a scripted check using Vigilmon's webhook-based custom monitor or an external cron script:
#!/bin/bash
# /etc/cron.d/shiori-tag-check
SHIORI_URL="http://localhost:8080"
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/def456"
# Authenticate and retrieve token
TOKEN=$(curl -s -X POST "${SHIORI_URL}/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-password"}' \
| grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
if [ -z "$TOKEN" ]; then
echo "Shiori auth failed" >&2
exit 1
fi
# Fetch tags with the token
STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
"${SHIORI_URL}/api/v1/tags" \
-H "Authorization: Bearer ${TOKEN}")
if [ "$STATUS" = "200" ]; then
curl -s "${VIGILMON_HEARTBEAT}" > /dev/null
fi
For a simpler setup, add a second HTTP monitor in Vigilmon pointing to /api/v1/tags with a hardcoded Bearer token and accept that it will alert when the token expires (a useful reminder to rotate credentials).
Step 4: SSL Certificate Alerts for HTTPS Deployments
Shiori is typically reverse-proxied behind nginx, Caddy, or Traefik, which handles TLS termination. The proxy's certificate must stay valid — an expiry locks all clients out.
- Open the HTTPS monitor for your Shiori 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.
For Caddy deployments, certificates auto-renew by default. For nginx with certbot, verify the systemd timer is active:
systemctl status certbot.timer
# Test without issuing a certificate
sudo certbot renew --dry-run
For Traefik, check the ACME JSON file for certificate expiry dates:
cat /etc/traefik/acme.json | python3 -c "
import json, sys, base64, datetime
data = json.load(sys.stdin)
for resolver in data.values():
for cert in resolver.get('Certificates', []):
raw = base64.b64decode(cert['certificate'])
print(cert['domain']['main'])
"
Step 5: Heartbeat Monitoring for the Bookmark Download Worker
Shiori can automatically download offline copies of bookmarked pages for e-reader mode. This background operation runs within the Shiori process — if it stalls, bookmarks are saved as metadata only, with no offline content available. A heartbeat that adds a test bookmark and verifies the download status confirms the worker is processing.
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set Expected ping interval to
60 minutes. - Copy the heartbeat URL (e.g.
https://vigilmon.online/heartbeat/ghi789).
Set up a cron job that adds a bookmark and checks that Shiori has populated the download fields:
#!/bin/bash
# /etc/cron.hourly/shiori-heartbeat
SHIORI_URL="http://localhost:8080"
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/ghi789"
# Authenticate
TOKEN=$(curl -s -X POST "${SHIORI_URL}/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-password"}' \
| python3 -c "import sys,json; print(json.load(sys.stdin).get('access_token',''))")
if [ -z "$TOKEN" ]; then
echo "Auth failed" >&2
exit 1
fi
# Add a lightweight test bookmark
BOOKMARK=$(curl -s -X POST "${SHIORI_URL}/api/v1/bookmarks" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "tags": [{"name": "healthcheck"}]}')
BOOKMARK_ID=$(echo "$BOOKMARK" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))")
if [ -z "$BOOKMARK_ID" ]; then
echo "Bookmark creation failed" >&2
exit 1
fi
# Wait for the download worker (up to 30 seconds)
for i in $(seq 1 6); do
sleep 5
STATUS=$(curl -s "${SHIORI_URL}/api/v1/bookmarks/${BOOKMARK_ID}" \
-H "Authorization: Bearer ${TOKEN}" \
| python3 -c "import sys,json; b=json.load(sys.stdin); print(b.get('hasArchive', False))")
if [ "$STATUS" = "True" ]; then
curl -s "${VIGILMON_HEARTBEAT}" > /dev/null
# Clean up the test bookmark
curl -s -X DELETE "${SHIORI_URL}/api/v1/bookmarks" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d "[${BOOKMARK_ID}]"
exit 0
fi
done
echo "Download worker did not process bookmark within 30 seconds" >&2
exit 1
If the download worker is not running or is stalled, the hasArchive field stays false and the heartbeat is never sent — Vigilmon alerts after the expected interval.
Step 6: Configure Alert Channels
- Go to Alert Channels in Vigilmon and add Slack, email, or a webhook.
- Set Consecutive failures before alert to
2on the web UI monitor — brief Go server restarts or container redeploys can cause a single probe to fail. - For the authentication API monitor, a single failure is a meaningful signal — set Consecutive failures before alert to
1.
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| Web UI | http://your-server:8080/ | Go server down, database unreachable |
| Auth API | /api/v1/auth/login (POST) | Authentication failure, database connectivity |
| Tag API heartbeat | Heartbeat URL | Authenticated API broken, database read failure |
| SSL certificate | Shiori domain | Reverse proxy certificate expiry |
| Download heartbeat | Heartbeat URL | Bookmark download worker stalled |
Shiori's simplicity is its strength — a single Go binary, minimal dependencies, and a clean REST API. Vigilmon keeps that simplicity honest: if the database disconnects, the download worker stalls, or the reverse proxy certificate expires, you'll know within minutes rather than discovering it when you're offline and need a saved article.