How to install a CalDav and CardDav server using Radicale

During my time at the university I had lots of meetings, events and I couldn’t remember all these events, so I had to write them down. But we’re living in a digital world, so I wanted to keep all my appointments digitally. I tried Thunderbird Lightning and it is a great Add On. But I also wanted to synchronize all these events with my smartphone without using an external cloud, e.g. Google Calendar.

I wanted a small program with minimal dependencies to act as a server which is able to run on a Raspberry Pi. It doesn’t have to provide a web interface, because I can use Thunderbird or my smartphone to add, change or delete events. I found Radicale which is written in Python and has no dependencies. It supports the CalDav and CardDav protocol. That’s all I wanted so I gave it a try. My first impression was very good and it works great. Here are all steps I did to set up my own CalDav server with Radicale.

1. Installation of Radicale
2. Adding bcrypt support to Radicale (optional step)
3. Configure Radicale
4. Configure Thunderbird Lightning
5. Configure Android Calendar

1. Installation of Radicale

First of all we have to download Radicale. You can find all versions at the download page of Radicale.

$ wget http://pypi.python.org/packages/source/R/Radicale/Radicale-0.8.tar.gz

Next step is to extract the archive:

$ tar xzvf Radicale-0.8.tar.gz

Radicale supports a lot of authentication protocols, but I will use HTTP-Basic-Authentication. The Problem is that all used hashing algorithms are insecure. I found a simple way to add the bcrypt algorithm to Radicale which is considered to be very secure. If you want to use HTTP-Basic-Authentication with bcrypt go to step 2 and come back after you finished step 2.

Last step of the installtion is to run setup.py

$ sudo python setup.py install

2. Adding bcrypt support to Radicale (optional step)

To use bcrypt in python you have to download and install the python bcrypt library. You can find the python bcrypt library here.

wget http://py-bcrypt.googlecode.com/files/py-bcrypt-0.4.tar.gz 

Extract the archive and install it:

$ tar xzvf py-bcrypt-0.4.tar.gz && cd py-bcrypt-0.4
$ python setup.py build && python setup.py install

Now we can modify Radicale to support bcrypt. You only have to modify one file which is radicale/auth/htpasswd.py
Add the following line to the import section of the file:

import bcrypt

and add the following function to the same file:

def _bcrypt(hash_value, password):
    """Check if ``hash_value`` and ``password`` match using bcrypt method."""
    hash_value = hash_value.encode("ascii")
    password = password.encode(config.get("encoding", "stock"))
    return bcrypt.checkpw(password, hash_value)

Now Radicale is able to use bcrypt passwords.

3. Configure Radicale

The configuration of Radicale is simple. You only have to change a few settings in the config file. In my case I created the directory /etc/radicale and copied the config file to this directory. Here is the config file that I use:

# -*- mode: conf -*-
# vim:ft=cfg

# Config file for Radicale - A simple calendar server
#
# Place it into /etc/radicale/config (global) 
# or ~/.config/radicale/config (user)
#
# The current values are the default ones


[server]
# CalDAV server hostnames separated by a comma
# IPv4 syntax: address:port
# IPv6 syntax: [address]:port
# IPv6 adresses are configured to only allow IPv6 connections
hosts = 0.0.0.0:5232
# Daemon flag
daemon = True 
# File storing the PID in daemon mode
pid = 
# SSL flag, enable HTTPS protocol
ssl = True 
# SSL certificate path
certificate = /etc/radicale/ssl/server.crt
# SSL private key
key = /etc/radicale/ssl/server.key
# Reverse DNS to resolve client address in logs
dns_lookup = True
# Root URL of Radicale (starting and ending with a slash)
base_prefix = /
# Message displayed in the client when a password is needed
realm = Radicale - Password Required


[encoding]
# Encoding for responding requests
request = utf-8
# Encoding for storing local collections
stock = utf-8


[auth]
# Authentication method
# Value: None | htpasswd | IMAP | LDAP | PAM | courier | http
type = htpasswd 

# Usernames used for public collections, separated by a comma
public_users = public
# Usernames used for private collections, separated by a comma
private_users = private

# Htpasswd filename
htpasswd_filename = /etc/radicale/users
# Htpasswd encryption method
# Value: plain | sha1 | crypt | bcrypt
htpasswd_encryption = bcrypt

