This is a simple guide on how to synchronise contacts and calendars between a desktop operating system (Windows, macOS, Linux) and Android relying on a combination of Syncthing and Radicale. The main goal and idea is to have Radicale running on every system locally, so that you can connect with it even when there is no network connection available. This applies to both desktop operating systems and Android as well.
In Android settings, give Termux permission to access files and also exclude the app from battery optimisation. The first is required for Radicale to access the Syncthing folder, and the second for DAVxâ” to trigger Radicale sync when in background.
Inside Termux, update repositories first:
pkg up
Install Python:
pkg install python
Install Radicale:
pip install radicale
Install Vim:
pkg install vim
Of course, you can use another text editor of choice instead.
Create a new text file called radicale.sh at ~/.termux/boot:
Note: if Data Saver is enabled in the OS, you need to exclude DAVxâ” from it, or otherwise nothing will happen when trying to run the sync (despite the fact that it happens fully offline ).
While this method may sound complicated at first, I have been using it for years now with zero issues. I had also tried using DecSync (https://github.com/39aldo39/DecSync) before, however it proved to be very buggy for me, hence I switched to this method instead. The main advantage is that Radicale runs locally both on the desktop and Android, which makes it possible to add, edit, and delete items offline, and Syncthing will sync the changes once connected. Of course, as with any other type of sync, simultaneous modifications on multiple devices will lead to conflicts, so you mustnât edit the same events or contacts without syncing the previous changes first.
I also understand that this short guide assumes the user has already got some basic knowledge on how to install software and operate the command line. I may try to make the guide more beginner-friendly later on, but unfortunately Iâm very limited on time right now, so Iâve only wanted to lay out the basic steps to follow along.
I hope someone will find this guide useful .
PS Inside Termux, you can test the script simply by executing it manually first, e.g. sh ~/.termux/boot/radicale.sh in order to verify that it actually works while watching the output live before trying to start in on boot (and possibly debug any errors there).
I wasnât able to import my existing contacts and calendars into it (see https://github.com/39aldo39/Radicale-DecSync/issues/6, the issue is still open), and also DecSync has a problem of creating a vast and always growing number of tiny files (see https://github.com/39aldo39/DecSync/issues/2), which is a problem for Syncthing specifically, because it slows down synchronisation, especially on Android (11 and newer), where dealing with thousands of files is very slow due to FUSE.
On the other hand, Radicale by itself only stores and syncs actual calendar event .ics files and contact .vcf files without any additional metadata attached to them separately (as long as you ignore the cache files as recommended in the instructions).
Of course, if DecSync works for you, then Iâm not saying that thereâs anything wrong with using it, especially considering that itâs much easier to set up on Android.
Thank you again for the guide. It works (with a+x for .sh and pwd file creation)! )
What do you do to encrypt content of collections so other apps canât access it?
I couldnât easilty spot any config or plugin that enables it.
Reasoning
âAll filesâ permission on Android is somewhat more widespread than Contacts.
In my case, itâs:
Contacts is only 6 of 50 apps allowed
âFiles and mediaâ: 44 apps allowed out of 77
âAll filesâ: 7 apps (termux+tasker+syncthing+âfile managerââŠ)
And thatâs not counting âsystemsâ apps like all those ânearby shareâ etc that has âall filesâ access.
I donât think you can protect the data like that and still make it accessible to other applications. This is because the folder in question needs to be in a location that both Syncthing and Termux can read and write to.
Personally, Iâm not really worried about other apps that much. I always try to use free and open source applications whenever possible, and if not, I stick to using the big names, avoiding unknown, closed source ones. I do use full disk encryption on all my devices to protect them from unauthorised physical access.
I would like to thank you again for the guide, Iâm piloting it for several users though still having troubles with how to avoid âallow all of them to use battery without any limitsâ.
Re encryption - it looks like one can create needed âStorage pluginâ for Radicale similarly t what was done for ?esty.
Iâm not talking here about secure vault invisible to anyone, but at least not storing them in plain text in plain sight - similarly to what is done in KeePassDX where pwd DB is kept in encrypted manner in âpublicly accessibleâ space.
Hi @tomasz86,
very nice work. This is essentially what I was looking for, for a long time and is well presented for my level of knowledge.
However I am struggling to set up the android version.
At the point, where your âradicale.iniâ config comes into play, I dont know what to do. I cant find this file anywhere neither do I know how to create it. And if I just run it without a specification I cant get it to run the desired Syncthing Folder as its storage without crashing. Could you go a little bit into detail on the android installation? I would really love to make this work, since everything else is very smoothly running.
Obviously, you should use your preferred usernames and passwords here.
filesystem_folder = . makes Radicale store all files inside the collection-root folder in the same path as radicale.ini is located.
This is basically it, but if you still have problems, please share screenshots of your configuration, including the exact path and structure of your Radicale folder that you sync with Syncthing.
This is a really great idea, thanks so much for the guide. Unfortunately, termux can only be run from the primary user account. The bootstrap binaries have a hardcoded $PREFIX path that can not be installed to any other path than /data/data/com.termux/files/usr. I run multiple profiles on my phone, and leave the primary as bare as possible. As such, I canât run termux in that profile. There does seem to be ways to bypass this restriction via binary patching, but that also requires root. Does anyone know of alternative methods for running radicale on android?
Very interesting. Out of curiosity: why did you opt for Syncthing when Radicale is actually about syncing contacts and calendar? (I am using Davx5 on Android connecting to a Radicale instance on the linux desktop).
I just prefer to have everything synced via P2P and self-contained . No central server, etc. This is especially true, as I often need to operate with extremely poor Internet connectivity, or even no Internet at all.
Thank you, Tomasz, for your efforts! Since this seems to be the only solution for syncing calendars and similar data on Android and desktop without a central server and without relying on abandonware, I think it would deserve a dedicated wiki + forum. What do you think? For now, Iâll use the Syncthing forum.
I set up almost everything as described.
Added .Radicale.tmp-* to the Syncthing ignore list since I donât think it makes sense to sync those.
For a reason I couldnât find out, Radicale on Android doesnât update mtimes on its ics files, at least for me. Because of that, locally updated events whose ics file sizes didnât change (e.g., just moved to another day) were ignored by Syncthing. I cured this by adding
hook = touch --no-create "%(path)s"
to the [storage] section of the Radicale config file on Android. It works very well so far. Still feels weird that this was necessary at all. Could someone please check if this behavior is standard for Radicale on Android file systems or if I just did something wrong?
What I couldnât cure was that on Android, DAVx5 + Radicale take a looong time to sync my calendars (roughly 3 min for 10000 events on a Pixel 8). Every time, no matter how few changes I made. Sometimes I even got timeouts, but I think I have never lost any data.
Can I somehow help DAVx5 and/or Radicale identify the events that have changed? Do they really have to check everything every time? If this canât be changed, could I, at least with root access, use a faster file system somewhere on the Android device (ext4 instead of fuse)? Iâm aware these are no Syncthing questions even though theyâre on-topic for this thread.
Thank you for this guide, its working really well for me.
One thing I noticed is that if you delete a collection in Radicale on one device, Syncthing will refuse to delete the collection folder on your other devices because they still contain the ignored .Radicale.cache folder. Changing your ignore pattern to (?d).Radicale.cache should fix that.
At least on my Android device running LineageOS 22 (Android 15), Radicale is correctly updating mtimes.
Thanks for this detailed writeup, @tomasz86. I need some alternative because Iâve been using DecSync+Syncthing for years for my contacts and calendar, but it is abandoned and barely hanging on, with entries randomly disappearing.
Iâd like to try this, but really donât know if I am up for another Termux adventure. It just seems like way too many links in the chain. Why can neither Android or Thunderbird expose backend ics and vcf files that can be synced between devices with Syncthing? We had this kind of thing figured out decades ago and now have to make things complicated with so many needless SQLite databases and servers snooping on our data.
Okay, enough rant, but really, I would financially support a small project for a self-contained app or utility on each end to expose ics and vcf files that can be synced by Syncthing. Syncthingâs conflict avoidance is really adequate, if I have to manually resolve a conflict on a rare occasion, itâs not a big deal because they are human-readable.