0. Introduction
Recently, I found it more and more troublesome that I couldn’t synchronize my personal calendar(s) across all my devices. Originally, I’ve been running a SyncML server for that purpose, as it was conveniently integrated with my mail server suite. Many years ago I used a Nokia E72 “smart” phone *cough* to synchronize against that server. There is even an app for it on Android called [Synthesis], which I am currectly using on modern Android. However, I could not find any software nor software plugins for SyncML for any one of my Desktop operating systems (WinXP x64, RedHat Enterprise Linux 8 & FreeBSD 12/13). Seems SyncML never really made it onto the desktop. And where it did – like in the form of the Funambol plugin for Mozilla Thunderbird – it’s been long abandoned and no longer works with modern software. Heck, it doesn’t even work with TB 52.9 on XP / XP x64 anymore, it’s too old for even that!
At first I tried to bring SyncML and modern CalDAV/CardDAV solutions together by running my own bridge server using [SyncEvolution] on Linux. In essence, I would run my own DAV server and bridge it to my SyncML server in the background. All of it over HTTPS. DAV as a protocol, originally called WebDAV (Web Distributed Authoring & Versioning) is a series of extensions to HTTP/HTTPS that can be used for sharing and collaboratively working on certain data sets. Like version control for software development (cvs+https://, svn+https:// etc., as opposed to doing it over e.g. svn+ssh://). CalDAV and CardDAV are just altered versions used for calendar, tasks and contact information data.
Unfortunately, that bridge thing did not work. While SyncEvolution can do it the other way around, running as a SyncML server and linking it to a CalDAV/CardDAV backend, it can not run e.g. a CalDAV server and bridge it to a backend SyncML one, like it is in my case.
Actually, the original developer told me it could, but I just didn’t find any way to do so, even with the latest version.
So, I gave up on the whole idea, when user M477 on the XIN IRC chat suggested just running a DAV server on my stoneage Windows 2000 Server machine directly. I had thought that to be an exercise in futility, but he proved me wrong! This can indeed be done, and when combining the Radicale CalDAV/CardDAV server with modern HTTPS using my own OpenSSL + stunnel backports it can satisfy the security requirements of modern client software as well!
1. The server software
As for software, some pretty old versions are required, at least partially. I’m using Python 2.7.10, the Radicale 1.1.7 DAV server and as mentioned, my own backport of relatively modern OpenSSL 1.1 and stunnel for bridging HTTPS to a localhost HTTP socket (unpack the files below with [7-Zip]):
1a. Python
Setting up Python is straight-forward, so I won’t discuss this here. Just run the installer and optimally install it into a path not containing any whitespaces.
1b. Radicale
1b1. Installation and basic configuration
Unpack it and put it wherever you wish, e.g. X:\servers\radicale\. It’s all written in interpreted Python language, so to execute it interactively for tests, you’d do something akin to this:
CD /D X:\servers\radicale\
"C:\Program Files\Python27\python.exe" .\radicale.py
I do suggest creating a restricted user to run it as though, just to make sure no part of the software unnecessarily runs with higher privileges. If you wish to create such a user including its user profile folder without having to log in with it interactively, you can run the following as an administrative user on a cmd terminal after regular user creation via Administrative Tools in the system control panel:
runas.exe /profile /user:<username> cmd.exe
This’ll create the profile and give you a terminal where you can work as the target user to set things up. If you’re authenticating against a domain controller’s ActiveDirectory, do it like this:
runas.exe /profile /user:<domainname>\<username> cmd.exe
Note there is a file called config coming with Radicale. This will be expected at the UNIX-style path ~/.config/radicale/config. Python translates the ~ home directory shorthand to %USERPROFILE% on Windows transparently, so pre-create the folders there and copy the config file to that location for the user which will be expected to run the software: %USERPROFILE%\.config\radicale\config. Slash-to-backslash translation will also be done by Python internally, so no need to change the conventions in config.
Edit the config file with your favorite text editor, and take a look at the options hosts, daemon, ssl & realm in the [server] block for now. I’d suggest the following settings:
[server]
hosts = 127.0.0.1:5232
daemon = False
ssl = False
realm = CalDAV/CardDAV
Since we’re not going to rely on the old SSL implementation of Python, the server should listen only on localhost with no encrpytion instead of on the actual, public network. Also, it cannot run as a “daemon”, which is a type of background service on UNIX and Linux, specifically. As for the realm option, you can just enter any arbitrary string. Its value will be presented to you likely as a dialog window title when the server asks your calendar/tasks/contacts client for login information.
1b2. Authentication
Radicale v1 supports multiple authentication backends by default. Newer versions 2 and 3 need additional plugins to gain the same flexibility, but with this version, a lot of them are bundled, like LDAP, IMAP and the file-based htpasswd. Look for the authentication block [auth].
htpasswd-style authentication is probably the easiest. This means creating a users & passwords file using the command line program htpasswd.exe, while picking a compatible hash function that works with Python 2.7.10 (e.g. SHA1). For help on usage, just run htpasswd.exe --help on a cmd terminal with htpasswd.exe on your search path. Creating a new user+password file with SHA1 password hashes is as easy as this:
htpasswd.exe -c -s <passwdfile> <username>
In config, you’d then specify it like this:
[auth]
type = htpasswd
htpasswd_filename = ~/.config/radicale/htpasswd
In my own case, I am running an eMail server with IMAPv4 on the same host, so I chose the IMAP authentication backend instead. As it’s running locally, no SSL is required when authenticating against it:
[auth]
type = IMAP
imap_hostname = localhost
imap_port = 143
imap_ssl = False
1b3. Rights management
Next, look at the [rights] block. For simple setups, where each user only needs to access their own calendar and contacts, I’d suggest setting the rights management type as such: type = owner_only. If you require more complex setups with certain users sharing specific calendars & contacts, I suggest reading up on the from_file value and its implementation. It’s not exactly trivial, but here’s the [documentation]!
1b4. Data storage
The most well-supported way of storing the data on the server side is to do so as such text files. Continue to the [storage] block in config. Let me suggest the following directives:
[storage]
type = filesystem
filesystem_folder = ~/.config/radicale/db
Note that you need to create the folder %USERPROFILE%\.config\radicale\db\ in advance! Also make sure the user who is supposed to be running Radicale has write access to it.
1c. stunnel
Full stunnel documentation with examples towards the end can be found [here]. Documentation on my own Windows 2000 backport can be found [here]. For now, let’s just assume you won’t be changing Radicale’s TCP socket, so it’ll run on localhost:5232. Then, a proper service definition in config\stunnel.conf would be like the following, assuming your public server IP address were 233.204.248.135:
[cdav]
accept = 233.204.248.135:5232
connect = 5232
cert = Your-SSL-certificate.pem
key = Your-SSL-certificate-private-key.pem
Naturally, you’d need to create SSL certificates first. For this I suggest [Let’s Encrypt] if you don’t have any server-side SSL implemented yet. Their certificates are trusted by all modern software vendors, so it’s a good pick when working with modern client software.
1d. instsrv & srvany
Those two are for installing and running interactive programs such as Python as background system services. This is optional, but I’d recommend doing so. Service installation works as follows on a cmd terminal, assuming instsrv.exe is on your search path and srvany.exe is in %WINDIR%\system32\:
instsrv.exe "<service name>" %WINDIR%\system32\srvany.exe
So, e.g.:
instsrv.exe "Radicale CalDAV and CardDAV server" %WINDIR%\system32\srvany.exe
Required system service properties are then edited in the system registry using regedit.exe. Please be careful with that! Look for a registry key named after the service name you just picked, e.g.:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Radicale CalDAV and CardDAV server\
There need to be three sub-keys: Enum, Parameters and Security. If Parameters doesn’t exist yet, create it, then enter it. Now, here you’ll create three string values called AppDirectory, Application and AppParameters. The first is the current working directory of the server. You’ll enter the path to Radicale as its value. The second is the full path to the Program being called. Enter the full path to python.exe here. And the last is a list of parameters to be passed to the invoked program. In our case this is the full path to the Radicale main program radicale.py. So, for example:
| Property |
Value |
AppDirectory |
X:\servers\radicale |
Application |
C:\Programs\Python27\python.exe |
AppParameters |
X:\servers\radicale\radicale.py |
Also, don’t forget to go to Win+r, run services.msc and reconfigure that service by setting the user to run the service as, if you’re using a dedicated account for it!
Before starting the service, you should run it interactively on a cmd terminal (e.g. the one you launched in 1b1. with runas.exe). To do that, just replicate the Registry settings on a terminal:
CD /D "X:\servers\radicale\"
"C:\Programs\Python27\python.exe" "X:\servers\radicale\radicale.py"
Make sure it works and you can reach it with a browser. Following the examples above, you’d just need to connect to https://233.204.248.135:5232, and you should get a login prompt. Test authentication, and if it breaks, take a look at the output on the terminal to debug it! The result should be either a blank, white page or alternatively a “Radicale works” message. Once you’re certain it works so far, terminate the program and start the configured system service in its stead, then test again.
2. The client software
In my case, I decided to use three clients: First, [Thunderbird] (both old and new) on Microsoft Windows, Linux and FreeBSD. Second, [KOrganizer] on Linux. And finally, [DAVxâĩ] on Google Android.
When configuring a client for a server-side calendar, the full URL would be in the format https://<server socket>/<user name>/<collection>. A “collection” is essentially a contacts list or a calendar+tasks list. You can pick its name freely when initially creating the collection. E.g. you can just call it “calendar” as well. The user name should match your login credentials.
For example: https://233.204.248.135:5232/johndoe/calendar. Let’s say you own mydomain.org, which points to 233.204.248.135, then of course the following would be much prettier, and won’t trigger any SSL warnings or errors, as long as your SSL certificate’s common name is mydomain.org:
https://mydomain.org:5232/johndoe/calendar
In Thunderbird, just switch to the calendars tab and press the “+” symbol on the left pane to add a new one. Select “On the network”, then enter your user name into the “User name” as well as the URL into the “Location” fields. You may also check “Offline Support” to make sure you can see the calendar and get notifications even while your Radicale server is down. Continue and you’ll be promped for a password. Authenticate, then scan for calendars, select the server’s offer and you’re done!
Once the calendar has been created on the server side, you can also import any calendar backups you may have (e.g. from Google Calendar or other software) onto the server. Thunderbird supports the very common iCalendar format (.ics) for this. Wait for the entries to be uploaded, and you should be set!
Here are some example screenshots of two versions of Thunderbird as well as KOrganizer working with a Radicale Server running on ancient Windows 2000, connected via TLSv1.2. Note that there is an additional, local-only calendar added to the mix on Linux (click to enlarge pictures):
-
-
Thunderbird 91.7 on Linux (Color import didn’t work?)
-
-
Thunderbird 52.9 on XP x64
-
-
KOrganizer 5.18 on Linux
As for Android, I decided to use the DAVxâĩ app, as mentioned. Setup is pretty similar to the desktop programs, here are some sample screenshots:
-
-
DAVxâĩ splash screen
-
-
DAVxâĩ CalDAV profile
-
-
Android 8 calendar
Note that Apple iOS supports this natively! CardDAV for contact synchronization should be found under Settings / Contacts / Accounts / Add Account / Other, “Add CardDAV Account” and CalDAV for calendar synchronization under Settings / Calendar / Accounts / Add Account, “Other”, “Add a calendar account”, “Add CalDAV Account”. I have not tried this though, as I do not have an iPhone or iPad.
So while I can’t really use good old SyncML in a cross-platform context, this still enables me to share a centralized set of self-hosted contacts, tasks and calendars for me or even for multiple users on an ancient server. While security may be quite debatable in this case, at least the cryptographic part is by no means ancient for both login and data transfer.
While the SyncML server will remain online, XIN eMail server users may now additionally request CalDAV/CardDAV access for synchronizing their calendars, tasks and contacts to an ancient museum server, without having to rely on “the cloud” to hold that data. 