# LDAP server URL, with protocol and port
ldap_url = ldap://localhost:389/
# LDAP base path
ldap_base = ou=users,dc=example,dc=com
# LDAP login attribute
ldap_attribute = uid
# LDAP filter string
# placed as X in a query of the form (&(...)X)
# example: (objectCategory=Person)(objectClass=User)(memberOf=cn=calenderusers,ou=users,dc=example,dc=org)
# leave empty if no additional filter is needed
ldap_filter = 
# LDAP dn for initial login, used if LDAP server does not allow anonymous searches
# Leave empty if searches are anonymous
ldap_binddn =
# LDAP password for initial login, used with ldap_binddn
ldap_password =
# LDAP scope of the search
ldap_scope = OneLevel

# IMAP Configuration
imap_hostname = localhost
imap_port = 143
imap_ssl = False

# PAM group user should be member of
pam_group_membership =

# Path to the Courier Authdaemon socket
courier_socket =

# HTTP authentication request URL endpoint
http_url =
# POST parameter to use for username
http_user_parameter =
# POST parameter to use for password
http_password_parameter =


[rights]
# Rights management method
# Value: None | owner_only | owner_write | from_file
type = owner_only

# File for rights management from_file
file = ~/rights


[storage]
# Storage backend
# Value: filesystem | database
type = filesystem

# Folder for storing local collections, created if not present
filesystem_folder = ~/collections

# Database URL for SQLAlchemy
# dialect+driver://user:password@host/dbname[?key=value..]
# For example: sqlite:///var/db/radicale.db, postgresql://user:password@localhost/radicale
# See http://docs.sqlalchemy.org/en/rel_0_8/core/engines.html#sqlalchemy.create_engine
database_url =


[logging]
# Logging configuration file
# If no config is given, simple information is printed on the standard output
# For more information about the syntax of the configuration file, see:
# http://docs.python.org/library/logging.config.html
config = /etc/radicale/logging
# Set the default logging level to debug
debug = False 
# Store all environment variables (including those set in the shell)
full_environment = False


# Additional HTTP headers
#[headers]
#Access-Control-Allow-Origin = *

The next step is to create a user for Radicale. This is just for security reasons, Radicale will run with the permissions of this user. I created a user radicale and a group radicale. All calendars and contacts will be stored in the home directory of this user (if you use the config file above). The following command creates the user radicale and adds it to the group radicale.

useradd -d /home/radicale/ -U -m -p PASSWORD radicale

One of the last steps is to create the users file which contains all login credentials. I saved the users file in /etc/radicale. If you don’t want to use bcrypt, you can use the htpasswd command to create a password file. The following example creates the file users and adds the user funkym0nk3y. You have to enter the password which will be hashed with SHA-1 (in this case).

htpasswd -cs ./users funkym0nk3y

I neither recommend using plaintext passwords nor hashed passwords with SHA-1 or crypt. The best way is to add the bcrypt hashing algorithm. You can use the following python script to hash a password using bcrypt. It will create the hashed password and output USERNAME:HASHED_PASSWORD

#!/usr/bin/env python
import bcrypt
from optparse import OptionParser

parser = OptionParser()
parser.add_option("-u", "--user", dest="username", help="Username")
parser.add_option("-p", "--password", dest="password", 
                  help="Password which will be hashed using bcrypt")
parser.add_option("-w", "--workfactor", dest="workfactor", default="12",
                  help="Workfactor of bcrypt, the higher the more secure")

(options, args) = parser.parse_args()
if options.username == None or options.password == None:
	parser.print_help()
else:
	hashed = bcrypt.hashpw(options.password,
                               bcrypt.gensalt(int(options.workfactor)))
	print "%s:%s" % (options.username,hashed)

This script is also available at Github.

The last step is to create a server key and a server certificate to use encrypted connections. You can use a self signed certificate (use the commands below to create a self-signed certificate). Don’t encrypt the key, because then you would have to enter the password each time a client connects to the server.

$ openssl genrsa -out server.key 1024
$ openssl req -new -x509 -days 365 -key server.key -out server.crt

If you want a certificate signed by a Certificate Authority (CA) you can take a look at this Post. It explains all steps to create your own Certificate Authority.

To start Radicale change the user to radicale and enter radicale to start the server.

4. Configure Thunderbird Lightning

Start Thunderbird and go to
File -> New -> Calendar
Choose the option “On the Network” and click Next. Select “CalDav” and enter the address to the calendar, e.g. https://COMPUTERNAME:5232/funkym0nk3y/calendar.ics. If the calendar does not exist, radicale will create it. Click Next and enter the name of the calendar, choose a color and click Next. You will get a message: “Your calendar has been created”.
You have to enter the username and the password.

5. Configure Android Calendar

