Logo RadicaleUn des services indispensables pour s’affranchir de Google en s’auto-hébergeant est le serveur de calendrier et de contacts. On va ici installer le logiciel Radicale, serveur calDAV et cardDAV simple.

Il existe plusieurs alternatives (DAVical, Baïkal, OwnCloud, etc.), mais Radicale est l’un des plus simples à mettre en œuvre pour un serveur auto-hébergé familial. Il ne demande aucune base de donnée, et n’ayant pas d’interface d’administration il se personnalise facilement via des fichiers de configuration.

Installation

La version présente dans les dépôts de Ubuntu 14.04 LTS est assez ancienne (0.8, au lieu de 0.10 à l’heure où je rédige ce tutoriel), il vaut donc mieux l’installer par une méthode alternative. Il est possible de l’installer par un sudo pip install radicale, de créer un utilisateur dédié, de mettre en place un script init, etc. mais j’ai trouvé mieux.

Ce logiciel étant très simple, sans dépendances particulières (python et adduser, autant dire rien du tout), est possible d’aller chercher les packages .deb de la version 0.10 sur les dépôts d’Ubuntu 15.10 et de les installer manuellement :

wget http://fr.archive.ubuntu.com/ubuntu/pool/universe/r/radicale/radicale_0.10-2_all.deb
wget http://fr.archive.ubuntu.com/ubuntu/pool/universe/r/radicale/python-radicale_0.10-2_all.deb
sudo dpkg -i python-radicale_0.10-2_all.deb
sudo dpkg -i radicale_0.10-2_all.deb

Radicale est désormais installée proprement, avec son utilisateur, ses dossiers de travail, son script init, etc.

Comme j’utiliserai l’authentification via LDAP, je dois installer le paquet python-ldap :

sudo aptitude install python-ldap

Configuration

Dans un premier temps, il faut activer le daemon via un sudo vim /etc/default/radicale et décommenter la ligne ENABLE_RADICALE=yes

Le service peut désormais se lancer avec un  :

sudo service radicale start

Configuration de Radicale

La configuration se fait dans le dossier /etc/radicale/, dans le fichier config. Pour exemple, voici le mien, sans les commentaires et nettoyé des informations personnelles :

[server]
hosts = 0.0.0.0:5232, [::]:5232
base_prefix = /radicale/
realm = Radicale - Mot de passe necessaire

[encoding]
request = utf-8
stock = utf-8

[well-known]
caldav = '/%(user)s/caldav/'
carddav = '/%(user)s/carddav/'

[auth]
type = LDAP
ldap_url = ldap://localhost:389/
ldap_base = ou=user,dc=exemple,dc=fr
ldap_attribute = mail
ldap_filter = (objectClass=posixAccount)
ldap_scope = OneLevel

[git]

[rights]
type = from_file
file = /etc/radicale/rights

[storage]
type = filesystem
filesystem_folder = /var/lib/radicale/collections

[logging]
config = /etc/radicale/logging
#debug = True
#full_environment = False

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

Une fois le fichier modifié, un sudo service radicale restart est requis.

Pour information, vous pouvez trouver l’ensemble des options par défaut (qui n’ont donc pas besoin d’être inscrites explicitement dans le fichier config, sauf en cas de modification) directement dans la source du logiciel.

Vous remarquerez que je n’active pas le chiffrement de la communication, car c’est le serveur web (Nginx) qui s’en chargera avant de “proxifier” les requêtes.

En cas de souci, vous pouvez procéder par étapes (utiliser l’authentification locale avec un fichier htpasswd, ou bien les droits “None”, etc.), tout en activant les logs Debug (attention, c’est très, très, verbeux).

Configuration du fichier “rights”

Comme nous avons choisi de gérer des droits manuellement, il faut créer le fichier /etc/radicale/rights. Voici le mien :

## Configurations par défaut ##
# Ce sont les options par défaut proposées pour l'authentification.
# Voici ce à quoi elles correspondent exactement.

# "authenticated" #
#[authenticated-rw]
#user:.+
#collection:.*
#permission:rw

# "owner_write" #
#[authenticated-r]
#user:.+
#collection:.*
#permission:r

#[owner-write-w]
#user:.+
#collection:^%(login)s(/.*)?$
#permission:w

# "owner_only" #
[owner-only]
user:.+
collection:^%(login)s(/.*)?$
permission:rw

## Ajouts personnels ##
# Collections publiquement lisibles si elles sont nommées public-abc123
[anon-read-public]
user: .*
collection: ^.+/public-.+$
permission: r

# Collections accessibles en lecture et écriture par les autres utilisateurs
# authentifiés, nommées shared-rw-abc123
[users-read-write-shared]
user: .+
collection: ^.+/shared-rw-.+$
permission: rw

# Collections accessibles en lecture par les autres utilisateurs authenifiés,
# nommées shared-r-abc123
[users-read-shared]
user: .+
collection: ^.+/shared-r-.+$
permission: r

# On peut créer un dossier complet dans lequel toutes les collections seront
# accessibles en lecture, ici le dossier /public/
#[public]
#user: .*
#collection: ^public(/.+)?$
#permission: r

# On peut utiliseur le nom de domaine des utilisateurs pour leur donner des
# accès particuliers
#[domain-wide-access]
#user: ^.+@(.+)\..+$
#collection: ^{0}/.+$
#permission: r

On peut ensuite ajouter des règles spécifiques à un utilisateur ou une collection précis. De plus, l’ordre dans lequel les règles sont créées importe peu.

Personnellement, je me méfie grandement de la possibilité qui serait donnée à un utilisateur anonyme (“.*”) d’écrire quoi que ce soit sur mon serveur, donc je n’active pas cette options.

Configuration du serveur web

