CalDAV and CardDAV with DAViCal

March 31, 2017

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/: {{< highlight apache >}} <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
{{< / highlight >}}

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: {{< highlight nginx >}} 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;
}

} {{< / highlight >}} (You'll have to figure out the SSL-part yourself. I use certbot 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.

{{< highlight php >}}

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'); {{< /highlight >}} [The last part](//wiki.davical.org/w/Configuration_settings#Apache_Module_does_the_Authentication) 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](//wiki.davical.org/index.php/CalDAV_Clients) and [carddav](//wiki.davical.org/index.php/CardDAV_Clients) 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 ------- * *