Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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.service est 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.

#GesteCe qu’on vérifie avant de continuer
1Empaqueter et installer le bundlele manifeste scellé porte l’empreinte du binaire livré
2Émettre l’octroiil est signé par la clé de la machine, et tient sous le plafond de service
3Installer air-launchd.service, démon sur 2223l’unité démarre, le lanceur ne refuse pas le bundle
4Ouvrir une session sur 2223de bout en bout : poignée de main, authentification, shell
5systemctl disable --now air-sshd.servicel’ancienne unité est partie
6Repasser le lanceur sur 2222, redémarrer
7Ouvrir une session sur 2222le 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ômeCause probable
le processus sort avec 125la 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 SIGSYSun appel système hors de la cage seccomp — famille d’octroi manquante
« octroi refusé » au journall’octroi excède le manifeste, ou le manifeste excède le plafond de service
connexion refusée, service actifle 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.