6.6 KiB
Baikal — Client Setup
Companion to baikal.md (auto-generated from compose). This file is hand-maintained and covers how to connect CalDAV/CardDAV clients to the Baikal server on Atlantis.
Server Reference
| Field | Value |
|---|---|
| Host | Atlantis (Synology NAS) |
| Container | baikal (image ckulka/baikal) |
| Port | 12852 → container 80 |
| Auth | HTTP Digest (not Basic) |
| DAV root | /dav.php/ |
| Admin UI | http://<host>:12852/admin/ |
Endpoints (all equivalent for authed CalDAV)
| URL | When to use |
|---|---|
http://192.168.0.200:12852/ |
LAN-only clients (dashboard, LAN appliances) |
http://atlantis:12852/ |
Nodes with Tailscale MagicDNS |
http://atlantis.tail.vish.gg:12852/ |
Preferred for portable clients (laptops that move on/off LAN) — stable DNS, works everywhere on the tailnet |
http://100.83.230.112:12852/ |
Raw Tailscale IP — fallback if DNS misbehaves |
URL patterns
- Principal:
/dav.php/principals/<user>/— point auto-discovering clients (iOS, macOS, DAVx⁵) here. - Calendar:
/dav.php/calendars/<user>/<calendar-uri>/— explicit calendar URL for clients that need it (Thunderbird with "Locate calendar" off). - Address book:
/dav.php/addressbooks/<user>/<addressbook-uri>/.
Credentials
- Baikal users live in the
userstable of/volume1/docker/baikal/Specific/db/db.sqlite. Passwords are stored as MD5 digesta1 (MD5(user:BaikalDAV:password)) — not reversible. - The
vishuser password is referenced by the dashboard's upcoming-events widget (seedashboard/api/routers/overview.py,BAIKAL_PASSconstant). Pull it from there — do not paste it into docs or client configs that get committed. - Reset or create a user from the admin UI at
/admin/(login with the admin password from compose env).
Inspecting the database
No sqlite3 binary in the container — use PHP PDO:
ssh atlantis "sudo /usr/local/bin/docker exec baikal php -r '
\$db=new PDO(\"sqlite:/var/www/baikal/Specific/db/db.sqlite\");
foreach(\$db->query(\"SELECT id,username FROM users\") as \$r){
echo \$r[\"id\"].\" \".\$r[\"username\"].PHP_EOL;
}'"
Useful tables: users, principals, calendars, calendarinstances (displayname, ACL, share state), calendarobjects, addressbooks, cards.
Thunderbird (GUI path)
- File → New → Calendar → On the Network → Next.
- Username: Baikal user (e.g.
vish). - Location: either
http://atlantis.tail.vish.gg:12852/dav.php/principals/vish/— lets TB auto-discover all calendars for that user, or- a specific calendar URL, e.g.
http://atlantis.tail.vish.gg:12852/dav.php/calendars/vish/default/.
- Find Calendars → select the one(s) to add → Subscribe.
- Password prompt appears on first sync; tick Use Password Manager to save.
Thunderbird (headless / prefs.js path)
Use when the client machine is remote and you want to drop a calendar in without touching the GUI. Procedure:
- Close Thunderbird.
prefs.jsis rewritten on exit — any edits made while it is running get clobbered. - Clear stale lock files if present:
rm -f ~/.thunderbird/<profile>/lock ~/.thunderbird/<profile>/.parentlock. - Back up:
cp prefs.js prefs.js.bak-$(date +%Y%m%d-%H%M%S). - Generate a UUID:
cat /proc/sys/kernel/random/uuid. - Append the registry block below (replace
<UUID>and tweakname,color,uri,username). - Update the
calendar.list.sortOrderline — append the new UUID (space-separated) so the calendar actually shows up.
user_pref("calendar.registry.<UUID>.cache.enabled", true);
user_pref("calendar.registry.<UUID>.calendar-main-in-composite", true);
user_pref("calendar.registry.<UUID>.color", "#3aa57c");
user_pref("calendar.registry.<UUID>.disabled", false);
user_pref("calendar.registry.<UUID>.forceEmailScheduling", false);
user_pref("calendar.registry.<UUID>.imip.identity.key", "id1");
user_pref("calendar.registry.<UUID>.name", "vish (Baikal)");
user_pref("calendar.registry.<UUID>.notifications.times", "");
user_pref("calendar.registry.<UUID>.readOnly", false);
user_pref("calendar.registry.<UUID>.refreshInterval", "30");
user_pref("calendar.registry.<UUID>.suppressAlarms", false);
user_pref("calendar.registry.<UUID>.type", "caldav");
user_pref("calendar.registry.<UUID>.uri", "http://atlantis.tail.vish.gg:12852/dav.php/calendars/vish/default/");
user_pref("calendar.registry.<UUID>.username", "vish");
Password handling: do not attempt to pre-populate the login store — it is NSS-encrypted and requires live TB APIs to write correctly. Leave the password out of prefs.js entirely; on first sync Thunderbird will prompt, and the user ticks Use Password Manager once.
Verification (from client machine, before TB relaunch): confirm the client can reach the URL with the credentials:
curl -s -o /dev/null -w 'HTTP %{http_code}\n' \
--digest -u '<user>:<password>' \
http://atlantis.tail.vish.gg:12852/dav.php/calendars/<user>/default/
Expect HTTP 200. If 401, the password is wrong or the realm name changed. If no response, check Tailscale reachability (tailscale status | grep atlantis) before blaming Baikal.
Deployed clients (as of 2026-04-19)
| Client | Calendar | URL | Auth flavor |
|---|---|---|---|
| Dashboard widget (homelab-vm) | vish/default |
http://192.168.0.200:12852/dav.php/calendars/vish/default/ |
Digest via httpx.DigestAuth, creds in dashboard/api/routers/overview.py |
| Thunderbird on moon laptop | vish/default |
http://atlantis.tail.vish.gg:12852/dav.php/calendars/vish/default/ |
Digest, password in TB password manager (user-entered on first sync) |
Troubleshooting
401 Unauthorized: Baikal speaks Digest, not Basic. Mostcurltests need--digest. Thunderbird handles this automatically.- Calendar appears but never refreshes: check
calendar.registry.<UUID>.cache.enabledistrue; the local-cache is what TB displays between network syncs. - Events not showing on the dashboard: the widget only queries
vish/default. Other calendars need a separatecalendar-queryREPORT against their URL. - Admin UI locked out:
INSTALL_DISABLEDis touched in/var/www/baikal/Specific/after first setup. Delete that file in the container to re-enable the install wizard if you need to reset the admin password.
Related
baikal.md— auto-generated compose reference.hosts/synology/atlantis/baikal/baikal.yaml— stack definition.dashboard/api/routers/overview.py— dashboard CalDAV consumer (reference implementation for Digest queries).