the ramblings of a random norwegian techie

CalDAV and CardDAV with DAViCal

· by Dennis Eriksen

I like to host everything myself, which means I run CalDAV and CardDAV on my own server to synchronize contacts and calendars. Previously I’ve been running Baïkal, but now It’s time to test something else. The reason I want to test out something else is that I want the ability to share calendars. Enter DAViCal.

I’ll be installing DAViCal on Ubuntu 16.04, but the configuration should be pretty similar for older and newer versions of both Ubuntu and Debian. Also, I’ll be explaining how I set this up in MY environment. Some parts might not apply in yours. For instance, I will be using BasicAuth in Apache to authenticate users, instead of DAViCals built-in solution.

I’m running PHP 7.0 using libapache2-mod-php7.0 and Apache, running behind an nginx-proxy. I’m assuming you’ve already got this set up, and that you’re already running a database. I’ll be using PostgreSQL.

Installing DAViCal

First off, let’s install DAViCal!

dennis@spandex:~$ sudo apt install davical

This will install DAViCal and all dependencies you need.

Database Setup

Permissions

You’ll need to edit the PostgreSQL-config file to give DAViCal the permissions it needs. My config-file is located at /etc/postgresql/9.5/main/pg_hba.conf. Put the following into your config-file:

# DAViCal
local   davical         davical_app                             trust
local   davical         davical_dba                             trust

Above the line that says

local   all             all                                     peer

And reload PostgreSQL using

dennis@spandex:~$ sudo systemctl reload postgresql

Creating the database

Next up we need to create and build the database. DAViCal comes with a script, create-database.sh, which can do this for you. It is located in /usr/share/davical/dba/, and needs to be run as a user with permissions to create databases. Typically we can do something like this:

dennis@spandex:~$ sudo su postgres -s /usr/share/davical/dba/create-database.sh


Supported locales updated.
Updated view: dav_principal.sql applied.
CalDAV functions updated.
RRULE functions updated.
Database permissions updated.
NOTE
====
*  The password for the 'admin' user has been set to 'laeDe9ae='

Thanks for trying DAViCal!  Check in /usr/share/doc/davical/examples/ for
some configuration examples.  For help, visit #davical on irc.oftc.net.

If the above command fails, it’s like you’ve screwed up the database-permissions, or something else. Fix it, and run the script again, after you’ve deleted the database. You can delete the database using:

dennis@spandex:~$ sudo su postgres -c "dropdb davical"

DNS

I like to give everything its own address. DAViCal will be running on davical.domain.tld. As such, I’m setting up a CNAME-record from davical.domain.tld, to spandex.domain.tld, which is the server DAViCal will be running on.

Apache

Here’s my Apache-configuration, located at /etc/apache2/sites-available/:

<VirtualHost *:8080>

    ServerName davical.domain.tld
    UseCanonicalName on

    DocumentRoot /usr/share/davical/htdocs
    DirectoryIndex index.php index.html
    Alias /images/ /usr/share/davical/htdocs/images/

    # To circumvent phps $_SERVER['HTTPS']-check
    SetEnv HTTPS "on"

    AcceptPathInfo On

    <Directory "/usr/share/davical/htdocs">
        AuthType Basic
        AuthName "private area"
        AuthUserFile /etc/apache2/davical.htpasswd
        Require valid-user
    </Directory>

    <Directory "/usr/share/davical/htdocs/images/">
        AllowOverride None
        Order allow,deny
        Allow from all
    </Directory>

    CustomLog /var/log/apache2/baikal.domain.tld-access.log combined
    ErrorLog /var/log/apache2/baikal.domain.tld-error.log

</VirtualHost>

Also, we’ll need to create a password-file. Mine is located at /etc/apache2/davical.htpasswd. You can create it like this:

dennis@spandex:~$ sudo htpasswd -c /etc/apache2/davical.htpasswd admin
New password:
Re-type new password:
Adding password for user admin

Note that the password you use here will be the actual admin-password.

The Apache-config is activated by running:

