CardDAV, CalDAV and WebDAV

In part III of this series (s. part I and part II) I’m going to highlight how I installed a Cal-/CardDAV and WebDAV server on my Pi. This will require valid certificates again (s. here for help).

Please note: this setup is for internal use only - do not expose it to the internet!

WebDAV

Let’s start with WebDAV. We’ll make use of nginx to provide the WebDAV service and apache2-utils to create the user/password file:

sudo apt install nginx libnginx-mod-http-dav-ext apache2-utils

We also need some directories to hold our WebDAV root. I’ve chosen my external NVME disk for that. Your setup might differ, i.e.:

ROOTPATH=/data/data
sudo mkdir -m 750 -p ${ROOTPATH}/davshares/root
sudo mkdir -m 750 ${ROOTPATH}/davshares/tmp
sudo chown www-data:www-data ${ROOTPATH}/davshares/root ${ROOTPATH}/davshares/tmp

Let’s create a user:

sudo htpasswd -c ${ROOTPATH}/davshares/davusers.dav myuser
sudo chmod 640 ${ROOTPATH}/davshares/davusers.dav
sudo chgrp www-data ${ROOTPATH}/davshares/davusers.dav

Only thing missing now is the nginx configuration. It should look something like this:

/etc/nginx/sites-available/mynginxconfig:
-----------------------------------------
# Redirect HTTP to HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name <YOUR_SEVER_NAME>;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;

    server_name <YOUR_SEVER_NAME>;

    # Specify SSL config when needed
    ssl_certificate </PATH/TO/YOUR/CERT.pem>;
    ssl_certificate_key </PATH/TO/YOUR/KEY.pem>;
    add_header Strict-Transport-Security "max-age=31536000;";

    client_max_body_size 525M;

    # webdav config
    location ^~ /dav/ {
        if ($request_method = MKCOL) {
        rewrite ^(.*[^/])$ $1/ break;
        }

        root <ROOTPATH>/davshares/root;
        client_body_temp_path <ROOTPATH>/davshares/tmp;
        dav_methods PUT DELETE MKCOL COPY MOVE;
        dav_ext_methods PROPFIND OPTIONS;
        create_full_put_path on;
        client_max_body_size 20M;

        # Basic authentication setup
        auth_basic "restricted";
        auth_basic_user_file <ROOTPATH>/davshares/davusers.dav;

        # Deny all access unless authenticated
        satisfy any;
        #allow all;  # This allows all authenticated users
        #deny all;   # This denies all other users
    }
}

Make sure to replace <…> to match your configuration. Remove the default config file and create a symlink to the new one:

sudo unlink /etc/nginx/sites-enabled/default
sudo ln -s /etc/nginx/sites-available/mynginxconfig /etc/nginx/sites-enabled/mynginxconfig

…and see if nginx is coming up:

sudo systemctl enable --now nginx

If you direct your client to https://<YOUR_PI_IP>/dav/ (trailing “/”!) you should end up in ${ROOTPATH}/davshares/root. Please note that this is not a multi user setup.

CardDAV + CalDAV

For Card-/CalDAV we’ll rely on Radicale and basically this is still true. Let’s get it installed by:

sudo apt install python3-passlib python3-bcrypt apache2-utils radicale

Of course you can omit apache2-utils if you installed it before (s. above).

Add user(s)

Again we’ll use htpasswd to generate a user file:

sudo htpasswd -B -c /etc/radicale/users <YOUR_USER>

-B will encrypt the password using bcrypt hashing.

Configure radicale

Create a directory to hold your certificate and key, i.e.:

sudo mkdir /etc/radicale/certs
sudo cp mycert.pem /etc/radicale/certs
sudo cp mykey.pem /etc/radicale/certs
sudo chmod 640 /etc/radicale/certs/*.pem
sudo chgrp radicale /etc/radicale/certs/*.pem

As I wanted the actual data located on my external disk again, I’ve created a dedicated directory for that purpose, i.e.:

sudo mkdir /data/data/radicale/collections
sudo chmod 775 /data/data/radicale/collections
sudo chgrp radicale /data/data/radicale/collections

Make sure it’s writable by radicale!

Then edit the configuration file and check for the following:

/etc/radicale/config:
---------------------
hosts = <YOUR_PI_IP>:5232

ssl = True
certificate = /etc/radicale/certs/mycert.pem
key = /etc/radicale/certs/mykey.pem

type = htpasswd
htpasswd_filename = /etc/radicale/users
htpasswd_encryption = bcrypt

type = owner_only

filesystem_folder = /data/data/radicale/collections

By default the service is not allowed to write in that new location, thus we need to create an override configuration file:

sudo mkdir /etc/systemd/system/radicale.service.d
echo -e "[Service]\nReadWritePaths=/data/data/radicale/collections" | sudo tee /etc/systemd/system/radicale.service.d/override.conf

Enable and start the service:

sudo systemctl enable --now radicale

…and point your browser to https://<YOUR_PI_IP>:5232. Done!