Hoarder (now also known as Karakeep) is a self-hosted bookmark manager that goes beyond simple link saving: it crawls the target URL, captures a screenshot, extracts the full article text, and runs AI-based tagging using OpenAI or a local Ollama instance — all automatically in the background. That background processing is exactly where silent failures hide. The Next.js frontend can return 200 while the crawler is stuck, the Meili search index is stale, or the AI tagger has been failing for days. Vigilmon gives you layered coverage: Next.js server health, a dedicated health API endpoint, authenticated API liveness, SSL certificate alerts, and a heartbeat that proves the async crawler is actually processing new bookmarks.
What You'll Set Up
- HTTP monitor for the Hoarder Next.js web UI (port 3000)
- HTTP monitor for the built-in health endpoint (
/api/v1/healthz) - HTTP monitor for the authenticated bookmarks API (
/api/v1/bookmarks) - SSL certificate expiry alerts for HTTPS Hoarder deployments
- Heartbeat monitor that confirms Hoarder's background crawler and AI tagger are processing new bookmarks
Prerequisites
- Hoarder deployed and accessible (Docker Compose recommended; web UI on port 3000)
- A Hoarder API key (generated in the Hoarder settings under API Keys)
- A free Vigilmon account
Step 1: Monitor the Hoarder Web UI
Hoarder's Next.js frontend is served on port 3000 by default. A GET / returns the app shell — a 200 response confirms the Next.js server is running and the basic routing layer is healthy.
- Log in to vigilmon.online and click Add Monitor.
- Set Type to
HTTP / HTTPS. - Enter your Hoarder URL:
http://your-server:3000(orhttps://hoarder.yourdomain.comif reverse-proxied). - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Click Save.
The root route will redirect to /dashboard or /login for unauthenticated users — enable Follow redirects so Vigilmon follows through to the final 200.
Step 2: Monitor the Health Endpoint
Hoarder ships with a dedicated health check endpoint at GET /api/v1/healthz that returns {"status": "ok"} when the tRPC API server and database connection are both healthy. This is the most lightweight and reliable monitor you can add — it was built specifically for liveness checks.
- Click Add Monitor in Vigilmon.
- Set Type to
HTTP / HTTPS. - Enter the health URL:
http://your-server:3000/api/v1/healthz - Set Check interval to
1 minute. - Set Expected HTTP status to
200. - Under Response body check, enter
"status":"ok"to verify the response content. - Click Save.
Run a manual check to confirm the endpoint is accessible:
curl -s http://localhost:3000/api/v1/healthz
# {"status":"ok"}
Step 3: Monitor the Authenticated Bookmarks API
The GET /api/v1/bookmarks endpoint requires a Bearer token and returns the user's bookmark list. Monitoring this confirms the authentication middleware is working, the database is returning data, and the full tRPC API stack is healthy — not just the health endpoint's lightweight probe.
- Click Add Monitor in Vigilmon.
- Set Type to
HTTP / HTTPS. - Enter the bookmarks API URL:
http://your-server:3000/api/v1/bookmarks - Set HTTP method to
GET. - Set Request headers:
Authorization: Bearer your-api-key-here - Set Expected HTTP status to
200. - Under Response body check, enter
bookmarksto confirm the response contains the bookmark array. - Set Check interval to
5 minutes. - Click Save.
Generate your API key in Hoarder: go to Settings → API Keys → Create new key. The API key does not expire unless you revoke it, so this monitor stays valid indefinitely.
Step 4: SSL Certificate Alerts for HTTPS Deployments
Hoarder is reverse-proxied behind nginx, Caddy, or Traefik in most production deployments. The reverse proxy manages TLS — if its certificate expires, the Hoarder browser extension, mobile apps, and web UI all stop working simultaneously.
- Open the HTTPS monitor for your Hoarder 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 Docker Compose deployments with Traefik, verify the ACME certificate store is being refreshed:
# Check Traefik logs for certificate renewal activity
docker logs traefik --since 24h | grep -i "acme\|certificate\|renew"
For Caddy, certificates are auto-renewed transparently — check the Caddy log for any ACME errors:
docker logs caddy --since 24h | grep -i "error\|certificate\|acme"
Step 5: Heartbeat Monitoring for the Crawler and AI Tagger
Hoarder's most critical background processes — the link crawler, screenshot capture, and AI tagger — are async workers that run independently of the web server. When they stall, bookmarks are saved as bare links with no title, no excerpt, no screenshot, and no AI tags. The heartbeat below adds a test bookmark and verifies that Hoarder's crawler has populated a crawledAt timestamp within a few minutes, proving the pipeline is end-to-end healthy.
- In Vigilmon, click Add Monitor → Cron Heartbeat.
- Set Expected ping interval to
30 minutes. - Copy the heartbeat URL (e.g.
https://vigilmon.online/heartbeat/jkl012).
Set up a cron job on the Hoarder host:
#!/bin/bash
# /etc/cron.d/hoarder-heartbeat (runs every 30 minutes via cron schedule)
HOARDER_URL="http://localhost:3000"
HOARDER_API_KEY="your-api-key-here"
VIGILMON_HEARTBEAT="https://vigilmon.online/heartbeat/jkl012"
# Create a test bookmark
RESPONSE=$(curl -s -X POST "${HOARDER_URL}/api/v1/bookmarks" \
-H "Authorization: Bearer ${HOARDER_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"type": "link", "url": "https://example.com"}')
BOOKMARK_ID=$(echo "$RESPONSE" | 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
# Poll for crawledAt timestamp (check every 10 seconds, up to 2 minutes)
for i in $(seq 1 12); do
sleep 10
CRAWLED=$(curl -s "${HOARDER_URL}/api/v1/bookmarks/${BOOKMARK_ID}" \
-H "Authorization: Bearer ${HOARDER_API_KEY}" \
| python3 -c "import sys,json; b=json.load(sys.stdin).get('content',{}); print(b.get('crawledAt',''))")
if [ -n "$CRAWLED" ] && [ "$CRAWLED" != "null" ] && [ "$CRAWLED" != "None" ]; then
# Crawler processed the bookmark — ping Vigilmon
curl -s "${VIGILMON_HEARTBEAT}" > /dev/null
# Delete the test bookmark
curl -s -X DELETE "${HOARDER_URL}/api/v1/bookmarks/${BOOKMARK_ID}" \
-H "Authorization: Bearer ${HOARDER_API_KEY}" > /dev/null
exit 0
fi
done
echo "Hoarder crawler did not process bookmark within 2 minutes" >&2
exit 1
Add to crontab:
*/30 * * * * /etc/cron.d/hoarder-heartbeat >> /var/log/hoarder-heartbeat.log 2>&1
If the crawler is stalled — due to a failed Playwright browser, an OpenAI API outage blocking the AI tagger, or a full disk — the crawledAt field stays empty and Vigilmon alerts after 30 minutes.
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 — Next.js cold starts and container restarts can cause single-probe failures. - Set Consecutive failures before alert to
1on the/api/v1/healthzmonitor — this endpoint is designed to fail fast, so a single failure is meaningful. - For the heartbeat monitor, configure the grace period to match your cron interval: Grace period to
35 minutes(30-minute interval plus 5 minutes of tolerance).
Summary
| Monitor | Target | What It Catches |
|---|---|---|
| Web UI | http://your-server:3000/ | Next.js server down, startup failure |
| Health endpoint | /api/v1/healthz | tRPC API or database unreachable |
| Bookmarks API | /api/v1/bookmarks (GET + auth) | Authentication broken, database read failure |
| SSL certificate | Hoarder domain | Reverse proxy certificate expiry |
| Crawler heartbeat | Heartbeat URL | Link crawler stalled, AI tagger failing |
Hoarder's value is in the enrichment layer — the screenshots, extracted text, and AI tags that turn a bare URL into a searchable knowledge library. If the background workers are silently failing, you're getting none of that. Vigilmon's heartbeat monitor is the only way to know the enrichment pipeline is working; everything else just tells you the front door is open.