tutorial

Monitoring Baikal CalDAV/CardDAV Server with Vigilmon

Baikal is a lightweight self-hosted CalDAV and CardDAV server, but calendar sync failures are silent. Here's how to monitor web server availability, PHP-FPM health, CalDAV/CardDAV endpoints, and database integrity with Vigilmon.

Baikal is a slim, PHP-based CalDAV and CardDAV server that lets you self-host your calendars, task lists, and contacts without relying on Google Calendar or iCloud. It runs under any web server (nginx, Apache) and stores data in SQLite or MySQL. The downside of self-hosting is that sync failures — a misconfigured PHP-FPM pool, a corrupted SQLite file, or an expired TLS certificate — are completely silent to calendar clients until your phone stops syncing at the worst possible time. Vigilmon closes that gap with continuous endpoint monitoring, TLS expiry alerts, and PHP-FPM heartbeats.

What You'll Set Up

  • HTTPS availability monitor for the Baikal web UI and DAV endpoints
  • TLS/SSL certificate expiry alert
  • PHP-FPM process health monitoring via a heartbeat
  • CalDAV and CardDAV endpoint response time checks
  • SQLite/MySQL database connectivity probe
  • Admin panel accessibility check
  • Cron heartbeat for the database backup job

Prerequisites

  • Baikal installed and accessible over HTTPS (nginx or Apache, port 443)
  • PHP-FPM running and serving Baikal
  • A free Vigilmon account

Step 1: Monitor the Baikal Web Server Availability

Baikal's entire feature set lives behind the web server. If nginx crashes or PHP-FPM stops responding, every calendar client silently fails to sync.

  1. Log in to vigilmon.online and click Add Monitor.
  2. Set Type to HTTP / HTTPS.
  3. Enter your Baikal URL: https://baikal.yourdomain.com/html/.
  4. Set Check interval to 1 minute.
  5. Set Expected HTTP status to 200.
  6. Click Save.

If you installed Baikal in the document root, the URL may simply be https://baikal.yourdomain.com/.


Step 2: Monitor TLS Certificate Expiry

CalDAV and CardDAV clients reject expired certificates immediately, breaking all sync without any user-visible error on the server side. Let's Encrypt renewals can fail silently.

  1. Open the HTTP / HTTPS monitor created in Step 1.
  2. Enable Monitor SSL certificate.
  3. Set Alert when certificate expires in less than 21 days.
  4. Click Save.

A 21-day window gives you three Let's Encrypt renewal cycles to recover before clients break. Verify your renewal cron job:

# Check the certbot/acme renewal timer
systemctl status certbot.timer
# Or for acme.sh
~/.acme.sh/acme.sh --list

Step 3: Monitor the CalDAV Endpoint

Baikal's CalDAV endpoint handles all calendar sync requests from iOS, Android, and Thunderbird. Monitor it directly to catch PHP or routing failures that wouldn't show up on the homepage:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: https://baikal.yourdomain.com/dav.php/calendars/
  3. Set Expected HTTP status to 401 (Baikal returns 401 Unauthorized for unauthenticated requests — this confirms the endpoint is alive).
  4. Set Check interval to 2 minutes.
  5. Click Save.

Alternatively, if using the HTML directory layout:

https://baikal.yourdomain.com/html/index.php/dav/calendars/

A 401 response is healthy — it means Baikal processed the request. A 502 Bad Gateway or 504 Gateway Timeout means PHP-FPM is down.


Step 4: Monitor the CardDAV Endpoint

The CardDAV endpoint handles contact sync separately from CalDAV. Add a parallel monitor:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: https://baikal.yourdomain.com/dav.php/addressbooks/
  3. Set Expected HTTP status to 401.
  4. Set Check interval to 2 minutes.
  5. Click Save.

If you use the HTML path layout:

https://baikal.yourdomain.com/html/index.php/dav/addressbooks/

Step 5: Monitor PHP-FPM Health

PHP-FPM has a built-in status endpoint that reports pool status, active processes, and request queue depth. Expose it in your nginx config:

# /etc/nginx/sites-available/baikal
server {
    ...
    location /php-fpm-status {
        fastcgi_pass unix:/run/php/php8.2-fpm.sock;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        allow 127.0.0.1;
        deny all;
    }
}

Enable the status page in your PHP-FPM pool config (/etc/php/8.2/fpm/pool.d/www.conf):

pm.status_path = /php-fpm-status

Reload PHP-FPM:

systemctl reload php8.2-fpm

Then add a Vigilmon monitor:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: http://127.0.0.1/php-fpm-status (or use an internal monitoring URL if you expose it on a non-public interface).
  3. Set Expected HTTP status to 200.
  4. Set Check interval to 1 minute.
  5. Click Save.

