Skip to main content

Baikal CalDAV Runbook

Service: Baikal CalDAV

Label: Docker container baikal + LaunchAgent com.john.calendar-bridge Tier: P2 (Business) Port: 5232 (local), calendar.basicconsulting.no (public via Cloudflare)

What It Does

Self-hosted CalDAV server for ALAI Business calendar. Alem syncs from iPhone/MacBook via native Calendar app. calendar-bridge.js daemon scans emails every 5min, detects meeting invites, forwards to [email protected], and creates CalDAV events.

Architecture

Email (john@) → email-agent.js → calendar-bridge.js → Baikal CalDAV → Alem iPhone/Mac
                                       ↓
                               mail-native.js forward → [email protected]

Components

Component Location Type
Baikal server ~/system/services/baikal/docker-compose.yml Docker
calendar-bridge.js ~/system/tools/calendar-bridge.js Tool + Daemon
LaunchAgent ~/Library/LaunchAgents/com.john.calendar-bridge.plist Daemon (5min)
Cloudflare tunnel calendar.basicconsulting.no → localhost:5232 Tunnel
Credentials Vaultwarden → "Baikal CalDAV" Vault
Calendar "ALAI Business" (CalDAV user: alem) CalDAV
Data ~/system/services/baikal/data/ Persistent volume

Dependencies

  • Docker (container: baikal)
  • Cloudflare tunnel (com.john.cloudflared)
  • Vaultwarden (credentials)
  • mail-native.js (email forwarding)
  • email-agent.js (inline meeting detection)

Health Check

# Quick check
node ~/system/tools/calendar-bridge.js test

# Docker container
docker ps --filter name=baikal

# CalDAV endpoint
curl -s -o /dev/null -w "%{http_code}" http://localhost:5232/dav.php/

# Public URL (expect 401 = auth required = healthy)
curl -s -o /dev/null -w "%{http_code}" https://calendar.basicconsulting.no/dav.php/

# List events
node ~/system/tools/calendar-bridge.js list

Common Failures & Fixes

Failure 1: Baikal container down

Symptoms: calendar-bridge.js test fails, CalDAV 502/connection refused Fix:

cd ~/system/services/baikal && docker compose up -d

Failure 2: Cloudflare tunnel not routing

Symptoms: Public URL returns 404 or timeout, local URL works fine Fix:

# Check config includes calendar entry
grep calendar ~/.cloudflared/config.yml
# Restart tunnel
launchctl kickstart -k gui/$(id -u)/com.john.cloudflared

Failure 3: Calendar-bridge scan finds nothing

Symptoms: Meeting invites arrive but no events created, no forwards Check:

# Check daemon is running
launchctl list | grep calendar-bridge
# Check logs
tail -50 ~/system/logs/calendar-bridge.log
# Check state file
cat ~/system/logs/calendar-bridge-state.json
# Manual scan with verbose
node ~/system/tools/calendar-bridge.js scan --verbose

Failure 4: Alem can't sync from iPhone

Symptoms: iPhone Calendar shows error, events not showing Check:

  1. Verify credentials in Vault: node ~/system/tools/vault.js get "Baikal CalDAV"
  2. Test public CalDAV endpoint (should return 401, not 502/404)
  3. iPhone settings: Server = calendar.basicconsulting.no/dav.php/principals/alem

Failure 5: Authentication failure

Symptoms: 401 with correct password Fix: Password might be out of sync. Re-hash in Baikal DB:

NEW_PASS=$(bw get password "Baikal CalDAV" --session $(cat /tmp/bw-session))
DIGEST=$(printf "alem:BaikalDAV:$NEW_PASS" | md5)
docker exec baikal sqlite3 /var/www/baikal/Specific/db/db.sqlite \
  "UPDATE users SET digesta1='$DIGEST' WHERE username='alem';"

Restart Procedure

# Restart Baikal
cd ~/system/services/baikal && docker compose restart

# Restart calendar-bridge daemon
launchctl kickstart -k gui/$(id -u)/com.john.calendar-bridge

Backup

  • SQLite DB: ~/system/services/baikal/data/Specific/db/db.sqlite
  • Config: ~/system/services/baikal/data/config/baikal.yaml
  • Included in daily db-backup.sh via Docker volume mount

MC Task

Created: #3029 (Deploy), #3035 (Documentation + Watchdog)