rss logo

Mettre en place un serveur Roundcube avec support de CalDAV sur Debian

Logo Rouncube Calendrier Rouncube

Dans un article précédent, j'ai abordé la mise en place d'un serveur de calendriers partagés CalDAV (voir ). Dans le cadre de ma démarche visant à me séparer de la solution Zimbra, je devais trouver une solution pour accéder aux e-mails et à un calendrier partagé via une interface Web. Je me suis dirigé vers Roundcube bien qu'il ne supporte pas nativement la fonctionnalité de calendrier.

Et nous allons justement voir ici comment configurer un serveur Roundcube avec une base de données SQLite3 sur Debian (facile !) ainsi que l'ajout d'un plugin de calendrier (un peu moins facile :/) qui permettra de se connecter à un calendrier partagé CalDAV.

Pour cette configuration, j'ai opté pour la base de données SQLite3, idéale pour un petit nombre d'utilisateurs, ainsi que l'utilisation des paquets Debian de Roundcube pour une mise à jour et une maintenance facilités. Pour ajouter le calendrier à Roundcube, j'ai choisi le plugin JodliDev/calendar, disponible gratuitement sur https://github.com/JodliDev/calendar. Car il semble toujours être pris en charge et permet de se connecter à un serveur CalDAV. Un grand merci à JodliDev et aux contributeurs de la communauté, Offerel et mtudury, pour leurs contributions précieuses.

Les prérequis incluent un serveur SMTP et IMAP fonctionnel pour la messagerie Web, ainsi qu'un serveur de partage de calendrier CalDAV. De plus, il est important de noter qu'au moment de la rédaction de cet article, la solution ne prend en charge qu'un seul calendrier. En effet je n'ai pas encore réussi à ajouter d'autres calendriers en parallèle. Espérons que le plugin sera mis à jour dans les mois à venir pour combler cette lacune.

  • Configuration:
    • debian: 12 bookworm
    • php: 8.2
    • roundcube: 1.6.5
    • sqlite3: 3.40

Roundcube

Installation

  • Installation des packages :
root@host:~# apt update && apt install roundcube sqlite3 roundcube-plugins roundcube-sqlite3
  • Répondre oui pour configurer la base de données :
Processus d'installation des paquets Roundcube sur un système Debian demandant de configurer la base de données
  • Éditez le fichier /etc/apache2/conf-enabled/roundcube.conf et décommentez cette ligne :
Alias /roundcube /var/lib/roundcube/public_html […]

Configuration

Ici, le serveur de messagerie dispose de certificats Let's Encrypt associés aux services imaps et smtps. Il faut donc dans ce cas, utiliser les noms et le mot-clé ssl:// pour se connecter.

  • Éditer le fichier de configuration /etc/roundcube/config.inc.php. Il est indiqué qu'il est judicieux de modifier la clé des_key, alors faites-le si vous le souhaitez :):
$config['imap_host'] = ["ssl://mx.std.rocks:993"]; $config['smtp_host'] = 'ssl://mx.std.rocks:465'; // This key is used to encrypt the users imap password which is stored // in the session record. For the default cipher method it must be // exactly 24 characters long. // YOUR KEY MUST BE DIFFERENT THAN THE SAMPLE VALUE FOR SECURITY REASONS $config['des_key'] = 'PaaKtcPFfopJxHHyTe9rahk3';
  • Redémarrer le service apache2 :