If PHP-FPM is unreachable, you'll see a 502 from nginx on all Baikal endpoints — this monitor identifies the root cause.


Step 6: Monitor the Admin Panel

Baikal's admin panel (/admin/) is the management interface for users and collections. Monitor it separately — admin routing can break independently of the DAV endpoints:

  1. Click Add MonitorHTTP / HTTPS.
  2. URL: https://baikal.yourdomain.com/html/admin/
  3. Set Expected HTTP status to 200.
  4. Set Check interval to 5 minutes.
  5. Click Save.

Step 7: Monitor Database Connectivity

Baikal stores all calendar and contact data in SQLite (default) or MySQL. A corrupt SQLite file or a MySQL connection failure means all DAV operations return errors.

SQLite Health Check Script

Create a script that probes the SQLite file and pings Vigilmon on success:

#!/bin/bash
# /usr/local/bin/baikal-db-check.sh
BAIKAL_DB="/var/www/baikal/Specific/db/db.sqlite"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_HEARTBEAT_ID"

if sqlite3 "$BAIKAL_DB" "SELECT COUNT(*) FROM calendarobjects;" > /dev/null 2>&1; then
    curl -s "$HEARTBEAT_URL"
else
    echo "Baikal SQLite check failed" | mail -s "Baikal DB Alert" admin@yourdomain.com
fi
chmod +x /usr/local/bin/baikal-db-check.sh

MySQL Health Check Script

If using MySQL instead:

#!/bin/bash
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_HEARTBEAT_ID"

if mysql -u baikal -p"$BAIKAL_DB_PASS" baikal -e "SELECT 1;" > /dev/null 2>&1; then
    curl -s "$HEARTBEAT_URL"
fi

Create the Vigilmon heartbeat monitor:

  1. Click Add MonitorCron Heartbeat.
  2. Set the expected interval to 5 minutes.
  3. Copy the heartbeat URL into the script above.

Schedule the check:

# /etc/cron.d/baikal-db-check
*/5 * * * * root /usr/local/bin/baikal-db-check.sh

Step 8: Heartbeat for the Database Backup Job

Your Baikal backup cron (or a script using sqlite3 .dump / mysqldump) should ping Vigilmon after each successful run:

#!/bin/bash
# /usr/local/bin/baikal-backup.sh
BACKUP_DIR="/backups/baikal"
BAIKAL_DB="/var/www/baikal/Specific/db/db.sqlite"
HEARTBEAT_URL="https://vigilmon.online/heartbeat/YOUR_BACKUP_HEARTBEAT_ID"

mkdir -p "$BACKUP_DIR"
sqlite3 "$BAIKAL_DB" ".dump" | gzip > "$BACKUP_DIR/baikal-$(date +%Y%m%d).sql.gz"

if [ $? -eq 0 ]; then
    curl -s "$HEARTBEAT_URL"
fi
  1. In Vigilmon, click Add MonitorCron Heartbeat.
  2. Set the expected interval to match your backup schedule (e.g. 24 hours).
  3. Set the heartbeat URL in your backup script.

Add to crontab:

# Daily backup at 2 AM
0 2 * * * root /usr/local/bin/baikal-backup.sh

If the backup script fails or is never run (e.g. the cron daemon crashes), Vigilmon alerts after the 24-hour window passes.


Step 9: Configure Alert Channels

  1. Go to Alert Channels in Vigilmon and add your preferred channel (email, Slack, webhook, PagerDuty).
  2. For the CalDAV and CardDAV endpoint monitors, set Consecutive failures before alert to 2 — transient PHP-FPM restarts can cause a single probe to fail.
  3. For the TLS certificate monitor, use immediate alerting — a certificate warning has a fixed deadline.

Summary

| Monitor | Target | What It Catches | |---|---|---| | Web server | https://baikal.yourdomain.com/ | nginx/Apache down | | TLS certificate | HTTPS endpoint | Let's Encrypt renewal failure | | CalDAV endpoint | /dav.php/calendars/401 | PHP routing or auth failure | | CardDAV endpoint | /dav.php/addressbooks/401 | PHP routing or auth failure | | PHP-FPM status | /php-fpm-status | FPM pool exhausted or crashed | | Admin panel | /html/admin/ | Admin routing broken | | Database heartbeat | Heartbeat URL | SQLite corruption, MySQL down | | Backup heartbeat | Heartbeat URL | Backup job missed or crashed |

Baikal's simplicity is its strength — and its monitoring blind spot. Calendar clients retry in the background and surface no errors until sync is hours behind. Vigilmon's continuous checks catch web server failures, PHP-FPM exhaustion, and expired certificates before your contacts and calendar entries stop syncing.

Monitor your app with Vigilmon

Free plan — 5 monitors, no credit card required. Up and running in 60 seconds.

Start free →