freedzhost.cloud

SSH pour un poste agentique : instantané, sûr, et quatre pièges

Niveau IntermédiaireTemps estimé 30 minÀ lire avant Un portable d'occasion devenu poste Linux confortable (Omarchy)Un mot inconnu ? Lexique

Depuis le portable, tout passe par SSH : vers le serveur, la machine de garde, les machines virtuelles. Vous tapez quelques commandes par heure ; un agent en envoie des centaines. À ce rythme, chaque poignée de main lente et chaque erreur de guillemets s'additionnent, et certaines erreurs exécutent du code que vous n'aviez jamais voulu lancer. Quatre réglages et règles, chacun payé une fois.

Ce que vous y gagnez. Des commandes vers vos machines qui répondent en 12 ms environ au lieu de 130 à 340, du texte qui ne peut jamais être exécuté par accident, des fenêtres ouvertes à distance qui n'emportent pas votre jeu en se fermant.

1. Partager une connexion par machine

# ~/.ssh/config
Host serveur
    HostName serveur.lan
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m

La première connexion ouvre un maître ; les suivantes passent par lui pendant dix minutes. Mesuré ici : premier appel de 130 à 340 ms, les suivants environ 12 ms.

Mettez-le sur vos alias seulement. Les tunnels de longue durée (autossh) doivent se connecter par adresse, pour ne jamais devenir le maître partagé dont tout le reste dépend.

2. Le texte libre voyage par l'entrée standard, jamais dans la ligne de commande

La commande passée à ssh est relue par le shell distant. Mettez-y le corps d'une demande de fusion ou la sortie d'un agent, et ses backticks et ses $( ) sont exécutés de l'autre côté. C'est arrivé chez nous : les backticks d'une description de PR ont été lancés comme des commandes. Elles n'existaient pas, par chance.

# non
ssh serveur "open-pr --body '$CORPS'"
# oui : le texte sur stdin, un script de l'autre côté construit lui-même les arguments
printf '%s' "$CORPS" | ssh serveur 'python3 ~/bin/open_pr_stdin.py'

3. Ouvrir une fenêtre sur une autre machine, proprement

Une appli graphique lancée par SSH a besoin de tout l'environnement de la session, relu sur un programme qui tourne déjà dans cette session :

tr '\0' '\n' < /proc/$(pgrep -u "$USER" -x steam | head -1)/environ \
  | grep -E '^(WAYLAND_DISPLAY|DISPLAY|XDG_RUNTIME_DIR|DBUS_SESSION_BUS_ADDRESS|XAUTHORITY)='

Puis lancez-la détachée, avec cet environnement :

setsid nohup env WAYLAND_DISPLAY=... DISPLAY=... XDG_RUNTIME_DIR=... \
  DBUS_SESSION_BUS_ADDRESS=... XAUTHORITY=... lutris >/tmp/lutris.log 2>&1 </dev/null & disown

XAUTHORITY n'est pas facultatif : sans lui, tout ce qui passe par XWayland (jeux Wine compris) plante au démarrage. Le nom de son fichier change à chaque session : relisez-le, ne le codez jamais en dur.

N'utilisez pas systemd-run --user --collect pour ça. À la fermeture de l'appli, systemd nettoie tout son groupe de processus : nous y avons perdu un lanceur de jeux, un jeu en cours et un téléchargement de 84 Go à mi-chemin.

4. Ne jamais tuer par motif de nom

pkill -f quelquechose attrape tout processus dont la ligne de commande contient « quelquechose ». Par SSH, cela inclut le shell distant qui lance votre commande, et le processus du serveur SSH qui la porte : votre session meurt en plein travail. C'est arrivé deux fois dans la même journée ici ; nous le bloquons désormais mécaniquement dans les crochets de l'agent.

pgrep -f "[m]on-serveur"      # les crochets : le motif ne correspond plus à sa propre ligne de commande
kill $(pgrep -f "[m]on-serveur")

Pièges

Un service utilisateur n'a pas ~/.local/bin dans son PATH. Donnez des chemins complets dans vos unités.

Une connexion partagée survit mal à un changement de réseau. Si les commandes se figent après un changement de Wi-Fi, fermez le maître : ssh -O exit serveur.

Utile ? Dites-nous ce qu'il faut mesurer ensuite.