Posséder mes données, partie 1 : intégrer une solution de calendrier auto-hébergée
(emilygorcenski.com)- Avec des déplacements professionnels et des voyages fréquents, combinés à la gestion de relations sur plusieurs fuseaux horaires, un système de calendrier auto-hébergé est devenu nécessaire pour réduire la dépendance aux Big Tech et garder le contrôle direct des données d’agenda
- La nouvelle architecture place le serveur CalDAV Baïkal au centre, agrège Airtrail, les e-mails IMAP et le calendrier ICS de l’école de langues dans CalDAV, puis les republie sous forme de fichiers
.icsà partager - La méthode consistant à écrire les événements en YAML puis à les convertir en ICS via une chaîne CI/CD suffisait pour un prototype, mais les erreurs manuelles et la charge de maintenance ont fini par remplacer l’approche par fichiers statiques
- Un script Python collecte et classe les événements toutes les 15 minutes, génère séparément des ICS pour la famille et pour le travail, et marque certains événements comme PRIVATE dans le calendrier professionnel
- Google Calendar et Google Script ne servent qu’à la synchronisation du calendrier professionnel ; après l’intégration de l’API Airtrail, une seule saisie de vol est répercutée dans le calendrier personnel en moins de 15 minutes, puis dans le calendrier professionnel en moins d’une heure
Pourquoi la gestion du calendrier est devenue complexe
- À cause des déplacements fréquents, il était difficile pour la famille, les amis et les collègues de savoir dans quel fuseau horaire l’auteur se trouvait ou s’il était à bord d’un vol, et coordonner des rendez-vous sur plusieurs fuseaux exigeait en permanence des calculs d’horaires
- Il fallait saisir en double dans plusieurs endroits les vols, les trains, les périodes de blocage avant embarquement et les temps de trajet vers l’aéroport, ce qui alourdissait la gestion de l’agenda
- Les limites de l’écosystème de calendrier existant concernaient les standards, les applications front-end et l’expérience utilisateur dans son ensemble
- Même lorsqu’un fournisseur d’e-mail créait des entrées de calendrier pour les vols, il pouvait omettre des correspondances ou se tromper de fuseau horaire
- L’
organizerdes entrées générées n’était pas toujours l’utilisateur, ce qui pouvait compliquer le partage ou la modification
- Les besoins allaient au-delà du simple stockage d’événements et incluaient aussi le partage et le contrôle
- Les événements devaient apparaître comme blocker dans le calendrier professionnel
- Le conjoint devait pouvoir s’abonner au calendrier
- La saisie d’un événement ne devait être nécessaire qu’une seule fois au maximum
- Les modifications devaient être possibles depuis plusieurs appareils
- Les données devaient rester sous contrôle direct
- Il n’était pas possible de partager le calendrier professionnel avec le conjoint
- Les exigences supplémentaires comprenaient l’import de pièces jointes
.icsreçues par e-mail, l’import HTTP du calendrier ICS de l’école de langues, l’intégration avec le tracker de vols auto-hébergé Airtrail, la différenciation par couleurs, un indicateur de confidentialité pour le calendrier professionnel, des rafraîchissements fréquents et la possibilité d’utiliser n’importe quel front-end
Là où l’approche YAML·ICS a atteint ses limites
- Les méthodes de partage existantes demandaient souvent une plateforme commune ou un environnement de compte identique pour offrir toutes les fonctionnalités
- L’écosystème Gmail ou Outlook.com
- Le partage entre comptes d’un même environnement comme Exchange
- Il existait deux contournements courants
- Publier des données iCal via HTTP sous forme de calendrier en lecture seule
- Envoyer un fichier iCal
.icspar e-mail
- La version initiale consistait à publier des fichiers
.icssur le site web à des URL publiques mais difficiles à deviner, avec plusieurs URL selon l’usage - Les données d’événements étaient écrites en YAML puis re-sérialisées en fichiers ICS par un petit script dans la pipeline CI/CD
- Cela suffisait pour un prototype, mais à mesure que le volume augmentait, les erreurs de saisie manuelle en YAML se multipliaient, et une tâche qui devait rester légère est devenue pesante
Une architecture repensée avec CalDAV et Baïkal
- La nouvelle architecture abandonne les fichiers statiques au profit d’un système hébergé basé sur CalDAV
- CalDAV est une extension de la spécification de création distribuée WebDAV qui fournit les fonctions nécessaires aux applications de calendrier
- Avec un serveur CalDAV, il devient possible de consulter et gérer les événements depuis plusieurs appareils, comme un ordinateur portable ou un téléphone, au moyen du front-end de son choix
- Comme il existe peu de serveurs CalDAV facilement abonnables sans authentification, il a fallu un script capable d’interroger périodiquement le serveur, d’en extraire les événements et de les republier sous forme de fichiers iCal sur le site web
- Le flux global est le suivant
- Interroger les sources de données pour récupérer les événements
- Publier les événements dans CalDAV de manière programmatique
- Récupérer tous les événements depuis CalDAV et les écrire dans des fichiers
.ics - Servir les fichiers
.icsen HTTP
Installation de Baïkal et connexion des clients
- L’outil retenu est Baïkal, un serveur CalDAV/CardDAV léger et auto-hébergé pour gérer calendriers et contacts
- L’image
ckulka/baikal:0.9.5est lancée avec Docker Compose, en définissant les ports et un volume local, puis démarrée avecdocker compose up -d - Baïkal peut utiliser MySQL, mais fonctionne aussi avec SQLite, dont l’administration est plus simple
- Un reverse proxy nginx est utilisé pour l’exposition web
proxy_passredirige vers le port local de Baïkal/.well-known/caldavest redirigé en 301 versdav.php- Cette redirection est nécessaire lors de l’ajout du calendrier dans l’application Calendrier sur iPhone ou Mac
- TLS a été configuré avec Let’s Encrypt et
certbot, qui met automatiquement à jour le fichier de configuration nginx - Après accès au domaine dans le navigateur, un compte administrateur a été créé, puis des utilisateurs et des calendriers ont été ajoutés
- La connexion a été établie avec les applications Calendrier par défaut sur macOS et iOS, en utilisant manual settings dans les réglages macOS/iOS plutôt que le mode automatique ou avancé
Classification des événements et visibilité dans le calendrier professionnel
- La spécification iCalendar prévoit une propriété optionnelle
CATEGORIESpour le composantEVENT, mais les outils utilisés, comme Calendar sur macOS, Calendar sur iOS ou Google Calendar, n’implémentent pas ce champ - Une classification en texte libre rend la cohérence difficile à maintenir, donc les types d’événements sont modélisés avec des enums Python
- Par exemple :
TerminType,CultureType,SocialType,AwayType,TransportType - Avec des valeurs comme
MEETUP,CONFERENCE,CLASS,APPOINTMENT,MEETING,EXAM
- Par exemple :
- La raison d’être de plusieurs groupes d’enums est d’organiser conceptuellement les types d’événements
- La logique définissant la visibilité dans le calendrier professionnel repose aussi sur ce système de classification
- Les valeurs d’enum à deux chiffres sont traitées par défaut comme private dans le calendrier professionnel
- Des événements comme un rendez-vous médical sont sérialisés comme privés dans un fichier de calendrier professionnel distinct
- Cette classification améliore la recherche et l’identification visuelle des événements, et facilite la lecture d’un coup d’œil dans les front-ends qui prennent en charge la différenciation par couleurs
Script Python de synchronisation et publication ICS
- Pour automatiser le tout, un script Python a été relié à une tâche cron
- Le script rassemble plusieurs entrées, les injecte dans Baïkal, puis les réexporte sous forme d’ICS partageables
- Import des événements depuis les e-mails via IMAP
- Extraction des événements de vol depuis l’API Airtrail
- Import du fichier ICS hébergé par l’école de langues
- Push des événements collectés vers Baïkal
- Récupération de tous les événements depuis Baïkal puis re-sérialisation en un ou plusieurs fichiers ICS partageables
- L’intégration IMAP permet d’importer automatiquement les invitations de calendrier reçues par e-mail et de les ajouter à l’agenda, offrant une fonction proche de Google Calendar
- Le script d’entrée exécuté par cron crée séparément un
Calendarfamilial et unCalendarprofessionnel, récupère les événements depuis Baïkal, puis applique une logique de branchement- Ajouter les événements à l’ICS familial
- N’ajouter les événements à l’ICS professionnel que si l’adresse e-mail professionnelle n’apparaît pas dans le résultat de sérialisation de l’événement
- Définir la classification sur
PUBLICouPRIVATEselon le résultat deis_work_public
- Le script d’intégration à Baïkal utilise des requêtes
PROPFINDet l’authentification HTTP Digest pour récupérer les événements distants - Si la description d’un événement contient le motif
CATEGORIES:, le script extrait la catégorie depuis le champ description, l’insère dansevent.categories, puis retire cette chaîne de la description - Les fichiers ICS de partage sont servis par nginx à des URL difficiles à deviner, générées à partir de chaînes de hachage aléatoires salées
- Cette tâche cron s’exécute toutes les 15 minutes
Synchronisation avec Google Calendar au travail
- Au-delà de la simple consultation des événements dans le calendrier personnel, il fallait que les périodes de déplacement et de vol apparaissent comme des créneaux bloquants dans le calendrier professionnel afin que les collègues puissent voir l’état de disponibilité
- La copie vers le calendrier professionnel utilise Google Script Engine
- Le script de base est une version modifiée de GAS-ICS-Sync
- Cette version modifiée lit la propriété
CATEGORIESdu calendrier et applique un codage couleur dans le calendrier professionnel - Google Script s’exécute toutes les 30 minutes
- L’utilisation de Google Calendar peut sembler contradictoire avec l’objectif de réduire la dépendance aux Big Tech, mais elle relève d’un environnement de travail imposé et non d’une dépendance pour l’usage personnel
Résultats en production et coûts
- Ce système est utilisé depuis environ six mois, avec quelques petites corrections et ajouts au fil du temps
- Le changement le plus récent est l’intégration de l’API Airtrail
- Lorsqu’un vol est réservé, les données sont saisies dans le tracker de vols
- L’événement apparaît dans le calendrier personnel en moins de 15 minutes
- Il est copié automatiquement dans le calendrier professionnel en moins d’une heure
- Pour des besoins de mobilité complexes, le temps consacré à la gestion de l’agenda a fortement diminué, ce qui s’est traduit par une amélioration de la qualité de vie
- Le coût global peut être maintenu au minimum, et l’ensemble peut facilement fonctionner sur un NAS domestique
- À l’heure actuelle, les données sont hébergées en Suisse et environ 100 dollars par mois de temps serveur sont payés pour faire tourner le site web et les intégrations
- Cette configuration est un peu excessive, et une optimisation est prévue avec le temps
- Le fait d’avoir pu tout mettre en place rapidement sur l’hôte Docker d’une instance VM justifiait ce coût supplémentaire, et la simplification de la gestion du calendrier permet déjà d’économiser l’équivalent de ces 100 dollars par mois en temps
1 commentaires
Commentaires sur Hacker News
Je pense que ça va faire réagir, mais CalDAV n’est pas terrible
Si c’était vraiment simple et excellent, il y aurait beaucoup plus de solutions CalDAV self-hosted et leur utilisabilité serait meilleure ; Radicale ne m’a pas impressionné non plus
En pratique, je n’avais qu’un seul fichier de calendrier à exposer pour moi-même, donc j’ai essayé d’implémenter directement un serveur CalDAV, mais même exposer un simple fichier était tellement peu intuitif et complexe que j’ai abandonné
Si l’on doit partager un calendrier avec quelqu’un via une app compatible CalDAV, je comprends l’intérêt, mais pour héberger un calendrier qu’on utilise seul, j’ai l’impression que c’est presque une perte de temps
À la place, au début, j’ai mis un fichier iCal mis à jour dynamiquement dans un bucket S3 et je le synchronisais avec ICSx5 sur Android. HTTPS suffisait, sans CalDAV
Cela dit, les apps de calendrier libres et open source pour Android restent insuffisantes, et comme ICSx5 ne fonctionne pas bien sur GrapheneOS, j’utilise maintenant Proton Calendar, qui prend en charge les liens directs vers des fichiers iCal, à peu près de la même façon
L’approche basée sur le format iCalendar est bonne, mais l’étendue de la prise en charge des fonctionnalités iCalendar varie beaucoup selon les logiciels de calendrier ; au final, on finit par mettre la plupart des métadonnées dans le champ description plutôt que dans des propriétés dédiées
Mon usage est un logiciel qui récupère des données depuis plusieurs sites comme Eventbrite, Meetup, des organisateurs de quiz de pub et des calendriers d’événements publics, ne garde que les événements sociaux qui m’intéressent, puis les fusionne dans un calendrier unique visible dans mon app de calendrier habituelle
En plus, nous avons énormément galéré à gérer les serveurs CalDAV non conformes d’Exchange et de Google, et les utilisateurs nous attribuaient tous ces problèmes
Maintenant que je travaille chez Google, je vois que les apps gCal utilisent des protocoles complètement différents
Au lieu d’être un format léger, il a été surconçu en essayant de faire trop de choses à la fois, et le résultat est un protocole en forme de pelote où s’entremêlent des idées différentes
Du coup, beaucoup de services n’essaient pas de respecter entièrement la spécification, parce qu’elle dépasse largement ce qu’ils veulent réellement faire
Les spécifications de formats de données du W3C semblent toujours finir comme ça ; c’est relativement moins le cas pour les spécifications de protocoles de bas niveau
Je l’ai lu il y a au moins 15 ans, mais je me souviens qu’il abordait aussi en partie la façon dont ce genre de protocole peut se perdre dans des comités pendant la conception
Le simple fait que ce projet ait commencé vers 2001 montre à quel point le problème des calendriers est un vieux casse-tête
Je le recommande si vous voulez comprendre pourquoi ce n’est pas terrible ; c’est aussi une bonne histoire sur le choc entre startups et open source, la création de produit et le développement logiciel en général
http://www.dreamingincode.com/ ; https://en.m.wikipedia.org/wiki/Dreaming_in_Code
Pour la synchronisation Android, j’utilise DAVX5, une app open source sans root qui fait tourner un service de synchronisation en arrière-plan, mais la configuration a posé beaucoup de problèmes, peut-être à cause de différences d’implémentation de CalDAV. La synchronisation de DAVX5 vers le calendrier ZOHO prend aussi longtemps
Evolution sur Ubuntu a une assez bonne prise en charge de CalDAV, mais il rafraîchit tout le calendrier à chaque bascule entre la vue mail et la vue calendrier. Le rafraîchissement du calendrier ZOHO est lent, et les limites de débit de ZOHO sont strictes, si bien qu’on finit en pratique par se faire soft-bloquer
La version récente de Thunderbird a une incompatibilité CalDAV où elle attend un autre code de succès HTTP. ZOHO renvoie 200, mais Thunderbird attend un autre code. À noter que le code CalDAV de Thunderbird est écrit en JS
Ce problème ne se produit qu’avec le deuxième calendrier, et dès qu’on ajoute le deuxième, ça commence à échouer. Au moins avec ZOHO, c’est assez pénible
Un autre serveur CalDAV recommandable est Radicale
Il est écrit en Python et conçu de façon assez modulaire, avec la possibilité d’ajouter des plugins pour l’authentification, l’autorisation, etc.
Les données sont stockées sous forme de fichiers texte simples, que je suis et sauvegarde avec git
Au fil du temps, j’ai accumulé quelques modifications intéressantes. L’authentification est gérée par pam sur le système hôte, et pour le partage de calendriers je lance un script périodique qui crée des liens symboliques vers les calendriers pour tous les utilisateurs autorisés. Il y a toutefois un problème d’explosion combinatoire
J’ai aussi ajouté des listes de contrôle d’accès avec un plugin d’autorisation utilisant des propriétés CalDAV personnalisées et un plugin web modifié
Les calendriers publics donnent un droit de lecture à l’utilisateur
publicvia les ACL, et un hack nginx autorise un accès global aux opérations de lectureCe calendrier public est visible dans un calendrier web : https://gitlab.nomagic.uk/popi/js_calendar_from_ics
Il faudrait que j’écrive un billet de blog sur cette configuration
C’est exactement l’article dont j’avais besoin
Sur mon serveur personnel, j’utilise le calendrier SoGO de Mailcow, et pour le travail j’utilise Fastmail, mais les deux ne s’entendent pas très bien
Je n’ai pas trouvé comment connecter correctement le calendrier Mailcow à d’autres outils, donc je passe du temps à le synchroniser de manière semi-manuelle
Ça fait un moment que je voulais séparer le calendrier, mais la seule alternative que je connaissais était Nextcloud, que je trouve un peu lourd
Baïkal a l’air bien, et j’ai hâte de l’essayer. Cela me permettrait aussi d’explorer le remplacement de Mailcow par un autre service mail self-hosted
Ces derniers temps, je suis en train de quitter le cloud de façon très agressive. J’avais plusieurs centaines de Go de données, mais même en migrant par à-coups, ça a pris moins de deux semaines, et ça fonctionne bien mieux que prévu
Le seul service que je confie encore à l’extérieur, c’est l’e-mail, parce que je n’ai pas envie de gérer les enregistrements MX ni IMAP/SMTP
Pour le reste, un Asus PN40 avec CPU Celeron double cœur m’a beaucoup aidé. Il est facilement accessible et dispose d’un emplacement M.2 NVME et d’un slot pour disque SATA, ce qui permet de mettre en place une sauvegarde sûre au même endroit
Je suis d’accord pour dire que CalDAV inspire un peu la méfiance, mais Nextcloud a couvert l’essentiel de mes besoins. Même avec Redis, certaines opérations peuvent être lentes, mais il gère très bien le calendrier, le remplacement de Dropbox/Google Drive, les documents, les photos, les sauvegardes et la synchronisation automatique
En ajoutant à cela plusieurs solutions open source, on couvre aussi le streaming de musique et de vidéos, le monitoring, les notifications, le VPN, le lecteur RSS, les outils d’administration et toutes sortes d’utilitaires
Même si ce mini-PC est plutôt peu puissant, mon FAI est excellent, donc il encaisse tout avec beaucoup de marge, au point qu’il pourrait probablement supporter 5 ou 6 personnes de plus comme moi sans problème
On a l’impression que l’ancien redevient nouveau
Au début des années 2000, j’hébergeais mon calendrier avec Mozilla Sunbird via le module IIS WebDAV de mon serveur personnel Win2k
Je crois que CardDAV n’existait pas encore, mais je peux me tromper
J’ai fini par importer toutes ces données dans Google Calendar, et c’est assez amusant parce qu’en remontant loin, il reste même des choses comme des devoirs de fac
Il m’est arrivé de perdre des rendez-vous parce que certains n’étaient pas envoyés au serveur, et je l’utilisais en CalDAV avec un serveur DAViCal
Sunbird a été abandonné, et je n’ai pas vérifié récemment s’il existe un remplaçant correct qui tourne sous Windows
Baikal a l’air intéressant
J’ai utilisé DAViCal autrefois pour partager des calendriers entre quelques appareils Apple iOS. Quand ça marchait, ça marchait bien, mais au fil des versions d’iOS ça a semblé devenir instable, et j’ai fini par abandonner
Si je m’y replonge un jour, je regarderai DAViCal et Radicale, et maintenant Baikal aussi
https://www.davical.org/
https://radicale.org/v3.html
Je suis récemment passé à Nextcloud, parce que mon hébergeur mutualisé prend en charge le déploiement et que l’interface Web intégrée réduit nettement la charge de configuration
J’utilise Baikal depuis plusieurs années, et c’est plutôt solide. Cela dit, je suis seul à l’utiliser et je n’ai pas toutes les exigences du billet original
Sur desktop, je m’y connecte avec le calendrier intégré de Thunderbird, et sur téléphone j’utilise DAVx5 et Fossify Calendar depuis F-Droid
Fossify Calendar est un fork de l’application Calendar de Simple Mobile Tools, mais malgré son nom, c’est l’application de calendrier la plus riche en fonctionnalités que j’aie vue jusqu’ici
J’aime sa simplicité, qui consiste à afficher toutes les options directement, sans vous obliger à fouiller dans plusieurs menus et boîtes de dialogue
Au travail j’utilise Outlook, et à la maison Google Calendar, mais la synchronisation via HTTP est totalement instable
Ça semble constamment casser les fuseaux horaires, et parfois les événements sont publiés en UTC, parfois non, donc les heures de réunion sont toujours fausses
Je ne comprends pas pourquoi ces deux grands fournisseurs n’arrivent pas à corriger une fonction aussi basique
Si utiliser mon propre système réglait le problème, je le ferais tout de suite, mais j’ai peur de retrouver exactement le même cas où une réunion créée dans Outlook est importée avec deux heures de décalage
De plus, beaucoup d’entreprises interdisent en pratique la synchronisation entre calendriers personnels et professionnels à cause des risques de fuite de données
J’aimerais faire ce genre de chose aussi pour les photos. Je veux me détacher de Dropbox et Google depuis un moment, et mes priorités sont au nombre de deux
D’abord, je veux créer quelque chose comme une fonction de souvenirs à partir de mes photos et l’envoyer sur mon téléphone. L’idée serait de regrouper selon des critères comme les anniversaires, les activités similaires,
moi et X (X étant mon conjoint, ma famille, mes amis, etc.), ou l’évolution au fil du tempsEnsuite, il faut que les photos prises sur mes appareils puissent être stockées sur mon serveur
J’ai préparé trois machines TrueNAS avec 2 To d’espace, réparties dans des lieux différents, et j’aimerais construire ça progressivement
https://www.synology.com/en-global/dsm/feature/photos
https://www.synology.com/en-global/dsm/feature/moments
Une autre option consiste à utiliser DecSync sans serveur
Thunderbird ou Evolution se synchronise avec l’application Android, et calendriers, contacts, tâches et RSS sont répliqués vers d’autres pairs. C’est aussi disponible sur F-Droid
https://github.com/39aldo39/DecSync