Radicale for calDAV and cardDAV storage

Radicale is a self-hosted calendar and contact solution that is “lightweight solution, easy to use, easy to install, easy to configure.”

I can finally dump my NextCloud, which was a sprawling mess of PHP scripts. Managing a NextCloud instance over a long period of a time requires the sysadmin to be mindful of the stateful configuration, which can only be upgraded one major version at a time.

I stumbled over Radicale a couple years ago right after I had spent an entire day writing a playbook to build a dockerless NextCloud container. I should have switched immediately, I’ve wasted numerous hours over that period making sure my container was up to date, or needlessly fiddling with settings just to feel like I had a handle on how the thing was going to operate.

Running radicale on NixOS:

service.radicale = {
  enable = true;
  settings = {
    server = {
      hosts = [ "" "[::]:5232" ];
    auth = {
      type = "htpasswd";
      htpasswd_filename = "/etc/radicale/users";
      htpasswd_encryption = "bcrypt";
    storage = {
      filesystem_folder = "/var/lib/radicale/collections";

Nginx configuration snippet from:

locations."/radicale/" = {
  proxyPass = "";
  extraConfig = ''
    proxy_set_header X-Script-Name /radicale;
    proxy_pass_header Authorization;

Creating my account after nixos-rebuild switch:

nix-shell -p apacheHttpd --run "htpasswd -B -c /etc/radicale/users bleetube"

The web interface is dead simple and let’s you create, import, or export calendars or addressbooks. I exported the vcf addressbook and ics calendar from my NextCloud instance and imported them into Radicale. The UI gives you URIs for the calendar or contacts, and I pasted that in along with my username in the relevant add dialog in Thunderbird.

Likewise, I added the account in davx5 on Android using the first “Login with URL and user name” option. For the URL this time, I appended my username, so it was https://example.com/radicale/myusername and davx was able to sync both the calendar and the contacts from that endpoint.