J'ouvre le code de go-webdav, mon serveur WebDAV modulaire
TL;DR : J’ai ouvert le code de go-webdav, un serveur WebDAV en Go qui permet de stocker ses fichiers sur différents backends (S3, SQLite, système de fichiers local). Le projet est né d’un besoin personnel de sauvegarder les photos de mon fils sans dépendre des GAFAM.
Le problème des photos de famille
Il y a quelques mois, mon fils est né. Au milieu de la joie et de la fatigue, une pensée m’a traversé l’esprit en regardant mon smartphone : “Si je perds ce téléphone, je perds toutes ces photos.”
La solution évidente serait d’utiliser Google Photos, iCloud ou OneDrive. Mais en tant que libriste convaincu, l’idée de confier mes souvenirs de famille aux GAFAM me dérange profondément. Je veux garder le contrôle sur mes données, pouvoir les migrer facilement, et ne pas être prisonnier d’une plateforme propriétaire.
Mon NAS à la maison est une première réponse, mais elle n’est pas suffisante : tout stocker chez soi, en un seul endroit, ce n’est pas une stratégie viable pour de l’archivage long terme. Un incendie, un cambriolage, une défaillance matérielle… les scénarios catastrophes ne manquent pas.
Et pourquoi ne pas utiliser un logiciel libre existant ?
Parce que j’y perdrais tout le plaisir de créer quelque chose moi-même ! 😉
La solution : WebDAV + S3
J’ai donc décidé de construire ma propre solution, basée sur deux constats :
-
Le stockage S3 est devenu ridiculement bon marché. Le protocole S3 est un standard de facto, et de nombreux fournisseurs proposent du stockage compatible à des prix très compétitifs.
-
WebDAV est un protocole simple et universel. Il est supporté nativement par Linux, Android, Windows, macOS. Mon épouse peut accéder aux photos depuis son smartphone Android, ma mère depuis son PC Windows, sans installer quoi que ce soit de complexe.
C’est ainsi qu’est né go-webdav : un serveur WebDAV écrit en Go, capable de s’interfacer avec différents backends de stockage.
Sur les épaules de géants
Avant toute chose, un point important : go-webdav ne réinvente pas la roue. Le projet s’appuie sur l’excellente librairie golang.org/x/net/webdav, maintenue par l’équipe Go. Cette librairie gère toute la complexité du protocole WebDAV : les verbes HTTP spécifiques (PROPFIND, PROPPATCH, MKCOL…), le parsing XML, la gestion des locks.
Mon travail consiste principalement à :
- Implémenter différents backends de stockage compatibles avec l’interface
webdav.FileSystem - Fournir une configuration simple et des outils pour déployer facilement un serveur
- Ajouter des fonctionnalités complémentaires (gestion des dead properties, système de locks persistants, règles d’autorisation avancées)
C’est ça aussi, le logiciel libre : ne pas repartir de zéro à chaque fois, mais construire par dessus ce qui existe déjà.
Une architecture modulaire
Le code que j’ouvre aujourd’hui est conçu dès le départ pour être modulaire. L’idée n’est pas seulement de résoudre mon problème immédiat, mais de poser les bases d’évolutions futures intéressantes.
Les backends actuels
Pour le moment, go-webdav supporte trois types de backend :
- Local : un simple système de fichiers local
- S3 : n’importe quel stockage compatible S3 (AWS S3, MinIO, Backblaze B2, Scaleway…)
- SQLite : une base de données SQLite embarquée
Le choix de SQLite peut sembler surprenant pour du stockage de fichiers, mais il ouvre des possibilités intéressantes pour des cas d’usage spécifiques (comme l’embarqué ou les tests).
Ce qui vient ensuite
La conception modulaire me permet d’imaginer des évolutions qui m’enthousiasment :
-
La réplication automatique. Un backend qui écrirait simultanément sur deux backends différents. Mes photos seraient automatiquement sauvegardées sur mon NAS et dans le cloud S3, sans intervention de ma part.
-
Un système de fichiers virtuel. Avec des “points de montage” permettant d’assembler différents backends. Je pourrais par exemple avoir
/photospointant vers S3,/documentsvers mon NAS local, et/archivevers un répertoire local de mon serveur, le tout présenté comme une arborescence cohérente. -
La gestion dynamique des droits. Via un moteur de règles flexible (j’expérimente avec Expr), je pourrais définir finement qui a accès à quoi, avec des règles qui évoluent selon le contexte.
-
Les dead properties pour la synchronisation. WebDAV supporte les “dead properties”, des métadonnées arbitraires attachées aux fichiers. Je pourrais les utiliser pour implémenter un système de synchronisation type Dropbox, avec détection des conflits et historique de versions.
Des tests pour garantir la conformité
Un serveur WebDAV qui ne respecte pas le protocole, c’est inutile. J’ai donc mis en place dès le départ deux niveaux de tests :
Une suite de tests d’intégration réutilisable
Le package filesystem/testsuite contient une batterie de tests d’intégration que chaque backend doit passer. Ces tests vérifient les opérations de base : création de fichiers et de répertoires, lecture, écriture, renommage, suppression, gestion des métadonnées.
L’avantage de cette approche : quand j’implémente un nouveau backend, je peux immédiatement vérifier qu’il se comporte correctement. Pas de surprise en production.
La suite Litmus pour la conformité E2E
Pour aller plus loin, j’ai intégré Litmus, la suite de tests de conformité WebDAV de référence. Litmus teste exhaustivement le protocole : les verbes HTTP, les headers, les codes de retour, les edge cases.
Le projet passe aujourd’hui quasiment 100% des tests Litmus. Les quelques pour-cents manquants sont liés à des limitations de base de la librairie golang.org/x/net/webdav elle-même, pas à mon implémentation.
La combinaison de ces deux suites de tests me rassure : je sais que mon serveur se comporte comme un vrai serveur WebDAV, compatible avec n’importe quel client standard.
Comment l’utiliser
Le plus simple pour tester go-webdav est d’utiliser l'image Docker publiée sur GitHub Container Registry.
Créez d’abord un fichier de configuration, par exemple config-s3.json :
{
"filesystem": {
"type": "s3",
"options": {
"endpoint": "s3.fr-par.scw.cloud",
"secure": true,
"region": "fr-par",
"bucket": "<nom_bucket>",
"bucketLookup": "dns",
"user": "<id_client>",
"secret": "<secret>",
"trace": false
}
},
"auth": {
"enabled": true,
"users": {
"alice": "password123"
}
}
}
Puis lancez le conteneur :
docker run --rm -it -p 3000:3000 \
-v "${PWD}/config-s3.json:/etc/go-webdav/config.json" \
ghcr.io/bornholm/gowebdav-server:latest
Votre serveur WebDAV est maintenant accessible sur http://localhost:3000. Vous pouvez vous y connecter avec n’importe quel client WebDAV en utilisant les identifiants alice / password123.
Pour un backend local, la configuration est encore plus simple :
{
"filesystem": {
"type": "local",
"options": {
"dir": "/data"
}
},
"auth": {
"enabled": true,
"users": {
"bob": "secretpassword"
}
}
}
Il suffit alors de monter un volume pour le stockage :
docker run --rm -it -p 3000:3000 \
-v "${PWD}/config-local.json:/etc/go-webdav/config.json" \
-v "${PWD}/data:/data" \
ghcr.io/bornholm/gowebdav-server:latest
Un projet encore jeune
Le code est ouvert, mais le projet reste jeune. L’API n’est pas stable, certaines fonctionnalités avancées sont encore en développement. C’est un chantier en cours.
Mais c’est aussi ce qui rend le projet intéressant : il y a de la place pour expérimenter, pour explorer des idées, pour construire quelque chose d’utile sans être contraint par une base de code vieillissante.
Le code est sur GitHub
Le projet est disponible sur GitHub sous licence AGPL v3: github.com/bornholm/go-webdav
Si le projet vous intéresse, n’hésitez pas à jeter un œil au code, ouvrir des issues, proposer des pull requests. C’est un projet personnel, mais c’est aussi une invitation à construire ensemble quelque chose d’utile.