Synchronizing iCloud Calendar

The Problem
A lot of my workflow is terminal-based. My email client, text editor, music player, calendar and IRC client are all terminal applications. My family has a shared calendar wherein all the events that concern members of the family are stored. However, I’ll frequently waste time doing something like this.
Open up my email
I’ll open up mutt to see if there have been any new events that are created. New events are forwarded to my inbox.
.ics
file
Download and import a A convenient .ics
file is always attached to any automatic event emails. I’ll
manually save and import these into Khal.
All this is very tedious. I needed to find some way to be able to automate this process. That’s when I found out about vdirsyncer - a program that automatically syncs your iCloud calendar events.
Configuring Vsyncdir
I’d simply add a configuration file, telling Vsyncdir a few important details.
- Where to fetch the events from.
- The calendar ID (since you can have multiple iCloud calendars).
- iCloud authentication details - as the calendar is private.
- Where to store the events
All in all, it looks like this. Sensitive information has been redacted for security purposes.
[general]
status_path = "~/.local/share/vdirsyncer/status/"
[pair family]
a = "family_local"
b = "family_remote"
collections = ["4138f409266b0ef84e8ccc6a2153c5ae9c12e5a345e61cad05db17cc05430a3a"]
[storage family_local]
type = "filesystem"
path = "~/.calendars/icloud/"
fileext = ".ics"
[storage family_remote]
type = "caldav"
url = "https://caldav.icloud.com/<USER_ID>/calendars/<CALENDAR_ID>/"
username = "<ICLOUD EMAIL>"
password = "<ICLOUD PASSWORD>"
Syncing remote data
After a configuration file has been defined, we can actually start the synchronization process. It’s a matter of just discovering the remote calendar identifier(s) and then following up by syncing the remote calendar data using Vdirsyncer.
Discover and synchronize as follows.
vdirsyncer discover && vdirsyncer sync
It may also be handy to have this linked up to a Systemd process. For example, on my server, I have the following setup.
I have a timer that is linked to the synchronization of common tasks such as reloading emails and calendar events:
[Unit]
Description=Periodically synchronize remote data
Requires=mbsync.service
Requires=icloud.service
Wants=network-online.target
After=network-online.target
[Timer]
OnStartupSec=1m
OnUnitActiveSec=3m
Unit=mbsync.service
[Install]
WantedBy=timers.target
This is then “linked” to the following service files.
Get recent iCloud photos
[Unit]
Description=Periodically synchronize icloud data
AssertPathExists=/run/media/ssd/icloud/
AssertPathExists=%h/.calendars/icloud
Wants=photos.timer
[Service]
type=oneshot
ExecStart=/usr/bin/icloudpd --directory /run/media/ssd/icloud --username <email> --password <password> --library "PrimarySync" --recent 10 --notification-email joshuarose@gmx.com
TimeoutSec=300
[Install]
WantedBy=default.target
Get new calendar events
[Unit]
Description=Periodically synchronize icloud calendar data
AssertPathExists=%h/.local/share/vdirsyncer/status
AssertPathExists=%h/.calendars/icloud
Wants=sync.timer
[Service]
type=oneshot
ExecStart=/usr/bin/vdirsyncer sync
TimeoutSec=500
[Install]
WantedBy=default.target
.ics
data with Khal
Displaying Khal does know how to display .ics
files, but it takes a bit of
hand-holding. Here’s what my Khal configuration looks like:
[calendars]
[[icloud]]
path = ~/.calendars/icloud/<CALENDAR_ID>
Then once you open Khal you should be seeing the same events that are in your iCloud calendar. Here’s what it looks like for me:
