Langues : Français · English
Comment fonctionne gitfed
Ce document explique le mécanisme central de gitfed : comment deux instances
qui ne se connaissent pas peuvent laisser leurs utilisateurs collaborer sans
qu'aucun compte ne soit jamais partagé entre elles. Pour le contexte plus
large (fichiers, code, déploiement), voir le README ; pour
le détail de chaque paquet Go, voir ARCHITECTURE.md ;
pour le mode d'emploi pratique (mettre en place une vraie collaboration
fédérée étape par étape), voir ../FEDERATION.md.
1. Le problème que ça résout
Sur GitHub ou GitLab, collaborer avec quelqu'un suppose soit que vous ayez tous les deux un compte sur la même plateforme, soit que l'un des deux migre. gitfed part d'un principe différent, plus proche du mail ou d'ActivityPub : chaque personne a un compte sur une seule instance — la sienne — et cette instance peut prouver son identité auprès de n'importe quelle autre instance qui accepte de lui faire confiance.
Concrètement : alice a un compte sur chez-moi.fr. Bob a un compte sur
ailleurs.net. Bob peut pousser du code sur un dépôt d'alice sans jamais
créer de compte chez elle — à condition que l'instance d'alice ait choisi de
faire confiance à l'instance de Bob.
2. L'identité : un certificat plutôt qu'un mot de passe partagé
Chaque instance gitfed génère, à sa création, sa propre autorité de certification (une paire de clés ed25519, stockée sur le volume de données). C'est le socle de tout le modèle :
- Un utilisateur local enregistre une clé SSH publique auprès de son
instance (via
gitfed-tuipour le tout premier compte, ou en autonomie ensuite dansParamètres → Clés SSH). - Quand il en a besoin, il demande à son instance un certificat
(
ssh git@instance gitfed-cert, ou via l'outilgitfed-renew-certen tâche planifiée). L'instance vérifie que la clé lui appartient bien, puis signe un certificat SSH au format OpenSSH. - Ce certificat embarque un principal —
bob@ailleurs.net, jamais un simple nom d'utilisateur seul — et une durée de validité courte, 24 heures par défaut. - Quand Bob se connecte à l'instance d'alice, il présente ce certificat au lieu de sa clé nue. L'instance d'alice vérifie deux choses : que la signature du certificat correspond bien à une autorité en laquelle elle a confiance, et que ce certificat n'a pas été révoqué (§6).
Aucune de ces deux instances n'a besoin de contacter l'autre en direct pour cette vérification — la signature suffit, un peu comme un passeport n'a pas besoin d'un appel téléphonique au pays émetteur pour être vérifié à la frontière, tant qu'on connaît la clé publique de l'autorité qui l'a délivré.
3. La confiance entre instances : le magasin de confiance
Faire confiance à une autorité, ça se construit. La première fois que
l'instance d'alice croise le domaine ailleurs.net (typiquement parce
qu'alice a accordé un accès à bob@ailleurs.net sur un de ses dépôts), elle
déclenche une découverte fédérée :
- Elle récupère
https://ailleurs.net/.well-known/gitfed.json, un document public qui contient la clé publique de l'autorité de certification de cette instance. - Elle vérifie que ce document est cohérent (le domaine déclaré correspond
bien, une clé est présente) et que la requête ne pointe pas vers une
adresse interne ou privée (protection anti-SSRF : IP littérales,
127.0.0.0/8,10.0.0.0/8,169.254.0.0/16/métadonnées cloud, etc. sont toutes refusées, y compris après résolution DNS). - Selon la politique configurée sur l'instance d'alice :
- liste blanche (par défaut) — le domaine est enregistré comme en
attente ; un administrateur doit l'approuver explicitement dans
Administration → Confiance fédéréeavant que le moindre accès ne soit accordé. - auto-confiance (TOFU — "trust on first use") — le domaine est approuvé immédiatement à la première découverte, à activer uniquement si on accepte ce niveau de risque.
- liste blanche (par défaut) — le domaine est enregistré comme en
attente ; un administrateur doit l'approuver explicitement dans
- La découverte est limitée à 10 nouveaux domaines par minute pour toute l'instance, pour empêcher qu'un compte compromis ne s'en serve comme sonde réseau à grande échelle.
Une fois un domaine approuvé, la vérification d'un certificat qui en
provient est entièrement locale : aucune requête réseau n'est refaite à
chaque git push.
4. L'autorisation : qui peut faire quoi sur quel dépôt
L'identité fédérée dit qui on est ; elle ne dit rien de ce qu'on a le droit de faire. Ça, c'est le rôle du modèle d'ACL, entièrement local à chaque dépôt :
- Chaque dépôt a un propriétaire (toujours admin) et, optionnellement, des collaborateurs, chacun avec un rôle explicite : lecture, écriture, ou admin.
- Un dépôt est en plus public ou privé. Un dépôt public accorde la lecture à n'importe quel principal authentifié, de n'importe quelle instance de confiance, sans qu'il soit besoin de l'ajouter comme collaborateur. L'écriture n'est en revanche jamais implicite — même sur un dépôt public, il faut un rôle explicite pour pousser du code.
- Octroyer un accès à un principal sur un domaine encore inconnu de l'instance est justement ce qui déclenche la découverte fédérée décrite au §3.
5. Le cycle complet, étape par étape
Reprenons l'exemple : alice veut donner à Bob un accès en écriture sur
alice/mon-projet.
- Sur l'instance d'alice — alice va dans les paramètres du dépôt et
accorde le rôle écriture à
bob@ailleurs.net. - Si
ailleurs.netest un domaine encore inconnu, l'instance d'alice déclenche la découverte (§3) et le domaine reste en attente tant qu'un admin ne l'a pas approuvé. - Sur l'instance de Bob — Bob demande un certificat à sa propre
instance (
gitfed-certou renouvellement automatique). Son instance signe un certificat portant le principalbob@ailleurs.net. - Bob exécute
git push ssh://git@chez-moi.fr:2222/alice/mon-projet.git, en s'authentifiant avec son certificat. - L'instance d'alice vérifie la signature du certificat contre la clé
d'autorité qu'elle a approuvée pour
ailleurs.net, vérifie qu'il n'est pas révoqué, puis vérifie dans son ACL locale quebob@ailleurs.neta bien le rôle écriture suralice/mon-projet. - Si tout est en ordre,
git-receive-packs'exécute normalement, exactement comme pour un utilisateur local.
À aucun moment Bob n'a eu besoin d'un compte, d'un mot de passe ou d'une clé enregistrée chez alice.
6. Expiration et révocation
Un certificat de 24 h qui traîne après la suppression d'un compte reste, en théorie, un accès résiduel. gitfed traite ça de deux façons complémentaires :
- Le TTL est court (24 h par défaut, configurable) — la fenêtre d'exposition d'une clé compromise est bornée même sans action de l'administrateur.
- La révocation est immédiate. Supprimer un utilisateur ou retirer une de ses clés SSH enregistre la révocation correspondante (par principal et/ou par empreinte de clé) ; chaque authentification SSH consulte cette liste avant d'accepter un certificat, même s'il est encore cryptographiquement valide.
7. Ce qui n'est pas fédéré
Pour être clair sur les limites du modèle : un dépôt vit sur une seule instance. Il n'y a ni réplication, ni miroir automatique entre instances. La fédération ne concerne que l'identité — qui a le droit de pousser ou de lire — jamais les données elles-mêmes. Si l'instance d'alice tombe, son dépôt n'est disponible nulle part ailleurs tant qu'il n'a pas été cloné en dehors.
8. Cas particulier : cloner un dépôt public sans compte
Tout ce qui précède décrit l'accès authentifié — nécessaire pour tout dépôt privé, et pour toute écriture, même sur un dépôt public. Mais un dépôt public peut aussi être cloné en HTTPS, sans certificat, sans clé SSH, sans compte du tout :
git clone https://chez-moi.fr/alice/mon-projet.git
C'est strictement un raccourci de lecture, pas une deuxième voie
d'authentification : aucune écriture n'est possible par ce chemin (il n'y
a pas de route git-receive-pack en HTTP, littéralement aucune), et un
dépôt qui redevient privé cesse instantanément d'être accessible ainsi.
Voir ARCHITECTURE.md §7 pour le détail
d'implémentation.
9. Cas particulier : fusionner une branche depuis le web
Les merge requests permettent à un collaborateur en écriture de fusionner
une branche dans une autre depuis l'interface web — une « écriture » qui
ne passe pas par SSH, ce qui ressemble à une deuxième exception au modèle
d'identité du §2. Ça n'en est pas une : le navigateur n'envoie jamais de
donnée git, il dit seulement au serveur de combiner deux branches qu'il a
déjà, et chaque commit que l'une ou l'autre pointe n'est arrivé dans le
dépôt que via un vrai push authentifié par SSH au départ. L'accès passe
par exactement le même contrôle de rôle en écriture qu'un git push
traverse déjà — le bouton web n'ouvre aucune capacité qu'un collaborateur
en écriture n'aurait pas déjà en clonant, fusionnant en local, puis en
repoussant. Voir ARCHITECTURE.md §8 pour comment la
fusion elle-même est isolée de l'état réel d'une branche (worktree
jetable, détection de conflit avant toute écriture, mise à jour de ref en
compare-and-swap).