Maintenant que Radicale est configuré et lancé, il faut configurer le serveur web, Nginx dans mon cas.

Créons (ou complétons) le fichier /etc/nginx/sites-available/machin.exemple.fr et mettons ceci dedans :

# Dans un premier temps, on redirige tout vers le port 443 sécurisé
server {
    listen  80;
    listen  [::]:80;

    server_name machin.exemple.fr;

    rewrite ^   https://$server_name$request_uri? permanent;
}

# Ensuite, on configure le tout dans la section dédiée au https
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name machin.exemple.fr;

    root   /var/www/machin.exemple.fr;
    index  index.html index.htm index.php;

    access_log  /var/log/nginx/cloud.arnoux.lu.access.log;  
    error_log /var/log/nginx/cloud.arnoux.lu.error.log;

    ssl_certificate /chemin/vers/certificat-ssl.pem;
    ssl_certificate_key /chemin/vers/cle-privee-ssl.key;

    # On gère les redirections utiles
    location / {
        rewrite ^/.well-known/carddav /radicale/$remote_user/carddav/ redirect;
        rewrite ^/.well-known/caldav /radicale/$remote_user/caldav/ redirect;
    }

    # On "proxifie" les requêtes à destination de /radicale/
    # On ajoute quelques entêtes utiles pour que Radicale ait accès à l'adresse IP réelle du client
    location /radicale {
        proxy_pass http://localhost:5232;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }

}

Configuration des DNS

Dans la configuration du serveur web, on a défini les URI “.well-known”, qui facilitent l’auto-configuration de certains clients, et la découverte des collections (calendriers ou carnets d’adresses) existantes.

Dans le cas où le nom d’utilisateur que nous utilisons est une adresse email, il est possible d’activer une étape supplémentaire d’auto-configuration, [grâce à un enregistrement SRV](https://tools.ietf.org/html/rfc6764#section-3].

Pour des adresse email de la forme utilisateur@domaine.com, et un serveur Radical qui se trouve sur l’ordi machin.exemple.fr, ajoutons ces enregistrements dans la zone DNS de domaine.com :

\_caldavs.\_tcp 10800   IN  SRV 0 1 443 machin.exemple.fr.
\_carddavs.\_tcp 10800  IN  SRV 0 1 443 machin.exemple.fr.

Je n’ai volontairement pas mis les enregistrements non sécurisés (_caldav._tcp et _carddav._tcp), puisque je ne veux que des accès sécurisés à mon serveur.

Création des collections

Certains clients, tel que DAVdroid, nécessitent que les collections existent déjà pour pouvoir les utiliser. Il faut donc les créer préalablement à toute utilisation. Comme l’explique ce billet similaire au mien(en), il est possible d’utiliser le programme cadaver, mais dans le cas de Radicale, il y a plus simple : simplement en accédant au calendrier à l’aide d’un navigateur internet.

Dans notre navigateur favori (Firefox, bien évidemment), il suffit d’accéder à la ressource “https://machin.exemple.fr/radicale/user@domaine.com/calendrier.ics/”. Entrez un nom d’utilisateur qui a un droit d’écriture sur cette ressource (user@domaine.com dans notre cas) ainsi que son mot de passe, et vous récupérerez un calendrier vide, qui aura été créé à la volée par Radicale.

Terminez bien l’URL par un “/”. Vous pouvez nommez les calendriers et listes de tâche avec ou sans extension “.ics” (“calendrier.ics”, “todo.ics”, ou bien simplement “calendrier”), mais les carnets d’adresse doivent avoir l’extension “.vcf” (“adressbook.vcf”) afin de ne pas être identifiés comme des calendriers. Cela créera un fichier du même nom dans l’arborescence des collections de Radicale.

Étapes supplémentaires

Intégration à fail2ban

Par sécurité, comme pour tout service ouvert sur l’extérieur et offrant un système d’authentification, il faut surveiller les tentatives ratées d’authentification.

Cela se fait avec fail2ban, mais il faut avoir accès à un fichier de log dans lequel apparait l’adresse IP du client. Par défaut, ce n’est pas possible dans Radicale, mais j’ai trouvé une astuce nécessitant de modifier le logiciel lui-même.

C’est d’ailleurs pour cela que j’ai ajouté l’entête X_Forwarded_For dans la configuration de Nginx. Il faut désormais accéder à cet entête.

Cela se passe dans le fichier /usr/lib/python2.7/dist-packages/radicale/__init__.py. Éditez-le en root, et modifiez la ligne suivante (qui devrait se trouver à la ligne 339) :

log.LOGGER.info("%s refused" % (user or "Anonymous user")

Afin qu’elle ressemble à cela :

log.LOGGER.info("%s refused from host %s" % (user or "Anonymous user", environ.get("HTTP_X_FORWARDED_FOR").split(", ")[0]))

fail2ban pourra désormais accéder à l’adresse IP du client dont l’authentification a échoué, ou auquel un accès a été refusé, via le fichier de log /var/log/radicale/radicale.log. La configuration de fail2ban fera l’objet d’un autre billet.

Suivi du projet

Afin de suivre les évolutions du projet, et de rester vigilant quant aux possibles découvertes de failles de sécurité, abonnez-vous au flux RSS de Radicale, et à la mailing list du projet (envoyez un mail, peu importe son contenu, à cette adresse. Ce premier mail sera supprimé après avoir lancé la procédure d’inscription).

Sources :

  • https://blogobramje.nl/posts/How_to_run_radicale_behind_nginx/
  • http://www.rezine.org/documentation/auto-hebergement/services/agenda-contact/serveurs-cal-card/#index3h1
  • http://www.pihomeserver.fr/2013/08/17/raspberry-pi-home-server-installer-radicale-pour-gerer-vos-contacts-et-calendriers/