Bascule du jalon B — air-sshd sous air-launchd
Ce guide décrit un geste d’administration, pas une procédure automatisée. Il n’existe aucun script qui l’exécute, et c’est délibéré (ADR-121) : un système qui installe seul son propre superviseur est un système dont personne ne relit l’installation.
Ce que le jalon exige, exactement
ADR-168 D2 :
une machine où l’unité
air-sshd.serviceest retirée, le service tournant sous le lanceur
C’est un état de machine. La preuve en test — le harnais sous_air_launchd — est
nécessaire et ne suffit pas.
Le chemin : cohabitation d’abord (ADR-168 D2.2)
Le critère décrit l’état final, pas le chemin. Retirer l’unité avant d’avoir vérifié laisserait la machine sans démon SSH Air pendant qu’on diagnostique.
| # | Geste | Ce qu’on vérifie avant de continuer |
|---|---|---|
| 1 | Empaqueter et installer le bundle | le manifeste scellé porte l’empreinte du binaire livré |
| 2 | Émettre l’octroi | il est signé par la clé de la machine, et tient sous le plafond de service |
| 3 | Installer air-launchd.service, démon sur 2223 | l’unité démarre, le lanceur ne refuse pas le bundle |
| 4 | Ouvrir une session sur 2223 | de bout en bout : poignée de main, authentification, shell |
| 5 | systemctl disable --now air-sshd.service | l’ancienne unité est partie |
| 6 | Repasser le lanceur sur 2222, redémarrer | |
| 7 | Ouvrir une session sur 2222 | le jalon est franchi |
Le retour en arrière est possible à chaque étape : tant que l’étape 5 n’est pas faite,
systemctl stop air-launchd rend la machine à son état d’avant.
⚠️ L’accès d’administration ne doit dépendre d’aucun des deux. Sur carbon, il passe par
OpenSSH sur le port 52222 — un troisième port, servi par un troisième démon. Cela borne le
risque ; cela ne dispense pas de la cohabitation, parce qu’un jalon franchi en laissant un
service cassé n’est pas un jalon franchi.
Étape 1 — empaqueter et installer
Le manifeste versionné (crates/air-sshd/bundle/manifest.toml) est un gabarit : son
empreinte vaut soixante-quatre zéros. C’est air-bundle install --seal-binary qui la pose,
sur le binaire réellement construit.
cargo xtask package --package air-sshd # produit le bundle scellé
Le bundle est déposé sous /var/lib/air/services/org.air-desktop.sshd/ : l’exécutable, son
manifest.aircfg et sa manifest.signature.aircfg.
Vérifier avant de poursuivre — un manifeste qui ne demande pas ce dont le démon a besoin produit un service qui ne peut jamais démarrer, l’octroi ne pouvant excéder la demande :
air-bundle show --bundle org.air-desktop.sshd
La sortie doit porter ioUring, le port en écoute, et les trois chemins de lecture
(/etc/air/sshd.aircfg, /etc/air/sshd, /etc/air/keystore).
Étape 2 — émettre l’octroi
L’octroi est signé par la clé de la machine, qui vit dans son keystore et ne le quitte pas (ADR-150 D16). Il n’accorde que ce qui est nommé :
air-bundle grant --bundle org.air-desktop.sshd \
--io-uring \
--bind-port 2223 \
--read-path /etc/air/sshd.aircfg \
--read-path /etc/air/sshd \
--read-path /etc/air/keystore \
--aircom-publish org.air-desktop.sshd \
--session-program /bin/bash \
--session-program /usr/sbin/nologin
Les noms d’options sont relevés dans crates/air-bundle-cli/src/lib.rs, pas reconstitués :
c’est --read-path et non --read, --session-program et non --session. Un guide dont on
copie les commandes doit porter celles qui existent.
Il est déposé sous /etc/air/grants/.
Étape 3 — installer l’unité du lanceur
Le fichier versionné est crates/air-launchd/units/air-launchd.service. Son en-tête explique
pourquoi Delegate=yes n’est pas décoratif : sans lui, le lanceur ne peut pas distribuer
pids/memory à ses services, et toutes ses bornes tombent en silence.
sudo cp crates/air-launchd/units/air-launchd.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now air-launchd.service
Ce qu’il faut lire ensuite, et ne pas survoler :
systemctl status air-launchd.service
journalctl -u air-launchd.service -n 50
Un bundle écarté est nommé sur la sortie d’erreur, avec son motif. Un lanceur qui démarre
sans rien superviser rend un succès — un système sans service installé n’est pas une
panne — donc active (running) ne prouve pas que le démon tourne. C’est le journal qui le
dit, pas le statut de l’unité.
Étape 4 — la vérification qui compte
ssh -p 2223 -o StrictHostKeyChecking=no <utilisateur>@<machine>
Une session ouverte prouve la chaîne entière : arbitrage, cage Landlock, seccomp avec la
famille io_uring, écoute liée, publication du nom au registre.
Si elle échoue, le diagnostic est dans cet ordre :
| Symptôme | Cause probable |
|---|---|
| le processus sort avec 125 | la cage n’a pas pu être posée ; l’étape fautive et l’errno sont sur sa sortie d’erreur (CHILD_CONFINE_FAILURE) |
| tué par SIGSYS | un appel système hors de la cage seccomp — famille d’octroi manquante |
| « octroi refusé » au journal | l’octroi excède le manifeste, ou le manifeste excède le plafond de service |
| connexion refusée, service actif | le port accordé n’est pas celui que la configuration sert |
Étapes 5 à 7 — le retrait, puis le retour sur 2222
sudo systemctl disable --now air-sshd.service
sudo rm /etc/systemd/system/air-sshd.service
sudo systemctl daemon-reload
Puis rééditer la configuration et l’octroi pour le port 2222, redémarrer le lanceur, et rouvrir une session — sur 2222 cette fois.
Après la bascule
- mettre
docs/etat-avancement.mdà jour : le jalon B n’est franchi qu’à l’étape 7 ; - journaliser la campagne dans
docs/JOURNAL.md; - ce qui reste ouvert pour le jalon C est dans ADR-168 D2.