How to Sync Radicale with iCloud Calendar

By Rida F'kih · August 11, 2026

You run Radicale because your calendar should live on your own hardware. Then you pick up your iPhone, and none of it is there.

Keeper.sh signs into Radicale and iCloud and keeps copies of your events in step.

What does this actually do?

Add an event in Radicale and a copy appears in iCloud, which means it appears on your iPhone. Move it, the copy moves. Delete it, the copy goes.

By default the copy is a block of busy time, not a readable event. Your notes do not come along.

Copies travel one way per connection: Radicale to iCloud, or iCloud to Radicale. Want both? That is two connections, not a single "two-way" switch.

Can Keeper.sh reach a Radicale on your home network?

You need a username and password from your htpasswd file, an Apple Account with two-factor login on, and an account on keeper.sh. You also need Radicale answering on an address Keeper.sh can reach, and that is the part to settle first.

Most Radicale instances sit on a home network — 192.168.1.x, a .local hostname, or localhost:5232.

On hosted Keeper.sh, private addresses are refused and you cannot change that. Your Radicale needs to be reachable from the public internet, through a domain with a reverse proxy or a tunnel. If you will not expose it, run Keeper.sh yourself on the same network instead.

The setting behind this is BLOCK_PRIVATE_RESOLUTION. It is off by default, but deploy/compose.yaml turns it on for the api and cron services. PRIVATE_RESOLUTION_WHITELIST is the exemption list:

BLOCK_PRIVATE_RESOLUTION=true
PRIVATE_RESOLUTION_WHITELIST=192.168.1.50,radicale.local,10.0.2.12

Set both on api and cron, whitelist the exact host and port you will paste into the form, and restart both. Skip it and the connect page says Failed to discover calendars, without telling you why. The reason only appears in the logs.

How do you connect Radicale?

From the dashboard, click Import Calendars, then Connect CalDAV Server at the bottom. Radicale has no button of its own, and does not need one.

The page is headed Connect CalDAV Server and has three boxes:

  • CalDAV Server URL — your Radicale address, like https://radicale.example.com
  • CalDAV Server Username — your username from htpasswd
  • CalDAV Server Password — the matching password

Start with the plain address. If nothing turns up, use your user collection root instead — https://radicale.example.com/username/, with the trailing slash. Radicale's htpasswd backend puts your password on the wire with every request, so put HTTPS in front of it.

Click Connect. Every calendar found is imported at once and you land in a short setup flow. Task lists and address books are skipped.

How do you connect iCloud?

Apple will not let outside apps sign in with your normal Apple password, which opens your photos, purchases and Find My. You generate a separate app-specific password instead, which only reaches your calendar.

Keeper.sh's connect page lists the steps, matching Apple's own instructions:

  1. Navigate to iCloud Apple ID
  2. Sign in with your Apple ID
  3. Select "App-Specific Passwords"
  4. Click the "+" next to "Passwords"
  5. Label and generate the password, then copy it
  6. Paste the app-specific password below

That section only appears if two-factor login is on, and Apple shows the password once.

Then click Connect iCloud on Import Calendars. The page is headed Connect Apple Calendar, and has two boxes:

  • Apple ID — your Apple sign-in address
  • App-Specific Password — the one you just generated

No server address is needed here.

How do you tell Keeper.sh which way events travel?

Setup asks four questions, word for word:

  1. Which calendars would you like to configure? Tick the ones you want now.
  2. Rename Your Calendars. Radicale collections often arrive named after directories. Renaming only changes what you see in Keeper.sh.
  3. Where should 'Personal' send events? Tick iCloud, and copies start appearing on your phone.
  4. Where should 'Personal' pull events from? Tick iCloud here for the reverse.

Each tick is one connection. Change any of it later from the calendar under Calendars, in the Send Events to Calendars section.

Will the copies carry real event titles?

Open the calendar under Calendars and find Sync Settings. Three switches decide what travels: Sync Event Name, Sync Event Description and Sync Event Location.

Calendars added through Import Calendars arrive with all three off, at both ends, so Radicale and iCloud exchange opaque blocks. Turn Sync Event Name on for real titles, shaped by the Event Name box, which understands {{calendar_name}} and {{event_name}}.

On Keeper.sh this is a Pro feature — the dashboard says Advanced sync settings are a Pro feature. Run Keeper.sh yourself and every user on the instance gets it. Below, Exclusions can drop Exclude All Day Events.

How fast do changes show up?

Keeper.sh reads both calendars every minute, on every plan. Getting that change onto the other calendar depends on the plan: up to thirty minutes on free, about a minute on Pro and on your own instance.

If you are mirroring Radicale so your phone knows you are busy, thirty minutes changes nothing. If people book you through a scheduling link, it is too slow.

What does not come across?

Guest lists, video call links and reminders do not travel at all, so a copied meeting is a block of time rather than a working invite. Guest lists are read only to show you invitations you have not answered yet.

Keeper.sh also looks at a fixed stretch of time — from a week ago to two years ahead. A one-off event further out is not copied. A repeating event that began before the window is still picked up, so its dates inside the window survive.

What goes wrong, and what does it look like?

The page says "Invalid credentials". The server was reached and rejected the sign-in. On the Radicale side, check the details against your htpasswd file. On the iCloud side, the normal Apple password was pasted, or the app-specific one has been cancelled.

The page says "Failed to discover calendars". This means something different. Keeper.sh never got a usable answer from that address, so the credentials were never tested. Check the address for a typo, confirm Radicale is running, and if you self-host, check the private-address setting above.

The page says "No calendars found". Your credentials worked, but Keeper.sh found nothing to import at that address. This is when to try https://radicale.example.com/username/ with the trailing slash.

One bad repeating event freezes a whole calendar. Not one missing event — everything stops updating. Keeper.sh refuses to work through a repeating series producing more than 10,000 dates in two years, and today that stops the whole calendar. Delete the runaway event and it catches up.

Events disappear from iCloud that still exist in Radicale. Keeper.sh reads the whole calendar each round. If a proxy in front of Radicale caps how many items come back in one response, Keeper.sh sees a shorter calendar and removes the difference.

There is no "sync now" button. You wait for the next round.

To tell which half of a problem you have, open View Events. Events listed there but missing in iCloud is a delivery problem. Events missing there is a Radicale problem.

What does the free plan cover?

Two calendar accounts and three connections. Radicale is one account no matter how many collections it holds, and iCloud is the second, so this pairing uses both. Adding Google later means upgrading.

Three connections covers both directions with one spare, and there is no cap on how many calendars an account brings in.

Would you rather run Keeper.sh yourself?

You already run Radicale, so this will not frighten you, and for a calendar server on your own network it is often the better fit. Keeper.sh is open source under AGPL-3.0. Run it yourself and every user on the instance gets Pro behaviour, with nothing held back.

It is a Docker Compose stack with Postgres and Redis behind it, documented in the repository. Running it beside Radicale is what makes PRIVATE_RESOLUTION_WHITELIST useful, and means you never expose Radicale at all.

The cost is real. Another service to upgrade, another database to back up, another thing that pages you when it stops.

How do you cut access off?

Delete the app-specific password at Apple, or delete the account under Calendar Sources in the dashboard.

Keeper.sh stores both passwords in a form it can read back, because this kind of connection sends the password on every request. They are encrypted first, with a key you control if you self-host.

Can Keeper.sh use cookies for analytics?