Skip to main content

How to Self-Host Radicale: CalDAV/CardDAV Server 2026

·OSSAlt Team
radicalecaldavcarddavcalendarself-hostingdocker2026

TL;DR

Radicale (GPL 3.0, ~3K GitHub stars, Python) is the simplest self-hosted CalDAV/CardDAV server — sync your calendars and contacts across all devices without Google or Apple. It's a single Python process, stores data as plain files, and can be set up in under 5 minutes. iCloud+ charges $1-3/month just for sync storage. Radicale is free and stores your calendars and contacts on your own hardware as simple .ics and .vcf files you can read directly.

Key Takeaways

  • Radicale: GPL 3.0, ~3K stars, Python — CalDAV + CardDAV in one lightweight server
  • File storage: Calendars stored as .ics files, contacts as .vcf — human-readable, easily backed up
  • Multi-user: Each user gets their own calendars and address books
  • Rights management: Configurable per-user or per-collection permissions
  • vs Baikal: Radicale has no web UI (just protocol server); Baikal has a browser-based admin
  • Pairs well with: Nextcloud (built-in), standalone server, or alongside any mail setup

Part 1: Docker Setup

# docker-compose.yml
services:
  radicale:
    image: tomsquest/docker-radicale:latest
    container_name: radicale
    restart: unless-stopped
    ports:
      - "5232:5232"
    volumes:
      - radicale_data:/data
      - radicale_config:/config
    environment:
      - RADICALE_CONFIG=/config/radicale.cfg
    # Run as specific user:
    user: "1000:1000"

volumes:
  radicale_data:
  radicale_config:
docker compose up -d

Part 2: Configuration

# Create config file:
mkdir -p ~/.radicale

cat > /path/to/radicale_config/radicale.cfg << 'EOF'
[server]
hosts = 0.0.0.0:5232
max_connections = 20
max_content_length = 100000000
timeout = 30

[auth]
type = htpasswd
htpasswd_filename = /config/users
htpasswd_encryption = bcrypt

[storage]
filesystem_folder = /data/collections

[rights]
type = owner_only

[logging]
level = warning
EOF

Create users (htpasswd)

# Install htpasswd (apache2-utils) or use Docker:
# Create first user (creates file):
docker run --rm httpd:alpine htpasswd -nbB alice password123 >> users

# Add more users:
docker run --rm httpd:alpine htpasswd -nbB bob password456 >> users

# Copy to volume:
docker cp users radicale:/config/users

# Restart:
docker compose restart radicale

Part 3: HTTPS with Caddy

cal.yourdomain.com {
    reverse_proxy localhost:5232
}

Part 4: iOS / macOS Setup

Calendar (CalDAV)

iOS:

  1. Settings → Calendar → Accounts → Add Account → Other
  2. Add CalDAV Account
  3. Server: https://cal.yourdomain.com
  4. Username: alice
  5. Password: your password

macOS:

  1. System Settings → Internet Accounts → Add Account → Other
  2. CalDAV Account
  3. Account type: Advanced (to specify server URL)
  4. Server: https://cal.yourdomain.com
  5. Username: alice, Password: your password

Contacts (CardDAV)

iOS:

  1. Settings → Contacts → Accounts → Add Account → Other
  2. Add CardDAV Account
  3. Server: https://cal.yourdomain.com
  4. Username: alice, Password: your password

macOS:

  1. System Settings → Internet Accounts → Other → CardDAV Account
  2. Account type: Advanced
  3. Server: https://cal.yourdomain.com

Part 5: Android Setup

  1. Install DAVx⁵ from F-Droid or Google Play
  2. + → Login with URL: https://cal.yourdomain.com/alice/
  3. Enter username and password
  4. DAVx⁵ discovers all calendars and address books
  5. Select which to sync → toggle each calendar/address book

Calendar apps

AppPlatformCalDAV
DAVx⁵AndroidYes (sync layer)
Simple CalendarAndroidVia DAVx⁵
EtarAndroidVia DAVx⁵
ThunderbirdAllBuilt-in (no plugin needed)
EvolutionLinuxBuilt-in

Part 6: Thunderbird Setup

Thunderbird supports CalDAV/CardDAV natively (no plugin required since TB 78):

Calendar

  1. Thunderbird → Calendar → New Calendar
  2. On the Network → CalDAV
  3. URL: https://cal.yourdomain.com/alice/calendar-name/
  4. Enter credentials

Contacts

  1. Thunderbird → Address Book → New Address Book → CardDAV
  2. URL: https://cal.yourdomain.com/alice/contacts/
  3. Enter credentials

Part 7: Multi-User Rights Configuration

For shared calendars:

# /config/radicale.cfg — advanced rights config:
[rights]
type = from_file
file = /config/rights

# /config/rights file:
# Format: [user:collection_path] = permissions
# R = read, W = write (implies read)

# Alice can read/write her own collections:
[alice:alice/.*]
user = alice
permissions = RW

# Bob can read/write his own:
[bob:bob/.*]
user = bob
permissions = RW

# Alice can read Bob's shared calendar:
[alice_reads_bob_shared]
user = alice
collection = bob/shared-calendar
permissions = R

# Everyone can read public holiday calendar:
[public_holidays]
user = .*
collection = .*/holidays
permissions = R

Part 8: Collection URLs and Structure

Radicale collections follow this URL pattern:

https://cal.yourdomain.com/{username}/{collection-name}/

Examples:
https://cal.yourdomain.com/alice/personal/          # Alice's personal calendar
https://cal.yourdomain.com/alice/work/              # Alice's work calendar
https://cal.yourdomain.com/alice/contacts/          # Alice's contacts
https://cal.yourdomain.com/alice/family-shared/     # Shared family calendar

Create a collection via curl

# Create a calendar collection:
curl -u alice:password \
  -X MKCOL "https://cal.yourdomain.com/alice/work/" \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0" encoding="utf-8"?>
<mkcol xmlns="DAV:" xmlns:C="urn:ietf:params:xml:ns:caldav">
  <set><prop>
    <resourcetype><collection/><C:calendar/></resourcetype>
    <displayname>Work</displayname>
  </prop></set>
</mkcol>'

Maintenance and Backup

# Update:
docker compose pull
docker compose up -d

# Backup (just copy the data directory — it's plain files):
tar -czf radicale-backup-$(date +%Y%m%d).tar.gz \
  $(docker volume inspect radicale_radicale_data --format '{{.Mountpoint}}')

# The backup contains:
# collections/alice/personal/event1.ics
# collections/alice/contacts/contact1.vcf
# etc. — all human-readable

# Logs:
docker compose logs -f radicale

# Test CalDAV connection:
curl -u alice:password \
  -X PROPFIND "https://cal.yourdomain.com/alice/" \
  -H "Depth: 1"

See also: Baikal (CalDAV/CardDAV with web admin UI)

See all open source calendar and contacts tools at OSSAlt.com/categories/productivity.

Comments