Xandikos CardDAV/CalDAV server

Posted on Wed 01 September 2021 in android

In looking to moving my phone to LineageOS, I've started thinking about moving my mail, contacts and calendar data to my own server. After researching solutions for a while, I decided to try out xandikos. A simple Python carddav/caldav server intended for a single user with a basic feature sit and Git backend.

Setup

For my setup I have chosen to use my existing nginx setup (for SSL/auth) and uwsgi for running xandikos. On Arch Linux you'll need uwsgi, uwsgi-plugin-python and xandikos installed. Then a xandikos user has to be created as the package provides none:

useradd xandikos -d /var/lib/xandikos

Create a uwsgi configuration file named: /etc/uwsgi/xandikos.ini

[uwsgi]
socket = /run/uwsgi/xandikos.sock
chmod-socket=660
uid = xandikos
gid = http
master = true
cheaper = 0
processes = 1
plugin = python
module = xandikos.wsgi:app
umask = 022
env = XANDIKOSPATH=/var/lib/xandikos/collections
env = CURRENT_USER_PRINCIPAL=/user/
env = AUTOCREATE=defaults

Then simply enable it with systemctl enable --now uwsgi@xandikos

For nginx you'll need this location snippet:

location / {
    include uwsgi_params;
    uwsgi_pass unix:/run/uwsgi/xandikos.sock;
}

This should set up xandikos running with uwsgi and a reverse proxy for SSL / authentication and using a unix socket.

Authentication

For authentication I have chosen to use client certificate authentication with the reasoning that it's probably more secure then username/password authentication and easy to deploy.

I use step-cli for creating certificates as it's a lot more user friendly then using just openssl. For authentication you'll need to create a new CA and a client certificate.

step-cli certificate create --profile root-ca "client auth CA" root_ca.crt root_ca.key
step-cli certificate create caldav.vdwaa.nl caldav.vdwaa.nl.crt caldav.vdwaa.nl.key \
    --profile leaf  \
    --ca ./root_ca.crt --ca-key ./root_ca.key --bundle --no-password --insecure --not-after "$(date --date "next year" -Iseconds)"

In your nginx configuration:

ssl_client_certificate /etc/nginx/rot_ca.crt;
ssl_verify_client on;

Generate a pcks#12 container for importing the client certificates in caldav/carddav clients:

step-cli certificate p12 caldav.vdwaa.nl.crt caldav.vdwaa.nl.key --ca root_ca.crt

Note that there are some caveats with client certificate authentication, as the certificate expires in a year and needs to be revoked using a CRL which requires additional configuration in nginx.

Clients

For setting up caldav/carddav on my phone I use davx5, to get it up and running you'll need to import your certificates in android. Go to Settings => Encryption & credentials => click User credentials to import your pkcs#12 container.

In thunderbird it's similar, you will need to import the pkcs#12 container for thunderbird to do client certificate authentication. In thunderbird you add the calendar by only specifying the location as https://caldav.vdwaa.nl/user/calendars/calendar/, the username field can be left empty.

Migrating Google data

To migrate Google contacts to my own carddav server, I configured the contacts provider in davx5 and then in Google contacts settings: Export => Export to .vcf file and then Import => .vcf file => select the davx5 address book.

The same can probably be done for Google calendar but I haven't tested it.

For Holiday calendars which are usually shown in Google calendar, I've used Apple's public calendar ics files for example for the Netherlands.