01La boucle GitOps signée
Chaque changement de flotte est un commit Git. Le runner CI évalue le flake,
canonicalise fleet.resolved.json (JCS, RFC 8785), et le signe avec une
clé Ed25519 de release dédiée. La closure est poussée vers un cache binaire Nix. Le
control plane interroge la forge Git, vérifie la signature, et distribue les générations
par hôte via mTLS. Chaque agent vérifie la même signature indépendamment avant d'activer.
Dépôt de flotte (forge Git auto-hébergée)
│ git push
▼
Runner CI
• nix flake check
• nixfleet-release build + canonicalise (JCS)
• signe fleet.resolved.json (Ed25519, clé release CI)
• pousse les closures vers le cache binaire
│ artefact signé + cache amorcé
▼
Control Plane (Rust, Axum, SQLite, AGPL)
• vérifie la signature CI
• vérifie le sidecar de révocations
• gating /v1/* sur artifact_primed + revocations_primed
• réconciliateur (fonction pure) émet les transitions
• NE DÉTIENT AUCUNE CLÉ DE SIGNATURE
│ mTLS (cert client par hôte)
▼
Agent (Rust, MIT)
• vérifie la signature CI INDÉPENDAMMENT du CP
• fetch la closure depuis le cache binaire
• active via nixos-rebuild switch
• rollback magique sur silence de deadline
• quarantaine de closure 24h sur échec d'activation 02Le modèle de confiance - la propriété décisive
Aucun composant unique du chemin de confiance ne détient à la fois pouvoir de signature et autorité d'exécution.
- La clé release CI vit dans le runner CI (ou HSM en production). Elle signe sans déployer.
- Le control plane vérifie les signatures et ne détient aucune clé. Compromettre le CP donne à l'attaquant aucune autorité de déploiement - les agents refusent tout artefact non signé par la clé release autorisée.
- L'agent vérifie les signatures à nouveau, indépendamment du CP, avant d'activer une closure.
- La clé org-root vit sur le poste opérateur (ou HSM). Elle ne sert qu'à émettre les bootstrap tokens et faire tourner la clé release CI. Hors-ligne le reste du temps.
Une compromission du control plane est une panne, pas une fuite. Le CP peut être reconstruit depuis l'état vide à partir de l'historique Git et de la disponibilité de la forge Git + cache binaire.
03Rollback magique à deadline
Après activation, l'agent ouvre une fenêtre de confirmation. S'il ne poste pas un acquittement signé avant la deadline, la génération précédente est restaurée automatiquement. La propriété de sécurité des canaries devient une propriété de protocole, pas une fonctionnalité d'un outil de monitoring externe. La détection de switch-inhibitor diffère l'activation quand des changements dbus, systemd ou kernel sont en attente.
04Promotion par vagues gating canal
Les politiques de rollout décomposent la flotte en vagues (canary, staged, all-at-once)
avec des temps de soak configurables. Une vague ne progresse que si chaque sonde de
santé de la vague précédente passe. channelEdges ordonne les canaux entre
eux - edge doit converger avant que stable ne démarre,
garantissant un test pré-production réel. disruptionBudgets plafonne le
nombre d'hôtes en cours par sélecteur.
05Quarantaine de closure
Un échec d'activation place ce hash de closure sur une liste de refus de 24 heures, empêchant les boucles de redéploiement. L'hôte refuse de retenter l'activation de la même closure défaillante jusqu'à expiration de la quarantaine ou levée explicite par l'opérateur.
06Capacité actuelle
| Composant | Statut |
|---|---|
Framework Nix (mkHost, mkFleet, mkVmApps) | Fonctionnel, schéma typé, 7 fixtures golden + 9 négatives mkFleet |
| Control plane (Rust) | Axum, SQLite, gating freshness + révocations |
| Agent (Rust) | Polling + rollback magique à deadline |
| Réconciliateur (Rust) | Fonction pure, tests lifecycle parity + soak |
| CLI (Rust) | status / rollout trace / mint-token / mint-operator-cert |
| mTLS agent ↔ CP | Implémenté (rustls, certificats client, liste de révocation) |
| Chaîne d'artefacts signés (Ed25519) | Implémenté de bout en bout (CI signe → CP vérifie → agent vérifie) |
| Vagues gating canal | Implémenté (rolloutPolicies + channelEdges + disruptionBudgets) |
| Tests E2E | 15 scénarios fleet-harness (signed-roundtrip, auditor-chain, deadline-expiry, rollback-policy, …) |
| LOC actuel | Exécuter tools/loc.sh dans le repo nixfleet |
07Cadrage honnête - ce qui n'y est pas encore
- Plafond SQLite ~150 hôtes. Prévu : pool de connexions ou Postgres async.
- Agent Darwin fonctionnel. Les rollouts Darwin multi-hôtes ne sont pas encore exercés par fleet-harness.
- Pas de mode air-gap. Spécifié dans RFC-0012, fondations déjà livrées. Voir la trajectoire de confiance.
08Licence + dépôts
- arcanesys/nixfleet : framework + agent (MIT) + control plane (AGPL)
- arcanesys/nixfleet-compliance : 16 contrôles, 4 référentiels (MIT)
- arcanesys/nixfleet-demo : flotte de référence 4 VMs (MIT)
Empreinte de la clé de signature release : FB04 CB1F CDC9 C55D 05FE E045 0634 8958 A782 9C5F
(ed25519, ancrage matériel). Vérifier n'importe quel tag de release avec
git tag -v v0.2.0 après avoir récupéré la clé publique depuis le dépôt.
Voir tourner - 10 minutes en local → En savoir plus sur le pilote →