The Android calendar is not able to sync all events with CalDav servers. I installed CalDavSync to add this feature. You can find a CalDavSync App here: CalDavSyncAdapter
I’ve tested this app and it works for me.

To sync your Android calendar with the server go to the calendar app and then
Settings -> Calendar -> Add Account -> CalDav Sync Adapter
Enter the login credentials and the url to your calendar.

That’s it

Sources:
Radicale User documentation
Source Code of Radicale

Posted on November 19, 2013, in Android, Command-Line, Configure, Cryptography, Install, Network, Security, Software and tagged , , , , , , , , , , , , , . Bookmark the permalink. 63 Comments.

  1. Excellent post – helped me out a lot, thanks. However, when I try to access Radicale using HTTPS I recieve the following message in Firefox: ssl_error_rx_record_too_long. Without HTTPS everything works fine.

    I have looked around with no luck finding an answer that applies to my situation. Any idea as to what might be causing this?

    • Thanks. Radicale has afaik no web interface. I tried to connect to my server with Firefox and it is “waiting for server”. Try to establish a connection with Thunderbird Lightning. You can find the config steps in section 4 “Configure Thunderbird Lightning”. If you still get the SSL error message with Thunderbird Lightning send me message and I will try to find a solution.

      • I am having some trouble adding the calendar with Lightning, but I think it is unrelated to Radicale (when I enter the information for my calendar, I am never prompted for a username or password). Either way though, what leads me to believe the problem is unrelated to the lack of web interface is that when I go to http://:5232 in Firefox, I see the message “Radicale works!” However, when I go to https://:5232, I get the error I mentioned earlier.

        In addition, when I try to connect using a CalDAV client on my Android phone, everything works perfectly if I use http. However, when I try to use https, I get an error message saying “I/O Error: Cannot verify hostname: .”

        If you need to see what happens with Lightning I can keep messing around with it and let you know.

      • I’m not 100% sure, but the error message “I/O Error: Cannot verify hostname:.” can have several reasons:
        1) you have not entered the full server name, e.g. https://radicale.mydomain.tld:5232
        2) the hostname does not match the commonName field within the certificate.
        I wrote a post how to create your own PKI: https://evilshit.wordpress.com/2013/06/19/how-to-create-your-own-pki-with-openssl/
        Make sure that the commonName field of your server certificate does match the hostname.

        If you use a certificate signed by your own CA, make sure to import the CA certificate into Thunderbird and/or Android, because they are not listed in the trusted CA list.
        I hope this helps. If you need more help, send me a message.

      • For some reason I couldn’t reply to your most recent post. Anyway, I could see it being the second issue you mentioned, “hostname does not match the commonName field within the certificate.”

        I have been messing around with it a bit more though and found that I am able to connect using SSL with CalDAV-Sync (before I was using a different app: DAVdroid). I find it odd that one would be able to connect with SSL but the other would not. Do you know if there is a way to confirm that SSL is actually being used? Either that or, do you know if CalDAV-Sync would warn me if SSL was not working? Thanks.

      • Sorry for the late answer.
        There are several ways to confirm that SSL is used to encrypt the traffic. The best way would be to use a network sniffer (e.g. Wireshark, tshark, etc) at your Radicale server. Record the network traffic and establish a connection with your phone (or Thunderbird) to the server. After that stop the recording and take a look at the logged traffic. You can filter the logged traffic to get only the communication between your phone and your server. If SSL is used, you’ll see packets which are encrypted. Wireshark displays (as far as I remember) a little note that the content is encrypted. This solution is the best because you can check the content of the packets.
        Another way is to use SSLScan. This scanner displays the cipher suites offered by the server. If SSL or TLS is not activated you should get no cipher suite. The problem with this solution is that it only displays the offered cipher suites. It doesn’t mean that the cipher suites are really used to encrypt the traffic.

        Long story short, the first solution is a bit more complicated but the better way to verify that the traffic is encrypted.

  2. Hi. Installation seems to be going fine so far, thank you. However, I’m a bit new to all of this, so I’m stuck at the user file bit. You’ve said to use this to create a user file if not using bcrypt: htpasswd -cs ./users funkym0nk3y. But what if you do intend to use bcrypt?

    I tried the htpasswd command anyway, but it didn’t create a file, just told me how to use the command. So a bit lost there.

    And I have no clue what to do with the script section after that! Am I making a file somewhere to put that in?

    Sorry to be so clueless!

    Thanks

    • Hi,
      Radicale doesn’t support bcrypt encryption, but it’s very easy to add bcrypt support to Radicale (take a look at Step 2). You also have to modify one line in the config file. Here is the important excerpt of the config file:
      # Htpasswd encryption method
      # Value: plain | sha1 | crypt | bcrypt
      htpasswd_encryption = bcrypt

      After adding and modifying these few lines I recommend to restart Radicale. Now Radicale supports bcrypt, but you have to create an encrypted password for the users. htpasswd doesn’t support bcrypt encryption, so you can’t create a bcrypt encrypted password with htpasswd. I wrote a little script, which you can find in the post or on Github (for direct download). This script will print the username and the encrypted password to the standard output (console, terminal, …). You can redirect the output to a file:
      ./bcrypt_pw_hasher.py -u USERNAME -p PASSWORD -w WORKFACTOR > users
      Don’t use a high workfactor, because it takes a lot of time to encrypt the string. A factor between 8 and 12 should be fine. If you use my config file, this (new created) “users” file is located at /etc/radicale/ Just copy or move the file “users” to the correct location and it should work.
      I hope this helps. If you need more help, send me a message.

      • Thanks for the quick reply! I think to start with, I’ll get it going without bcrypt, make sure it all works as is. Then have a go with adding bcrypt afterwards, when I’ll maybe understand things a little better! I’ll be back here then…

  3. Phew, got it working! Thank you. Well, one quick test adding an event in Thunderbird, viewing it on Android phone. That was with an SHA password, for now. Now to get CalDavZAP going, which looks like a whole load of fun….

  4. Has anyone had any luck publishing calendars to Radicale? Or setting up public calendars. I’ve had a look around, but can’t really find any relevant guidance.

    • Sorry for the late answer.
      I’ve not used a public calendar and it seems to be a bit complicated to do that. If you only use public calendars it should be no problem. You have to modify the “global” rights to None (see: Radicale documentation). But if you want to use public and private calendars, you have to set up a user for public access (as far as I know). You have to modify the “global” rights to From File and have to set up a file for all rights (see link above).
      I’m currently very busy and have not the time to test this setup, sorry for that. Maybe I will take a look at it a bit later.

      • Thanks for the response again. To be honest, I think all of this is beyond my ability. Fine, I have normal calendars working to some extent. But nothing else, and no web GUI. I thought once I had Radicale set up, I’d more or less be good to go, but unfortunately not. Sorry to sound whiny, it’s just I’m doing my best to move away from Google etc, and a week later, I have next to none of the functionality I did have, despite many many hours of work. There’s simply nothing elegant out there.

      • I know it’s not easy to configure Radicale. The first time I installed and configured Radicale was also not easy and in my opinion the user doc of Radicale is not very good. But keep in mind that Radicale is still under development and I’m sure there will be some nice features in the next versions.
        But back to the problem. I’m not quite sure about your setup and what you really want to do with Radicale. I need a bit more information about your use case, e.g. what kind of calendars do you want to use (public, shared, private), how many of them, etc. I can set up another Radicale server and try to solve the problems.
        Long story short, I need a bit more information. You can post it in the comments or send me an email: linuxm0nk3ys@gmx.de
        But like I said, I’m currently very busy, so maybe I’ll need some time to get a solution to your problems. But I’ll do my best to help you.

      • The basic set-up is fairly easy. I’m still a beginner, but I got the basic bits done.

        What I want, is to host Caldav and Carddav on my Pi, and access them from my phone (I can do the phone part ok), and a web GUI. Caldavzap looks like the only web GUI option for Radicale, but I’ve not been able to find any kind of step-by-step instructions for that at all, and I don’t have anything like the experience to try to do it myself.

        On the calendar side, I want to have my own calendars, as before. That bit works. I also want to be able to subscribe to public calendars, or publish a public calendar to my server, to then access via phone/web. I don’t know if this is possible.

        I tried OwnCloud but hit some snags, so thought I’d try Radicale + Web GUI. It does look like there are some nice features coming in the future. And maybe with some practice I can still get something working. I think now I might have to try OwnCloud again, but get someone else to host it.

        Currently on my Pi I have Raspbmc, but I’m happy to use something else.

        I appreciate your offer of help, but I wouldn’t like to take up any more of your time. I’m certainly not complaining about the assistance that is out there, it’s my lack of expertise that is the frustrating part! I’ll keep trying 🙂

  5. Just wanted to say thank you for this detailed how-to!
    It would be nice if you could explain how to add radicale to run when rebooting 🙂

    • I’m a bit surprised that this post is so popular 🙂
      I will update this post as soon as possible, but I’m currently writing my thesis and have not much time. The update will contain a much more detailed description, configuration steps for card dav and maybe a video. I’ll write a tweet, if the update of this post is available.

      Thanks for your hints and questions to all of you. This will help us to improve our posts.

      • I’m not that tech savvy but still interested in privacy and turn my back on google&co. Espacially the part about bcrypt helped me a lot!
        I wish you success with your thesis!

    • to start Radicale at startup, edit the rc.local file:
      sudo vi /etc/rc.local

      In the text add:
      echo -n Starting Radicale…
      /usr/bin/radicale && echo done

  6. Hey funkym0nk3y, thanks for this great article! This worked perfectly on my Arch Linux “Server”. Since you are busy with your thesis I thought I write down some stuff that may come in handy for some of your readers:

    – Maybe it’s better to create the user and set the password like this:
    $ useradd -d /home/radicale/ -U -m radicale
    $ passwd radicale

    – For testing/debugging purpose I recommend starting radicale like this (you will be able to see the requests and responses in the terminal):
    $ radicale -f -D

    – My distro uses Systemd as its default init system, so I have written a “radicale.service”. With the service file you can start radicale automatically at startup and also manually start/stop radicale via Systemd. Here ist the service file, which should be saved under /etc/systemd/system/radicale.service :
    [Unit]
    Description=Radicale CalDav Server
    After=network.target
    [Service]
    Type=forking
    User=radicale
    Group=radicale
    PIDFile=%h/pid.pid
    ExecStart=/usr/bin/radicale -d
    [Install]
    WantedBy=multi-user.target

    After putting the service file into /etc/systemd/system/ execute this command:
    $ systemctl daemon-reload

    Now you can start/stop radicale like this:
    $ systemctl start radicale
    $ systemctl stop radicale

    To start radicale automatically with the system:
    $ systemctl enable radicale

    Again, great post! Now I can finally move my data from Google to my own server 🙂

  7. Hi!

    I was wondering why the change from the default config file:
    ‘file = ~/.config/radicale/rights’ and
    ‘filesystem_folder = ~/.config/radicale/collections’
    to your:
    ‘file = ~/rights’ and
    ‘file = ~/collections’ respectively.

    Does this mean that I need to move the ~/.config…/collections folder to the directory /etc/radicale? Or will this auto populate?

    I have made my config as yours and am using bcrypt. When I enter the https://…:5232, I receive, “A server error occurred. Please contact the administrator.”

    When I enter https://…:5232/name/calendar.ics/ after entering the credentials, it waited a while and again gave the same error: “A server error occurred. Please contact the administrator.”

    Why am I getting this error?

    • Hello!

      Did you manage to find out what was causing that error ?

      Thanks!

    • funkym0nk3y

      Sorry for the late answer.
      I only changed the folder because I didn’t want my collections within a hidden folder (nothing special).
      And no, you don’t have to move them to /etc/radicale. “~/rights” is a file within the home folder of the user radicale, i.e. “/home/radicale/rights”

      For the second error, I need a bit more information. It’s hard to help with this information.
      Try it first without SSL/TLS, just to make sure, that the encryption is not the problem.

  8. Hello! I have followed your instructions and installed radicale with bcrypt but when i go to the url https://ip:5232/user/calendar.ics I get == A server error occurred. Please contact the administrator. ==. If I try to connect from ‘CalDAV Sync Adapter (Android) I get == Invalid server answer ==. What did I do wrong ?

  9. I can’t build bcrypt…. May you help me with that?
    I have the same problem on 2 different servers running different versions of python.

    I installed a fresh copy of debian 7.5 in a local VM and tried to build bcrypt

    ~/py-bcrypt-0.4$ python setup.py build && python setup.py install
    running build
    running build_py
    creating build
    creating build/lib.linux-x86_64-2.7
    creating build/lib.linux-x86_64-2.7/bcrypt
    copying bcrypt/__init__.py -> build/lib.linux-x86_64-2.7/bcrypt
    running build_ext
    building ‘bcrypt._bcrypt’ extension
    creating build/temp.linux-x86_64-2.7
    creating build/temp.linux-x86_64-2.7/bcrypt
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c bcrypt/bcrypt.c -o build/temp.linux-x86_64-2.7/bcrypt/bcrypt.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c bcrypt/bcrypt_pbkdf.c -o build/temp.linux-x86_64-2.7/bcrypt/bcrypt_pbkdf.o
    gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -fPIC -I/usr/include/python2.7 -c bcrypt/bcrypt_python.c -o build/temp.linux-x86_64-2.7/bcrypt/bcrypt_python.o
    bcrypt/bcrypt_python.c:18:20: fatal error: Python.h: No such file or directory
    compilation terminated.
    error: command ‘gcc’ failed with exit status 1

    • You need the python-dev package: “apt-get install python-dev” …

      • funkym0nk3y

        Hi, thanks for the answer. I’m very sorry that I need some time to answer your questions. I’m still very busy but I hope that I’ll have more time in a month.

    • No problem funkym0nk3y! I’m glad I found the answer after hours of googling around 😀 Not easy at all. I don’t understand why it isn’t mentioned somewhere!

      I have another question. How do I make the daemon run even after startup AS the user “radicale”?
      There is a script for archlinux mentioned here, but I don’t think it will help me. I found some other scripts running as a service, but I installed it via python and not apt-get from a repository…

      Haven’t tried the bcrypt variant yet. Do I have to uninstall/remove radicale (where is its location?) or can I change the setup.py and install again?

  10. I just wanted to thank you for these excellent instructions. Until now I have been using an implementation of ownCloud on a Raspberry Pi to manage the storage and syncing of a few hundred contacts between several Android phones and tablets, but this provides a much leaner solution. I now have Radicale running on one of my Raspis with bcrypt, and syncing with CardDAV-Sync. Good luck with your thesis.

  11. HI monkeys!! another clue before going to sleep 😉
    so after playing with bcrypt i am now stuck with a server error, i cannot find my collection folder on disk so i think it is a permission problem. i execute radicale as a normal user since my pi is only a server.
    so the file should be in user/.config/radicale/… ?? right? i have also checked in /etc/radicale but found nothing…

    • funkym0nk3y

      Hi,
      the default location of the collection folder is $USER/.config/radicale (as far as I remember). If you use my config file it is located at $USER/radicale. I’m not 100% sure, but it is possible that radicale creates the collection folder if you create a calendar or a contact-db. Check your config file again for the location, in my case it’s the config file entry:
      filesystem_folder = ~/collections

      Try to create a calendar with Thunderbird or another client and check it again. If nothing changed and you still get an error or can’t find the collection send me a message.

  12. well that is the case, tried with thunderbird, it connects to the server but have an error retrieving the file, and it don’t create it… also i don’t have a group radicale in my /etc/group…

  13. seems that bcrypt will blow my mind…
    starting with:

    radicale -f -D

    show messages btw thunderbird and radicale and give me these recurrent lines when i want to create a calendar or event by thunderbird:

    Traceback (most recent call last):
    File “/usr/lib/python3.4/wsgiref/handlers.py”, line 137, in run
    self.result = application(self.environ, self.start_response)
    File “/usr/lib/python3.4/site-packages/radicale/__init__.py”, line 290, in __call__
    auth.is_authenticated(user, password):
    File “/usr/lib/python3.4/site-packages/radicale/auth/htpasswd.py”, line 67, in is_authenticated
    return globals()[“_%s” % ENCRYPTION](hash_value, password)
    KeyError: ‘_bcrypt’

    still no file created, tried to store collection in various places and manually add them too: no change…

    • funkym0nk3y

      Have you added the bcrypt function to the file htpasswd (Step 2)? I think so, but maybe something is not correct indented.

    • I’m not sure about this, but I think either bcrypt or radicale require python2 to run without problems. I remember that I also tried it with python3 at first and had to switch to python2 in the end, but maybe I’m wrong.

      Notice: There is no problem in installing python2 next to python3. However you have to compile the application with the environment set to python2 or at least start the application explicitly with python2.

      • have checked this, both radicale and bcrypt 0.4 have support for python3, i have python 2.7 installed too but haven’t find how to start radicale using it.

        anyway i don’t think this is the problem, since i have tried to change the root directory of radicale in the config file, setting it to a folder in the user directory, and tada! this error message didn’t show up anymore,
        but radicale still answer thunderbird requests with an error: permission denied. instead of server internal error previously…

  14. hey funkey,

    your bcrypt script on GitHub is missing the line with “parser.add_option(“-p” …..).
    I am talking about the password-option as shown on this website!

    best regards

    • funkym0nk3y

      Hi, I know. The script on GitHub is an updated version. I removed the password option (as recommended by Lukasz, see Issue #1).

      • God…. Am I that kind of blind?

        I checked your script again and now laughing my *** off 😀
        Please delete my last comment with the “new” script ^^

      • funkym0nk3y

        done 😉

    • funkym0nk3y

      Hi Sefer,
      thanks for your script.
      If you use the current GitHub version of the script, the password won’t get logged in the bash history. It should also be compatible with Python versions >= 3.
      I haven’t updated this post due to the missing time 😦 .

      Again 😉 I promise I’ll update this post as soon as possible.

      But thank you very much for your script. I really appreciate all the questions, hints and scripts in the comments 🙂

  15. Submitted on 2014/06/12 at 07:02

    # ./radicale.py
    Traceback (most recent call last):
    File “./radicale.py”, line 29, in ?
    import radicale.__main__
    File “/home/radicale/radicale/__init__.py”, line 49
    from . import auth, config, ical, log, rights, storage, xmlutils

    Submitted on 2014/06/12 at 07:05

    from . import auth, config, ical, log, rights, storage, xmlutils
    ^
    SyntaxError: invalid syntax

    Hi,
    Please ignore this..the issue got fixed by upgrading version of python..

    Thank you

  16. There is an error:
    It’s not supposed to be
    password = password.encode(config.get(“encodingtock”))
    but
    password = password.encode(config.get(“encoding”, “stock”))
    for the bcrypt encoding.

    • Maybe I miss something, but that’s exactly what I wrote. Can you tell me where you found the incorrect line?

      • There is this section where you list the snippet for adding bcrypt within the radicale scipt:
        def _bcrypt(hash_value, password):
        “””Check if “hash_value“ and “password“ match using bcrypt method.”””
        hash_value = hash_value.encode(“ascii”)
        password = password.encode(config.get(“encodingtock”))
        return bcrypt.checkpw(password, hash_value)

        And the line before the last one is not correct in my opinion.
        At least I read password.encode(config.get(“encodingtock”)) there.
        It’s supposed to be password.encode(config.get(“encoding”, “stock”)).

        I tried it in Chrome and Firefox, to make sure there is no rendering issue, but it reads the same in both cases.

        On and by the way, THANK FOR THE POST!
        Very very helpful, also the part with the bcrypt encryption.
        Works very well, the only problem I’m having is that the web server in python doesn’t seem to be very stable, at least I have to restart the radicale server every now and then.

      • This is a strange error. First, you’re right, it has to be:
        password = password.encode(config.get(“encoding”, “stock”))

        I checked it with Firefox, Seamonkey, wget, curl, on my tablet and smartphone. I get always the line above, not the one you mentioned. But thank you for reporting this” bug”, I’ll try to figure out why this happens.

        At least, I never had problems with the stability on my Raspberry Pi (Slackware Linux) with Radicale. I recommend to start Radicale in debug mode (arguments: – f – D) to get more information.

  17. Hey, I ran into the problem, too. In the page’s source the line is ok, but it is displayed wrong. Maybe this helps: I saved the page via Firefox’ File -> Save. There the line reads: password = password.encode(config.get(“encodingtock”))
    I assume some css goes wrong.

    • Ok, the css tags got removed from my previous comment, so the line i stated above won’t be any help.

      • funkym0nk3y

        Hi Dennis, thanks for your comment. Which browser have you used?
        I’m sorry that this line makes so much trouble.

        Just for the record, the latest version of Radicale is 0.10 and you should use the latest version. The steps in this post to install Radicale still works fine with 0.10, except the config file. Some lines changed a bit, but you can use the example config of Radicale and tweak it a bit:
        http://radicale.org/user_documentation/#idconfiguring-the-server

        I promised an update of this post a long time ago, but I still have not much time, but I will update this post as soon as possible.

      • Hey!
        No need to be sorry, the debug mode helped as described in your comment 🙂
        Basically, I used Firefox, but with addons like adblock, so that won’t be any help I think. The problem occurs in Opera 12.17 build 1863 as well. Here’s the source: http://pastebin.com/y1wkL42T

        I can confirm the manual’s valid for 0.10 and it gives a good start. Using the official documentation is recommended anyway, as it always is 🙂

        If you do an update, I’d suggest to take a look into infcloud (https://www.inf-it.com/open-source/clients/infcloud/), that would be a nice addition and seems to work ok on raspberry pi 2 using raspbian.

        Cheers, Dennis

  18. I have just contributed passlib-based bcrypt support to Radicale: https://github.com/Kozea/Radicale/pull/297

  19. This guide has been very helpful, only one like it out there, really, and I couldn’t have gotten anywhere at all without it. I know nothing of Python, and very little of Linux. I agree that Radicale’s documentation isn’t very good. This guide goes a long way to bridge that gap. However, I did have to spend many hours working through a few issues and still don’t have them all solved (highlighted with **** below). I’ll list problems I had to work through and the solution that ended up working. So far, I’ve only gotten contacts to Android running. Calendar and Thunderbird will be next.

    I’m using Raspbian Wheezy (w/ Python 2.7.3) on a headless Raspberry Pi 2. So far, I’ve connected only from Android 4.4.4 with CardDAV-Sync 0.4.14.

    #1. Realizing that I needed to install python development packages.

    sudo apt-get install python-dev

    #2. How to use Nano, and the necessity of using sudo.

    #3. How to run Radicale in debug mode. This helped me address most errors.

    sudo -u radicale radicale -f -D

    hit “q” to exit

    ********************************
    #4. Directory creation and permissions for /etc/radicale.
    (Not sure I’ve got it right, but it stopped throwing errors.)

    sudo chown -R radicale:radicale /etc/radicale/
    ********************************

    #5. This guide’s error in how to edit the htpasswd.py file. (“encodingtock”) vs. (“encoding”, “stock”). Debug mode was throwing all kinds of crazy error messages.

    #6. The bcrypt_pw_hasher.py script, figuring out how to use it. Eventually, I went with a modified version from a similar guide (written in German) that actually writes the user:hash line directly into the /etc/radicale/users file. I now call it add_user.py. Its last section looks like this:

    (options, args) = parser.parse_args ()
    if options.username == None or options.password == None:
    parser.print_help()
    else:
    hashed = bcrypt.hashpw(options.password,
    bcrypt.gensalt(int(options.workfactor)))
    with open(“/etc/radicale/users”, “a”) as configfile:
    configfile.write(options.username + “:” + hashed + “\n”)
    print “Radicale user created”

    But an example of how to run this script would be helpful for people like me.

    python add-user.py -u -p

    #7. How to edit /etc/rc.local, making Radicale start at bootup. I tried several methods, including:

    echo -n Starting Radicale…
    su -c /usr/bin/radicale radicale &
    echo Done

    That didn’t work, so I eventually ended up with:

    su -c radicale radicale &

    ************************************
    #8. (STILL UNSOLVED) User authentication for rights purposes. I’m now able to access my contacts collection, but only because I set the rights type to None. It doesn’t recognize my username, treating me as an Anonymous user.

    Should I create a linux user with the same name and password as my Radicale user? Or are linux users completely unrelated to Radicale users?
    ************************************

    • Hi, thank you so much for your comment and the solutions for your problems.
      I really have to apologize, that the update of this post takes so long. The problem is that I had so much things to do the last year. I will start the update of this post within the next days. I will read all the comments again and try to consider all your problems.

  20. I have encountered a strange anomaly. I’m not sure if it’s an issue with CardDAV-Sync or Radicale. Below are excerpts of what I sent to the developer of CardDAV-Sync. I thought you might have some insight.

    I’m using multiple Radicale users to segregate my contacts. Occasionally I want to move a contact from one account to another. On the Android, I use an app called Contacts Optimizer. If I move the contact using the Android, the contact correctly appears in its new account in the People app… until I sync with Radicale using CardDAV-Sync. The contact is deleted from all accounts on the Android. But a peek in Thunderbird’s Addressbook will reveal that the contact is not deleted from Radicale. If I move the contact between Radicale accounts using the Thunderbird Addressbook rather than the Contacts Optimizer app on the Android, the result will be the same. At the next CardDAV-Sync sync, the contact will disappear from all Android accounts, but still be visible in the Thunderbird Addressbook.

    I have an update to the issue above:
    Resyncing the Android a few times does not bring the contact back on the Android. But if I open the contact in Thunderbird’s Addressbook, make no changes and then close the contact, Thunderbird will immediately sync with Radicale. And then a resync on the Android will cause the contact to reappear in the correct account on the Android.

    Would you suspect the problem is with Radicale or with CalDAV-Sync? Do you think there are any settings that would change this behavior?

  21. Caesar Samsi

    Hey, I know I’m late to the party 🙂 But Thank You so much for providing this guide. I chose to implement the systemctl method to make radicale run as a daemon.

    It runs happily on my Raspberry Pi 2B box 🙂

  22. Hello, I’d appreciate your help with the following: radicale (CardDav part at least) is going to operate within LAN with 192.168.45.* subnet. Could you please suggest the “hosts = …” conf file line so as to allow connections from all machines within the subnet? Nothing works and I’m not sure what is to blame :/ Firewall is off.

  1. Pingback: Build a CalDav/CardDav server | 0ddn1x: tricks with *nix

  2. Pingback: Setting up a calendar infrastructure on your home server | ROELOF.INFO

  3. Pingback: Raspberry Pi: Radicale CalDAV und CardDAV Server installieren » Jan Karres

  4. Pingback: Radicale – calendario sul server con calDAV | vaseline deb

Leave a comment