dennis@spandex:~$ sudo a2ensite davical.domain.tld.conf
Enabling site davical.domain.tld.
To activate the new configuration, you need to run:
  service apache2 reload
dennis@spandex:~$ sudo systemctl reload apache2

Nginx

You’ll notice that Apache is listening to port 8080. That is because I’m running Apache behind Nginx. This is because I’m using Nginx for other things, and it is hogging port 80 and 443. Also, I prefer Nginx, so I use it to terminate TLS.

This is my Nginx-config, located at /etc/nginx/sites-available/davical.domain.tld:

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name davical.domain.tld;

    access_log /var/log/nginx/davical.domain.tld-access.log;
    error_log /var/log/nginx/davical.domain.tld-error.log;

    ssl on;
    ssl_certificate /etc/ssl/letsencrypt/davical.domain.tld.pem;
    ssl_certificate_key /etc/ssl/letsencrypt/davical.domain.tld.key;

    charset utf-8;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 604800;
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
    }
}

(You’ll have to figure out the SSL-part yourself. I use lets-ca.sh and Let’s Encrypt)

It is activated like this:

dennis@spandex:~$ sudo ln -s "../sites-available/davical.domain.tld" /etc/nginx/sites-enabled/davical.domain.tld"
dennis@spandex:~$ sudo systemctl reload nginx

DAViCal should now be available on the web. Try visiting davical.domain.tld. It should look something like this.

Configuring DAViCal

DAViCals configurationfiles are located in /etc/davical/. If you want to run multiple instances of DAViCal, each instance can must have its own config-file, named domain.tld-conf.php (or sub.domain.tld-conf.php - you get the gist of it). If you only need one instance, you can name the file config.php.

Since I only need one instance of DAViCal, my config-file will be /etc/davical/config.php.

<?php
  $c->domain_name = "davical.domain.tld";
  $c->sysabbr     = 'DAViCal';
  $c->admin_email = 'root-davical@domain.tld';
  $c->system_name = "My DAViCal Server";
  $c->pg_connect[] = 'dbname=davical port=5432 user=davical_app';

  // Use Apache-supplied headers and believe them
  $c->authenticate_hook['server_auth_type'] = 'Basic';
  include_once('AuthPlugins.php');

The last part lets Apache do the authentication.

Setting up users

Navigate to davical.domain.tld and log in as admin. Select “Create Principal” from “User Functions” in the menu. Fill in the details, and click Create.

Remember that whenever you setup a new user, you will have to create a line for that user in /etc/apache2/davical.basicauth using the command you user earlier.

Sharing a calendar

Sharing calendars isn’t too difficult. You start off by creating the users involved. Then you create a group, and add the users to the group. Then you grant this group privileges to access (preferably read-only) each user. In iCal on MacOS you’ll find the shared calendars under Delegation under the account in Accounts.

Configuring the Client

I use MacOS and iOS on the client-side, so I will only explain how to set up caldav- and carddav-sync on those platforms. DAViCal has instructions for setting up caldav and carddav on other clients.

iCal on MacOS

Open up iCal, open Preferences (you can use the hot-key ⌘,), select Accounts, hit the +-sign to add account, select Other CalDAV Account…, select Advanced as “Account Type”, and fill in everything.

User Name, Password, and Server Address should be pretty self-explanatory. Server Path is /caldav.php/USERNAME/, port is 443, the Use SSL-box should be ticked, and the Use Kerberos v5 for authentication should not.

Contacts on MacOS

Open up Contacts, open Preferences (you can use the hot-key ⌘,), select Accounts, hit the +-sign to add account, select Other Contacts Account…, select Manual as Account Type. Fill in the rest, and voilà, it should work.

Calendar on iOS

Open up Settings, select Calendar, select Accounts, select Add Account, select Other, select Add CalDAV Account, fill in your details, and hit Next. Voilà.

Contacts on iOS

Open up Settings, select Contacts, select Accounts, select Add Account, select Other, select Add CardDAV Account, fill in details, and hit Next. Voilà.

Sources