root@host:~# systemctl restart apache2
  • La page web de Roundcube devrait être accessible via HTTP (ex : http://IP_ROUNDCUBE/roundcube) :
Interface web d'authentification Roundcube

Activer HTTPS

Par souci de sécurité, il est conseillé d'activer les connexions HTTPS pour accéder à Roundcube. Voyons comment faire.

  • Activer le module ssl d'Apache :
root@host:~# a2enmod ssl

Let's Encrypt

  • Si vous avez des certificats Let's Encrypt, éditez le fichier /etc/apache2/sites-available/default-ssl.conf :
SSLCertificateFile /etc/letsencrypt/roundcube.std.rocks/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/roundcube.std.rocks/privkey.pem SSLCertificateChainFile /etc/letsencrypt/roundcube.std.rocks/chain.pem

Certificats auto-signés

  • Sinon (dans le cas ou on ne dispose pas de certificats Let's Encrypt), on pourra créer un certificat auto-signé :
root@host:~# mkdir /etc/apache2/ssl/ root@host:~# openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -keyout /etc/apache2/ssl/selfsigned.key -out /etc/apache2/ssl/selsigned.crt root@host:~# cat /etc/apache2/ssl/selfsigned.key /etc/apache2/ssl/selsigned.crt > /etc/apache2/ssl/cert.pem

Finaliser la Configuration

  • Éditer le fichier de configuration /etc/apache2/sites-available/default-ssl.conf :
DocumentRoot /var/lib/roundcube/public_html/ #AUTOGENERATE CERTIFICATES SSLCertificateFile /etc/apache2/ssl/cert.pem SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key
  • Éditer le fichier de configuration /etc/apache2/ports.conf et désactiver http:
#Listen 80
  • Activer la configuration ssl et redémarrer le service apache2 :
root@host:~# a2ensite default-ssl root@host:~# systemctl restart apache2

Prérequis

Remarque : Pour éviter la limite de téléchargement GitHub, nous devons ouvrir un compte (gratuit) sur ce dernier afin d'obtenir un jeton OAuth. Une fois le compte créé, se rendre sur la page https://github.com/settings/tokens afin de générer un nouveau jeton.

  • Considérations à prendre en compte concernant le serveur CalDAV :
    • Si HTTPS est utilisé, il faudra s'assurer que le serveur CalDAV utilise un certificat valide; sinon, on pourra au choix s'y connecter via HTTP ou déclarer le certificat racine de ce dernier sur le serveur Roundcube comme étant de confiance.
    • Utiliser une authentification Basic

Authentification Basic

  • Configurer le calendrier distant avec l'authentification Basic ; par exemple ici, avec un serveur de calendrier partagé Baïkal :
Menu de type d'authentification WebDAV de Baïkal

Serveur CalDAV avec certificat auto-signé

Si un certificat auto-signé est utilisé sur le serveur CalDAV, alors on pourra utiliser HTTP (bof niveau sécurité) ou ajouter le certificat racine dans le serveur Roundcube pour qu'il soit reconnu comme fiable. Voyons comment faire cela toujours avec Baïkal.

Activer HTTP

  • Depuis le serveur Baïkal, éditer le fichier /etc/apache2/sites-available/000-default.conf :
<VirtualHost *:443> DocumentRoot /var/www/baikal/html ServerName baikal.std.rocks RewriteEngine On # Generally already set by global Apache configuration #RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteRule /.well-known/carddav /dav.php [R=308,L] RewriteRule /.well-known/caldav /dav.php [R=308,L] <Directory "/var/www/baikal/html"> Options None # If you install cloning git repository, you may need the following Options +FollowSymlinks AllowOverride None # Configuration for apache-2.4: Require all granted # Configuration for apache-2.2: # Order allow,deny # Allow from all </Directory> <IfModule mod_expires.c> ExpiresActive Off </IfModule> SSLEngine On #AUTOGENERATE CERTIFICATES SSLCertificateFile /etc/apache2/ssl/cert.pem SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key </VirtualHost> <VirtualHost *:80> DocumentRoot /var/www/baikal/html ServerName dav.example.org RewriteEngine On # Generally already set by global Apache configuration #RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteRule /.well-known/carddav /dav.php [R=308,L] RewriteRule /.well-known/caldav /dav.php [R=308,L] <Directory "/var/www/baikal/html"> Options None # If you install cloning git repository, you may need the following Options +FollowSymlinks AllowOverride None # Configuration for apache-2.4: Require all granted # Configuration for apache-2.2: # Order allow,deny # Allow from all </Directory> <IfModule mod_expires.c> ExpiresActive Off </IfModule> #SSLEngine on #AUTOGENERATE CERTIFICATES #SSLCertificateFile /etc/apache2/ssl/cert.pem #SSLCertificateKeyFile /etc/apache2/ssl/selfsigned.key #LETS ENCRYPT CERTIFICATES #SSLCertificateFile /etc/letsencrypt/baikal.std.rocks/fullchain.pem #SSLCertificateKeyFile /etc/letsencrypt/baikal.std.rocks/privkey.pem #SSLCertificateChainFile /etc/letsencrypt/baikal.std.rocks/chain.pem </VirtualHost>

Installer le certificat racine auto-signé sur le serveur Roundcube

  • Copier le certificat racine /etc/apache2/ssl/selsigned.crt du serveur CalDAV dans le dossier /usr/local/share/ca-certificates/ du serveur Roundcube puis exécutez update-ca-certificates :
root@host:~# cp selsigned.crt /usr/local/share/ca-certificates/ root@host:~# update-ca-certificates Updating certificates in /etc/ssl/certs... rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL 1 added, 0 removed; done. Running hooks in /etc/ca-certificates/update.d... done.

Plugin Calendrier

Installer le Plugin

Il est maintenant temps d'installer le plugin de calendrier sur le serveur Roundcube !

  • Installer les paquets nécessaires :
root@host:~# apt update && apt install php-sabre-* php-curl composer wget
  • Changer de répertoire vers /var/lib/roundcube/ :
root@host:~# cd /var/lib/roundcube/
  • Créer un fichier composer.json :
{ "name": "roundcube/calendar", "type": "roundcube-plugin", "description": "Calendar plugin", "homepage": "https://git.kolab.org/diffusion/RPK/", "license": "AGPLv3", "version": "3.5.11", "authors": [ { "name": "Thomas Bruederli", "email": "bruederli@kolabsys.com", "role": "Lead" }, { "name": "Aleksander Machniak", "email": "machniak@kolabsys.com", "role": "Developer" } ], "repositories": { "libcalendaring": { "type": "vcs", "url": "https://github.com/JodliDev/libcalendaring" }, "calendar": { "type": "vcs", "url": "https://github.com/JodliDev/calendar" }, "0": { "type": "composer", "url": "https://plugins.roundcube.net" }, "1": { "type": "vcs", "url": "https://github.com/JodliDev/libcalendaring" } }, "require": { "php": ">=5.5", "roundcube/plugin-installer": ">=0.1.3", "jodlidev/libcalendaring": "dev-master", "kolab/libkolab": ">=3.4.0", "sabre/dav": ">=4.1.5" }, "extra": { "roundcube": { "min-version": "1.4.0", "sql-dir": "drivers/database/SQL" } }, "minimum-stability": "dev" }
  • Lancer l'outil composer afin d'installer le plugin de calendrier et renseigner le token GitHub du compte précédement créé lorsque demandé :
root@host:~# composer -vv require kolab/calendar Do not run Composer as root/super user! See https://getcomposer.org/root for details Continue as root/super user [yes]? yes […] Reading composer.json of kolab/calendar (3.2.16) GitHub API limit (60 calls/hr) is exhausted, could not fetch https://api.github.com/repos/JodliDev/calendar/contents/composer.json?ref=a0aacd4a737e48189cfb5a82463e8b9fe16d56ea. Create a GitHub OAuth token to go over the API rate limit. You can also wait until 2024-02-09 16:43:21 for the rate limit to reset. When working with _public_ GitHub repositories only, head to https://github.com/settings/tokens/new?scopes=&description=Composer+on+roundcube+2024-02-09+1543 to retrieve a token. This token will have read-only permission for public information only. When you need to access _private_ GitHub repositories as well, go to https://github.com/settings/tokens/new?scopes=repo&description=Composer+on+roundcube+2024-02-09+1543 Note that such tokens have broad read/write permissions on your behalf, even if not needed by Composer. Tokens will be stored in plain text in "/root/.config/composer/auth.json" for future use by Composer. For additional information, check https://getcomposer.org/doc/articles/authentication-for-private-packages.md#github-oauth Token (hidden): GIT_TOKEN […] roundcube/plugin-installer contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins Do you trust "roundcube/plugin-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] Y […] 12/15 [======================>-----] 80% 1 sec/1 sec Do you want to activate the plugin libkolab? [Y|n] Y Updated local config at /etc/roundcube/config.inc.php Creating package config file Do you want to activate the plugin libcalendaring? [Y|n] Y Updated local config at /etc/roundcube/config.inc.php 14/15 [==========================>-] 93% 1 min/1 min Do you want to activate the plugin calendar? [Y|n] Y

Installer les correctifs pour PHP8 et SQLite

Maintenant, il faut passer à l'ajout des correctifs pour Debian 12 car ce dernier utilise PHP 8 et le plugin semble avoir été développé pour PHP 7. Les correctifs sont disponibles sur la page officielle du plugin sur GitHub : https://github.com/JodliDev/calendar/pulls.

Correctifs PHP

  • Télécharger les fichiers corrigés et copier-les dans leurs dossiers respectifs :
root@host:~# wget https://raw.githubusercontent.com/JodliDev/calendar/e50160c2e1be4dca42788e7de9436fca1216f9f3/drivers/caldav/caldav_client.php root@host:~# mv ./caldav_client.php /var/lib/roundcube/plugins/calendar/drivers/caldav/caldav_client.php root@host:~# wget https://raw.githubusercontent.com/JodliDev/calendar/fa24c2f1ba0a72d83bd717fc5852a69366e39db2/calendar.php root@host:~# mv ./calendar.php /var/lib/roundcube/plugins/calendar/calendar.php root@host:~# wget https://raw.githubusercontent.com/JodliDev/calendar/2e526d5977da44e35722e332f0c3fc51034746ad/drivers/caldav/caldav_driver.php root@host:~# mv caldav_driver.php /var/lib/roundcube/plugins/calendar/drivers/caldav/caldav_driver.php

Correctifs SQLite

Nous allons maintenant appliquer les correctifs pour la base de données SQLite (qui a dit que c'était une bonne idée de l'utiliser?)!

calendar.php
  • Modifier au niveau de la ligne 439 dans /var/lib/roundcube/plugins/calendar/calendar.php :
//$select->add($choices); foreach ($choices as $choice) { $select->add($choice, $choice); }
sqlite.initial.sql
  • Télécharger le fichier sqlite.initial.sql et appliquer le patch :
root@host:~# wget https://raw.githubusercontent.com/JodliDev/calendar/c221f134063f21047cd9c2aefa120c6903dc84bd/drivers/caldav/SQL/sqlite.initial.sql root@host:~# sqlite3 /var/lib/dbconfig-common/sqlite3/roundcube/roundcube < sqlite.initial.sql
caldav_driver.php
  • Modifier au niveau de la ligne 301 dans /var/lib/roundcube/plugins/calendar/drivers/caldav/caldav_driver.php :
//if($this->rc->db->affected_rows($result)) continue; if($this->rc->db->num_rows($result) > 0) continue;
  • Modifier au niveau de la ligne 2066 dans /var/lib/roundcube/plugins/calendar/drivers/caldav/caldav_driver.php :
//$base_uri = $tokens['scheme']."://".$tokens['host'].(isset($tokens['port']) ? ":".$tokens['port'] : null); $base_uri = $tokens['scheme']."://".$tokens['host'].($tokens['port'] ? ":".$tokens['port'] : null);
  • Modifier au niveau de la ligne 2266 dans /var/lib/roundcube/plugins/calendar/drivers/caldav/caldav_driver.php :
// no local event -> create event // else else if(isset($update["remote_event"]))
  • Modifier au niveau de la ligne 2305 dans /var/lib/roundcube/plugins/calendar/drivers/caldav/caldav_driver.php:
private function _is_synced($cal_id) { //ADD THIS LINES : if ($this->rc->db->db_provider == 'sqlite') { // this is a minimal $query = $this->rc->db->query( "UPDATE ".$this->db_calendars." ". "SET caldav_last_change = CURRENT_TIMESTAMP WHERE calendar_id = ?", $cal_id); return false; }
calendar_ui.php
  • Commenter les lignes 52 à 61 dans le fichier /var/lib/roundcube/plugins/calendar/lib/calendar_ui.php :
//$this->cal->add_button([ // 'command' => 'calendar', // 'class' => 'button-calendar', // 'classsel' => 'button-calendar button-selected', // 'innerclass' => 'button-inner', // 'label' => 'calendar.calendar', // 'type' => 'link' // ], // 'taskbar' //);
Redémarrer apache
  • Redémarrer le service apache2 :
root@host:~# systemctl restart apache2

Connecter Roundcube au calendrier partagé

  • Se connecter à Roundcube, l'icône du calendrier devrait apparaître :
Interface web de Roundcube avec le plugin de calendrier
  • Dans le menu du calendrier, sélectionner Ajouter des sources CalDAV :
Roundcube ajoutant un menu de sources CalDAV
  • Remarque : on pourra récupérer l'URI complète depuis le serveur CalDAV; voici un exemple avec l'incontournable Baïkal :
URI du calendrier partagé depuis le serveur Baïkal
  • Ajouter le serveur CalDAV, voici un exemple avec une connexion HTTP :
Roundcube ajoutant une fenêtre de sources CalDAV
  • Ou, si on utilise un serveur HTTPS, noter que l'on doit spécifier le nom correspondant au certificat, sinon, la connexion ne sera pas établie :
Roundcube ajoutant une fenêtre de sources CalDAV
  • Une fois terminé, on pourra (enfin!) profiter de l'utilisation de son calendrier partagé CalDAV via Roundcube :
Roundcube accédant à une fenêtre de calendrier CalDAV