How to Self-Host Baikal: CalDAV/CardDAV Server with Web Admin 2026
TL;DR
Baikal (GPL 3.0, ~2K GitHub stars, PHP) is a CalDAV/CardDAV server built on the sabre/dav library — the same library powering many hosting providers' calendar sync. Its key advantage over Radicale is the browser-based admin UI for managing users, calendars, and address books without touching config files. If you want CalDAV/CardDAV that non-technical users can manage via a web interface, Baikal is the right choice.
Key Takeaways
- Baikal: GPL 3.0, ~2K stars, PHP — CalDAV/CardDAV with a web admin UI
- sabre/dav: Battle-tested CalDAV/CardDAV library used by Nextcloud, ownCloud, and hosting providers
- Web admin: Create users, calendars, and address books in a browser
- SQLite or MySQL: Choice of database backend
- vs Radicale: Baikal has a web UI; Radicale is even more minimal (config file only)
- vs Nextcloud: Baikal is just calendar/contacts — no files, no apps overhead
Part 1: Docker Setup
# docker-compose.yml
services:
baikal:
image: ckulka/baikal:nginx
container_name: baikal
restart: unless-stopped
ports:
- "8800:80"
volumes:
- baikal_config:/var/www/baikal/config
- baikal_specific:/var/www/baikal/Specific
environment:
- TZ=America/Los_Angeles
volumes:
baikal_config:
baikal_specific:
docker compose up -d
Visit http://your-server:8800/admin/ for first-time setup.
Part 2: First-Run Setup
- Admin Panel URL:
https://cal.yourdomain.com/admin/ - Set admin password
- Database: Choose SQLite (simple) or MySQL (multi-user production)
- Click Save changes
With MySQL backend
services:
baikal:
image: ckulka/baikal:nginx
environment:
- BAIKAL_MYSQL=true
- BAIKAL_MYSQL_HOST=db
- BAIKAL_MYSQL_DBNAME=baikal
- BAIKAL_MYSQL_USERNAME=baikal
- BAIKAL_MYSQL_PASSWORD="${MYSQL_PASSWORD}"
depends_on:
- db
db:
image: mariadb:10.11
restart: unless-stopped
environment:
MARIADB_DATABASE: baikal
MARIADB_USER: baikal
MARIADB_PASSWORD: "${MYSQL_PASSWORD}"
MARIADB_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
Part 3: HTTPS with Caddy
cal.yourdomain.com {
reverse_proxy localhost:8800
}
Part 4: Create Users and Collections
Via web admin
- Log in at
https://cal.yourdomain.com/admin/ - Users and resources → + Add user
- Username:
alice - Display name:
Alice Smith - Email:
alice@yourdomain.com - Password: set password
- Username:
- Click the user → Add calendar
- Calendar ID:
personal - Display name:
Personal - Description:
Personal calendar
- Calendar ID:
- Click the user → Add address book
- Address book ID:
contacts - Display name:
Contacts
- Address book ID:
Via URL structure
After creating users, the CalDAV/CardDAV URLs are:
# Calendar (CalDAV):
https://cal.yourdomain.com/dav.php/principals/alice/
https://cal.yourdomain.com/dav.php/calendars/alice/personal/
# Contacts (CardDAV):
https://cal.yourdomain.com/dav.php/addressbooks/alice/contacts/
Part 5: iOS / macOS Setup
Calendar (CalDAV) — iOS
- Settings → Calendar → Accounts → Add Account → Other
- Add CalDAV Account
- Server:
https://cal.yourdomain.com - Username:
alice - Password: your password
- Description:
Baikal Calendar
iOS auto-discovers calendars. After adding account, check Settings → Calendar → Accounts → your account — calendars should appear.
Contacts (CardDAV) — iOS
- Settings → Contacts → Accounts → Add Account → Other
- Add CardDAV Account
- Server:
https://cal.yourdomain.com - Username:
alice, Password: your password
macOS
- System Settings → Internet Accounts → Add Account → Other
- Add both CalDAV Account and CardDAV Account
- Account type: Advanced → enter server URL manually
Part 6: Android with DAVx⁵
- Install DAVx⁵ from F-Droid (free) or Google Play
- + → Login with URL and username
- Base URL:
https://cal.yourdomain.com/dav.php - Username:
alice, Password: your password - DAVx⁵ discovers all calendars and address books
- Toggle each to enable sync
Part 7: Thunderbird
Calendar
- Calendar → New Calendar → On the Network → CalDAV
- URL:
https://cal.yourdomain.com/dav.php/calendars/alice/personal/ - Username:
alice, Password: your password
Contacts
- Address Book → New Address Book → CardDAV
- URL:
https://cal.yourdomain.com/dav.php/addressbooks/alice/contacts/ - Username:
alice, Password: your password
Part 8: Sharing Calendars
Baikal supports shared calendars via the admin UI:
- Admin → Users → alice → [Calendar] → Share
- Add user
bobwith read or read/write access - Bob's device syncs to:
https://cal.yourdomain.com/dav.php/calendars/alice/shared-calendar/
For family or team use, create a dedicated shared user:
User: family (password: shared-password)
Calendar: family-events
Address book: family-contacts
Everyone connects with username "family" to sync shared data.
Maintenance
# Update:
docker compose pull
docker compose up -d
# Backup SQLite:
docker cp baikal:/var/www/baikal/Specific/db/baikal.db \
./baikal-backup-$(date +%Y%m%d).db
# Backup all config and data:
tar -czf baikal-backup-$(date +%Y%m%d).tar.gz \
$(docker volume inspect baikal_baikal_config --format '{{.Mountpoint}}') \
$(docker volume inspect baikal_baikal_specific --format '{{.Mountpoint}}')
# Logs:
docker compose logs -f baikal
See also: Radicale (even more minimal, config-file only)
See all open source calendar tools at OSSAlt.com/categories/productivity.