November 16, 2019 · software linux selfhost

Self-Hosting Part 3: WebDAV Server

Introduction

This is Part 3 of the Self-Hosting Series, a guide on how to run a CalDAV and CardDAV server! As always, you can check out the rationale for this series in Part 1: Why I'm Ditching iCloud. In this guide, we will be replacing iCloud Calendar, iCloud Contacts and iCloud Reminders, using the Python Radicale package.

Server Installation

We will be using the root account for all the commands in this guide. Start by dropping into a root shell. Then install the Radicale package from the PyPI servers, as well as the password hashing tools used for authentication.

# Drop into a root shell
sudo su
python3 -m pip install --upgrade radicale[bcrypt]
apt install apache2-utils

Create a seperate radicale user, for running radicale:

useradd --system --home-dir / --shell /sbin/nologin radicale

Next, generate the users file which will contain the accounts that will be accessing this server:

mkdir /etc/radicale
touch /etc/radicale/users
chown radicale:radicale /etc/radicale/users
chmod 400 /etc/radicale/users

To add a user run the following command, which will prompt for the password.

htpasswd -B /etc/radicale/users username_here

Create the directory which will store our CalDAV and CardDAV collections:

mkdir -p /var/lib/radicale/collections && chown -R radicale:radicale /var/lib/radicale/collections

Next, create the radicale config file, with the following defaults:

# nano /etc/radicale/config

[server]
max_connections = 20
# 100 Megabyte
max_content_length = 100000000
# 30 seconds
timeout = 30

[auth]
# Average delay after failed login attempts in seconds
delay = 1

type = htpasswd
htpasswd_filename = /etc/radicale/users
# encryption method used in the htpasswd file
htpasswd_encryption = bcrypt

Now we can configure a systemd service, which will automatically start radicale upon boot:

# nano /etc/systemd/system/radicale.service
[Unit]
Description=A simple CalDAV (calendar) and CardDAV (contact) server
After=network.target
Requires=network.target

[Service]
ExecStart=/usr/bin/env python3 -m radicale
Restart=on-failure
User=radicale
# Deny other users access to the calendar data
UMask=0027
# Optional security settings
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
PrivateDevices=true
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
NoNewPrivileges=true
ReadWritePaths=/var/lib/radicale/collections

[Install]
WantedBy=multi-user.target

Finally, we can enable and start the radicale service. Note that radicale will only serve localhost at this point.

# Enable the service
systemctl enable radicale
# Start the service
systemctl start radicale

For general access, set up a reverse proxy such as nginx in front of the radicale server. Here is a sample nginx configuration.

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	ssl_dhparam /etc/ssl/certs/dhparams.pem;
	include snippets/lets_encrypt.conf;
	server_name caldav.naut.ca carddav.naut.ca;
	location / {
		proxy_pass http://127.0.0.1:5232;
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
	}
}

Fix Contacts

In some cases, you will find that your contacts aren't being synced. To fix this, open your web browser and navigate to the Radicale server. On the login screen, type in the username and password you created above. Click Create new addressbook or calendar, and create a collection of type addressbook, using the name "Contacts". Finally, on your device, delete and re-add the Contacts server.

Client Connection

You can now connect to your server by going to System Preferences, Internet Accounts, and then adding both a CalDAV and CardDAV account!

settings-1