by Tykling
05. dec 2017 11:25 UTC
I've been working to replace my OwnCloud
installation with something else. I use the Calendar part of OwnCloud
a lot, and this post is about replacing the CalDAV
bits of OwnCloud
with Radicale, a Python based CalDAV
and CardDAV
server.
I use nginx
and supervisord
so I will start out by showing the config for those before getting deeper into Radicale
.
I run all my webstuff through a reverse proxy which takes care of terminating TLS and IPv6 and passes the request to the backend jail running the service in question. This means that the configuration of the backend webserver in the service jail can be kept very simple:
location / { # regular proxy stuff proxy_pass http://127.0.0.1:5232; proxy_http_version 1.1; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # radicale http_x_remote_user config proxy_set_header X-Remote-User $remote_user; auth_basic "Radicale - Password Required"; auth_basic_user_file "/usr/local/etc/nginx/radicale-htpasswd"; }
I read in the Radicale reverse proxy documentation about the auth method called http_x_remote_user
which sounds perfect since I can let nginx
handle the authentication with regular HTTP Basic Auth
. This was actually the reason I had to switch to the 2.x version of Radicale
since 1.x doesn't support http_x_remote_user
.
I am becoming a big fan of running stuff with Supervisord
. Although software should be stable it is nice to have "something" keeping an eye on things, restarting as needed. But that is not all Supervisord
does, it also handles logging very well. The following block (Ansible
generated of course) is what I use to run Radicale
and redirect console logs to syslog:
[program:radicale] command=/usr/local/virtualenv/bin/python /usr/local/virtualenv/bin/radicale -C /usr/local/etc/radicale/config user=radicale stdout_logfile=syslog stderr_logfile=syslog startsecs=5 numprocs=1
To make Radicale
not daemonize I had to add daemon = False
to the [server]
section of the config. Also note that I am calling the virtualenv
Python directly and that the Radicale
executable is also inside the virtualenv
.
I started out (as one does) with Radicale
from the FreeBSD
Ports tree, which at the time of writing (December 2017) was at version 1.1.2. I was forced to switch to installing Radicale
from pip
instead to get the 2.x version. I will change that back to installing from FreeBSD
Ports when the new Radicale
arrives in Ports.
All this boils down to the following config file:
[server] daemon = False [auth] type = http_x_remote_user [rights] type = from_file file = /usr/local/etc/radicale/rights [storage] filesystem_folder = /usr/local/share/radicale/collections [logging] config = /usr/local/etc/radicale/logging
Since Supervisord
is configured to redirect both stdout
and stderr
to syslog
I don't need Radicale
to log to files or syslog
by itself, it should just log to console and let Supervisord
handle the rest. The following logging config accomplishes that:
[loggers] keys = root [handlers] keys = console [formatters] keys = full [logger_root] level = DEBUG handlers = console [handler_console] class = StreamHandler # change this to DEBUG for more verbosity level = INFO args = (sys.stdout,) formatter = full [formatter_full] format = %(asctime)s - %(levelname)s: %(message)s
Radicale
used Pythons default logging framework and actually manages to distribute it in a fairly understandable and flexible way, well done. Documentation here.
Radicale
has a pretty flexible rights system. It can be configured in a couple of different ways, I went with from_file
with the following rights file
:
# Authenticated users can read and write their own collections. [owner-write] user = .+ collection = %(login)s(/.*)? permission = rw # Everyone can read the root collection [read] user = .* collection = permission = r
This just means that each user can read and write their own collections. To configure sharing add a section like this:
[tykling-read-someones-calendars] user = tykling collection = someone(/.*)? permission = r
This would allow the user tykling
to access all collections under the username someone
. Read more about configuring rights in their rights documentation.
The Radicale
directory structure is pretty simple and it saves it's data as .ics
files. Here is the structure with an example calender with two events created:
$ sudo find /usr/local/share/radicale/collections /usr/local/share/radicale/collections /usr/local/share/radicale/collections/.Radicale.lock /usr/local/share/radicale/collections/collection-root /usr/local/share/radicale/collections/collection-root/tykling /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/29d56410-4b59-4cc3-95ea-cf167bfb24b2.ics /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/history /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/history/29d56410-4b59-4cc3-95ea-cf167bfb24b2.ics /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/history/8a6f1c57-aff6-4645-b483-10c99f61f866.ics /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/item /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/item/29d56410-4b59-4cc3-95ea-cf167bfb24b2.ics /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/item/8a6f1c57-aff6-4645-b483-10c99f61f866.ics /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/sync-token /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.cache/sync-token/d41d8cd98f00b204e9800998ecf8427e /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/.Radicale.props /usr/local/share/radicale/collections/collection-root/tykling/5405a11d-52e8-0f00-e540-feba9927044d/8a6f1c57-aff6-4645-b483-10c99f61f866.ics
For a while I didn't realise that Radicale
has a webinterface to create users and collections in the filesystem. Since I authenticate users in nginx
I first have to add the username and password in the htpasswd
file there of course, but then I go to the Radicale
web interface with a webbrowser and log on, and it shows me a simple view where I can choose to Create new addressbook or calendar
. After creating a calendar I can copy the full URL including UUID for that collection and use that in when configuring Lightning or other clients.
When searching for ways to import an existing calender (an ICS
file exported from OwnCloud in my case) I found that the advice was just to drop the ICS
file into the folder with the rest of the ICS
files and it would kindof just work. But it didn't:
Dec 5 21:24:38 radicale1 supervisord: radicale_00 2017-12-05 21:24:38,470 - ERROR: An exception occurred during PROPFIND request on '/tykling/a5196bd5-f2fe-82dc-8e6a-81cefa92b4b6/': Failed to load item 'export.ics' in 'tykling/a5196bd5-f2fe-82dc-8e6a-81cefa92b4b6': Muliple VEVENT components with different UIDs in object: '2be379d9-3ef0-4749-a14e-bd11028b5675', '08fd2497-c73d-46f5-b25d-7888d1ed8f27'
As you can see further up Radicale
creates one (1) .ics
file per event. The ICS
format obviously supports multiple events in a single file, but support for this appears to have been removed from the Radicale 2.x
series.
So I used this alternative method to import my ICS
:
cat export.ics | curl -u 'tykling:password' -X PUT https://cal.tyk.nu/tykling/a5196bd5-f2fe-82dc-8e6a-81cefa92b4b6/ --data-binary @-
This took around 10 seconds for a ~100kb ICS
file, and resulted in Radicale
creating a whole bunch of ICS
files. Perfect.
Thunderbird
comes with Lightning
built-in these days, and it works perfectly with Radicale
. Just add a network calendar, paste in the URL to the collection, enter credentials, done. Thunderbird does not appear to support the calendar coloring thing where you can configure the color in Radicale
and the CalDAV
clients should show the calendar in that color. But I'll live :)
I run Copperhead OS
on my phone so I only have access to the F-Droid
app-store so I was happy to see that I still had some options wrt. CalDAV
clients. I am currently using the "built-in" Etar
calendar app to show/use the calendar, and Davdroid
to synchhronise with the CalDAV
server. This works very well, and it was even able to show a list of the calendars created under my user so I didn't have to enter the full URL. Fancy.