Démarrage passerelle OpenClaw via launchd sur Mac mini : chemin absolu node, ProcessType et correctif code 78 (2026-05-21)
Après un redémarrage, votre LaunchAgent passerelle OpenClaw sur une Mac mini M4 louée à Hong Kong, au Japon, en Corée, à Singapour ou aux États-Unis peut ne jamais lier son port d’administration, se terminer avec le code 78 dans launchctl list, ou mettre environ trois minutes avant que les clients WebSocket ne cessent de voir des fermetures anormales 1006. Ce runbook du 21 mai 2026 cible les erreurs de plist launchd — un node nu dans ProgramArguments et l’absence de ProcessType à Interactive — et non les arbres orphelins MCP. Il complète la récupération après redémarrage de la passerelle, la checklist premier démarrage SSH sans écran et l’alignement runtime Node / nvm.
Code 78, écoute lente et WebSocket 1006 au démarrage à froid
Les retours terrain sur hôtes Apple Silicon décrivent deux formes distinctes d’échec launchd. Le code de sortie 78 immédiat signifie que launchd n’a jamais exécuté correctement le binaire de votre passerelle — souvent parce que ProgramArguments commence par la chaîne node alors que l’environnement launchd a un PATH vide ou minimal. La lenteur de mise en service affiche le job « en cours » dans launchctl list mais lsof ne trouve aucun processus à l’écoute pendant des minutes ; les tableaux de bord enregistrent alors le code de fermeture WebSocket 1006 jusqu’à ce que le processus soit enfin planifié. Les deux cas diffèrent des boucles de crash ThrottleInterval, qui martèlent la CPU avec des relances rapides.
- Statut de sortie 78 juste après
launchctl bootstrapou la connexion — vérifiez~/Library/LaunchAgents/*.plistpour unnodenu. - 180+ secondes entre le boot et la première sonde de santé réussie sur une mini autrement inactive.
- 1006 sur le WebSocket de contrôle alors que SSH fonctionne et que le disque est sain — socket pas encore en écoute, pas une mauvaise config TLS.
node gateway.jsmanuel en SSH fonctionne mais le chemin LaunchAgent échoue — classique écart PATH vs binaire absolu.
node -v diffère entre le shell de connexion et le plist, lisez d’abord l’article décalage runtime. Le code 78 signifie « binaire introuvable » ; le décalage signifie « trouvé mais mauvais ABI ».
Pourquoi launchd ignore votre PATH shell et rétrograde les agents en arrière-plan
Les LaunchAgents héritent d’un environnement réduit par rapport aux sessions Terminal.app interactives. La documentation et les fils terrain insistent : EnvironmentVariables dans le plist n’aide pas à résoudre le nom de l’interpréteur dans ProgramArguments — launchd résout l’exécutable avant d’appliquer ces clés. C’est pourquoi copier un plist portable avec node en argv[0] échoue sur les mini ProxyMac sans écran même si vous exportez PATH dans le même XML.
Par ailleurs, quand ProcessType est omis, macOS peut traiter la passerelle comme charge de fond soumise aux heuristiques d’alimentation et de planification après redémarrage. Les opérateurs rapportent un délai d’écoute au démarrage à froid passant de l’ordre de trois minutes à quelques secondes après ajout de <key>ProcessType</key><string>Interactive</string> à côté de Label. Traitez cela comme une hygiène de planification, pas une licence pour des sessions GUI sans surveillance — associez le travail Trousseau ponctuel à la VNC selon la checklist premier démarrage, puis restez en SSH.
Matrice opérateur (signal → premier correctif)
| Signal principal | Première réponse (l’ordre compte) | Preuves à capturer | Retour arrière si erreur | Responsable |
|---|---|---|---|---|
| Dernier code de sortie 78 sur le label OpenClaw | Remplacer argv[0] par le chemin absolu $(command -v node) ; bootout → bootstrap | launchctl print gui/$UID/<label> + XML du plist | Restaurer l’ancien plist depuis git | SRE plateforme |
| Job actif, pas d’écoute >60 s après redémarrage | Ajouter ProcessType Interactive ; confirmer un seul label plist | lsof -nP -iTCP:<port> -sTCP:LISTEN horodaté | Retirer ProcessType si la politique de session bureau l’interdit | Responsable automatisation |
| Sockets en écoute dupliqués sur le port admin | Suivre la récupération avec un seul processus à l’écoute | Deux PID dans la sortie lsof | bootout du label dupliqué | Astreinte |
| Boucle de crash <30 s, CPU élevée | Ajuster ThrottleInterval / KeepAlive — pas cet article | log show --predicate 'process == "launchd"' --last 5m | Revenir aux clés throttle | SRE |
Correctif plist en neuf étapes (SSH sur mini ProxyMac)
- Identifier le label :
launchctl list | grep -i openclawet noter le nom reverse-DNS complet. - Afficher l’état live :
launchctl print gui/$(id -u)/<label>et capturer le dernier code de sortie. - Résoudre Node : dans le même contexte utilisateur, exécuter
command -v node(ouwhich node) et noter le chemin absolu — typiquement sous/opt/homebrewou~/.nvm. - Éditer le plist : définir argv[0] de
ProgramArgumentssur ce chemin ; garder aussi le chemin absolu du script passerelle. - Ajouter ProcessType : insérer Interactive sous le dict racine si le délai au démarrage à froid correspond aux retours terrain.
- Valider le XML :
plutil -lint ~/Library/LaunchAgents/<file>.plistavant rechargement. - Recycler :
launchctl bootout gui/$(id -u) <label>puisbootstrapdu même chemin (ou kickstart fournisseur). - Délai d’écoute : boucler
lsoftoutes les 5 secondes pendant 120 secondes ; viser <15 s sur M4. - Documenter : committer le plist dans votre dépôt infra ; lier cet article dans le runbook pour le prochain arrivant.
/opt/homebrew/bin/node + chemin absolu vers le script d’entrée openclaw-gateway + --config + JSON de config absolu — ne jamais compter sur cd dans un wrapper sauf si WorkingDirectory est défini.
Vérifier l’écoute, le point de santé et la stabilité WebSocket
Après bootstrap, confirmez qu’un seul PID écoute sur votre port admin configuré (souvent cité autour de 18999 dans la doc opérateur — alignez sur votre config.json). Testez la route HTTP de santé si activée ; puis attachez votre client bureau et assurez-vous qu’il n’y a pas de 1006 dans les 30 premières secondes après redémarrage. Si la santé passe mais que les outils MCP échouent, basculez vers l’hygiène orphelins MCP plutôt que de rééditer le plist passerelle.
Test de redémarrage une fois par trimestre sur les hôtes d’automatisation : les régressions launchd n’apparaissent souvent qu’après les mises à jour de sécurité macOS, pas lors des modifications SSH le jour même. Journalisez uname -r à côté du délai d’écoute dans votre système de tickets.
Prévention : plists infra-as-code et labels de staging
- Stocker les plists dans git avec le chemin Node absolu templaté depuis votre image (préfixe Homebrew ou défaut nvm).
- Séparer les labels LaunchAgent dev/staging/prod sur la même mini — voir le guide récupération redémarrage pour les collisions de ports.
- Test fumée CI : après déploiement, vérifier l’écoute en <20 s via script SSH avant de marquer l’hôte sain.
- Mini labo jetable à HK/JP/KR/SG/US pour les expériences plist — moins cher que déboguer sur l’orchestrateur de production.
FAQ
Pourquoi mon LaunchAgent OpenClaw se termine immédiatement avec le code 78 ? launchd résout ProgramArguments avant d’appliquer EnvironmentVariables. Une chaîne node nue échoue quand PATH est vide sous launchd. Remplacez-la par le chemin absolu de command -v node, puis bootout et bootstrap à nouveau le plist.
Pourquoi la passerelle met-elle plusieurs minutes à écouter après un redémarrage ? Les plist LaunchAgent par défaut omettent souvent ProcessType Interactive, ce qui laisse macOS rétrograder le démarrage en arrière-plan pendant des minutes. Ajouter ProcessType Interactive sous le dict principal réduit souvent le délai d’écoute d’environ trois minutes à quelques secondes sur les mini Apple Silicon.
En quoi est-ce différent des boucles de crash ThrottleInterval ? Les problèmes ThrottleInterval se manifestent par des tempêtes de relance rapides et une CPU élevée. Le code 78 est un échec de configuration unique avant l’exécution de la passerelle. Une écoute lente sans boucle de crash pointe vers ProcessType ou la planification des ressources — pas KeepAlive qui combat un binaire incorrect.
Pourquoi une Mac mini louée est le bon endroit pour durcir OpenClaw launchd
Les plists passerelle sont de l’infrastructure : ils doivent survivre au redémarrage, aux mises à jour OS et aux ingénieurs qui ne connaissent que les chemins Homebrew du portable. Les mini Apple Silicon M4 offrent un timing de démarrage à froid prévisible, macOS launchd correspond au flux LaunchAgent documenté d’OpenClaw, et le placement HK / JP / KR / SG / US garde la latence du plan de contrôle près des API que vous automatisez. ProxyMac vous permet de cloner un plist validé sur une mini de staging, prouver une écoute sous la minute en SSH, puis promouvoir le même XML en production — voir les tarifs pour le choix de région et le centre d’aide pour les modes d’accès.
Valider les plists launchd sur du métal de staging
Louer une Mac mini HK / JP / KR / SG / US pour durcir la passerelle OpenClaw