Self-hosting address books

I wanted to self-host a server to sync my contacts across devices. One that uses an open protocol (CardDAV) and easy to self-host. Radicale was very easy to set up on Arch, but davx5 client (Android) couldn't sync the changes. Xandikos works flawlessly in combination with nginx. The package is in Arch repos but required some assembly:

# (as root)
mkdir /var/lib/xandikos /etc/xandikos
chown xandikos:xandikos /var/lib/xandikos
useradd -U -s /usr/bin/nologin xandikos
htpasswd -c /etc/xandikos/htpasswd usr

/etc/systemd/system/xandikos.service, ugly hack here because Xandikos can't use an existing socket:

Description=Xandikos CalDAV/CardDAV server
ExecStart=/usr/bin/xandikos \
  -d /var/lib/xandikos \
  --current-user-principal=/usr \
  -l /run/xandikos/socket
ExecStartPost=/usr/bin/sh -c 'sleep 2; chmod g+w /run/xandikos/socket'


upstream xandikos {
    server unix:/run/xandikos/socket; # nginx will need write permissions here
server {
    server_name home-dav;
    # Service discovery, see RFC 6764
    location = /.well-known/caldav {
        return 307 $scheme://$host/user/calendars;
    location = /.well-known/carddav {
        return 307 $scheme://$host/user/contacts;
    location / {
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
        proxy_buffering off;
        proxy_pass http://xandikos;
        auth_basic "Login required";
        auth_basic_user_file /etc/xandikos/htpasswd;

Add this line to nftables ruleset to allow sync on LAN only:

tcp dport 8099 ip saddr { } ip daddr accept comment "Accept connections to xandikos behind nginx"

To sync to local directories I use vdirsyncer, on Android - davx5 (in F-Droid repos).