Use Radicale to get your own shared calendar !


I was looking for a shared calendar, my prerequisites were:

  • self hosted
  • open source and free
  • “cross-platform” (I want it on my laptop, PC and my mobile)

After some research, I ended up on Radicale it’s a small CalDAV and CardDAV python server, and it fulfills all my requirements. Also you can:

  • secure the connection (I don’t mind I use HAProxy on top with Let’s Encrypt certificate, but still it’s cool)
  • support authentication (I use .htpasswd)
  • rights access, you can set some pretty interesting rights to your calendars, like read only for some users, and write for some others to others’ calendar …
  • storage hook, you can add a hook for example git, so each time you modify a calendar it’s committed and pushed to git !
  • other cool stuff, I didn’t completely review it all

So if it’s still appealing to you, follow me !

Install Radicale

Open up your terminal and do the following (still only showing Debian version):

aptitude install python3-pip
python3 -m pip install --upgrade radicale
Install requirements and Radicale

Configure it

For security reasons and convenience, I run my Radicale server behind HAProxy, so my configuration file maybe won’t be useful to you, you just have to change the hosts though.

It’s possible you don’t want the same choice I’ve made within the configuration below either (storage, git hook, authentication, file rights) so I suggest you take a look at the wonderful documentation.

If you want to use git as a hook, and also to have an authentication mechanism which I highly recommand, do the following:

aptitude install git libffi-dev apache2-utils
python3 -m pip install --upgrade passlib bcrypt
Requirements for authentication and git hook

Do not forget to create the storage folder:

mkdir -p /var/lib/radicale/collections
Create storage folder

If you choose an “.htpasswd authentication”, you can create each access like that:

htpasswd -B /etc/radicale/users <username>
Create a user access

Now edit /etc/radicale/config:

hosts               =
max_connections     = 5
timeout             = 2

filesystem_folder   = /var/lib/radicale/collections
hook                = git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s)

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

#type                = none

debug               = true

type                = from_file
file                = /etc/radicale/rights

Some quick explanations:

  • server section is quite self explanatory
  • auth section, you can define several fields such as the type of auth, where is your file and the encryption
  • web needs some explanation, if you set type to none, then you won’t have the interface though the web (it’s cool when you are in production), there I comment it so I have access to the interface so I can create calendars
  • logging is easy to understand
  • rights, in my case I choose to load the rights from a file but there are other options

You have to init the git repository if you chose to use it:

cd /var/lib/radicale/collections
git init
Init the repository

Now create a .gitignore like that and you’re done:


Let’s move on to the configuration of rights in /etc/radicale/rights:

## GLOBAL ##

# any authenticated user can reach root collection
user = .+
collection =
permission = r

# specific to login to web panel, if not you can't login because only your data is allowed and not your root
user = .+
collection = %(login)s
permission = rw

# any authenticated user can rw its data
user = .+
collection = %(login)s/.*
permission = rw

Again it’s quite easy to understand, a few notes:

  • the name within the bracket can be what you want
  • you cannot put several user in one section, let’s say you want to give rw to several user, you’ll have to repeat each section
  • careful between user = .* (matches everyone including anonymous users) and user = .+ (only matches authenticated users)

A special note, in my case I have more right with my user, it can rw an other user’s calendar and also only read an other. Here’s a preview if you want to adapt it for your own purpose:

# floreo can read blublu
user = floreo
collection = blublu/.*
permission = r

# floreo can read/write blibli
user = floreo
collection = blibli/.*
permission = rw
Extra for /etc/radicale/rights

Check the configuration documentation for further details.

I suggest you have a look at the rights configuration since it can be very dangerous.


I use Supervisor to run Radicale in case it crashes. I know you can write an init script or you can use screen or tmux but that’s ugly.

aptitude install supervisor
Install Supervisor

Now let’s configure it to run Radicale in /etc/supervisor/conf.d/radicale.conf:

command=python3 -m radicale
stderr_logfile = /var/log/supervisor/radicale-stderr.log
stdout_logfile = /var/log/supervisor/radicale-stdout.log

Time to start it:

supervisorctl reread
supervisorctl start radicale
reread and start Radicale

To be clean, let’s add a logrotate in /etc/logrotate.d/supervisor:

/var/log/supervisor/*.log {
    rotate 52


As I said previously I’m running HAProxy on top, here goes one possible configuration in /etc/haproxy/haproxy.cfg:

frontend https
        bind :::443 v4v6 ssl crt <path to your pem>
        http-request set-header X-Forwarded-Proto https

        use_backend radicale if { hdr(Host) -i <your domaine name> }

frontend http
        bind :::80 v4v6
        http-request redirect scheme https if { hdr(host) -i <your domaine name> } !{ ssl_fc }
        use_backend radicale if { hdr(Host) -i <your domaine name> }

backend radicale
        option forwardfor
        server radicale localhost:5232

Runtime !

Now if you connect to your Radicale web panel with one of your user created previously in the .htpasswd file, you should be able to create a new calendar or adressbook. So you can do it, that shouldn’t be hard, and it will give you a full link to your own collection, that’s the link you’ll have to insert in your clients !


On my computer I use Thunderbird with the lightning modules, careful because if you have several account in Radicale, Thunderbird only sticks to one, so I put the user and password in the URL (i.e to avoid the login prompt …

On my mobile, I use Open Sync to deal with the sync of CalDAV and SolCalendar (it looks like it got removed from the Play Store recently …)

The end

If you followed well, you should remember that we have the Radicale web panel UP, I suggest to turn it off once you have created the calendar and addressbook for each of your users since you can manage events and contacts from your clients. To do so, open up /etc/radicale/config and uncomment the lines:

hosts               =
max_connections     = 5
timeout             = 2

filesystem_folder   = /var/lib/radicale/collections
hook                = git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s)

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

type                = none

debug               = true

type                = from_file
file                = /etc/radicale/rights

And don’t forget to restart Radicale through Supervisor:

supervisorctl restart radicale
Restart Radicale through Supervisor

Done, it should all work well 🙂

Addendum : how to get your calendar back in case you fucked up

So it happened to me few minutes ago to completely destroy my calendar using a script trough WebDAV. Hopefully I use git hook to track all modifications to my calendar so here it goes to get your calendar back !

First, don’t panic.

Secondly, go to your Radicale root lib directory, it should be /var/lib/radicale/collections and list your modifications in git:

# git log
commit d78ec10d0b80ccae7fb25ecda26d5b5f05e2f69f
Author: root <root@xxx>
Date:   Thu Aug 17 18:55:30 2017 +0200

    Changes by fuckedup_script

commit 7fe7c14099834ef843175c06e6bd2bfa1212a68c
Author: root <root@xxx>
Date:   Thu Aug 17 18:50:20 2017 +0200

    Changes by floreo
git log

So in this example, we can see two commits, the last one was made by a script, and the other one by me directly. We need to go back to the previous commit made by me, and not by the script, so just write down the commit number, here it’s 7fe7c14099834ef843175c06e6bd2bfa1212a68c.

Let’s go back to our previous commit:

git reset --hard 7fe7c14099834ef843175c06e6bd2bfa1212a68c
git reset

And voilà, you got your calendar back, fiuuu !

Addendum 2: keep your Radicale up to date

It’s quite easy to do so, just run an upgrade once in a while, or read that page

python3 -m pip install --upgrade radicale
Upgrade Radicale

You now have to restart it, if you use Supervisor as I explained above, just kill nicely the pid and it will run automagically:

kill -3 $(ps aux | grep -i radicale | grep -v grep | awk '{ print $2 }')
Kill Radicale!

Check the version is alright:

radicale --version
Check Radicale's version