Rien ne fige un déploiement OpenClaw aussi vite que Error: listen EADDRINUSE: address already in use. En 2026, les équipes confondent encore « port occupé » et « API modèle en panne », tournent les clés API des heures et oublient qu’un node zombie du smoke test d’hier tient encore TCP 8787. macOS complique : launchd relance un job avant que l’ancien socket soit totalement libéré, plusieurs profils partagent un Mac mini loué, et les sondes synthétiques curlent souvent 127.0.0.1 alors que la passerelle écoute sur une IP LAN. Ce guide propose une triage reproductible—lsof d’abord, parité plist ensuite, alignement des sondes enfin—reliée à doctor et diagnostic passerelle, premier lancement LaunchAgent et surveillance de santé pour arrêter les suppositions.
Traitez les collisions de ports comme des incidents de capacité : notez interface, PID et label LaunchAgent pour des post-mortems courts.
Sans plage de ports documentée, le blue/green du week-end se termine souvent par deux instances sur le même numéro—anticipez avec un tableau partagé.
Symptômes ressemblant à des pannes amont
Les clients voient refus de connexion, curl vide ou tableaux « passerelle hors ligne » avec CPU au repos. Avant d’accuser les fournisseurs de modèles, vérifiez si le serveur HTTP a atteint LISTEN. Si le processus meurt au boot, les journaux peuvent s’arrêter avant la bannière—seul errno reste. Collectez stderr via StandardErrorPath et corrélez avec launchctl print.
Sur Mac mini partagés, les sessions npm run dev oubliées sont le coupable habituel ; elles n’apparaissent pas dans Grafana car jamais instrumentées.
Les erreurs DNS ou TLS produisent des nuages de symptômes similaires : vérifiez d’abord la socket, puis TLS, puis l’amont.
Recettes lsof en une minute
lsof -nP -iTCP:8787 -sTCP:LISTEN
-n évite les résolutions DNS lentes ; -P affiche les ports numériques. Pour un PID node inconnu, capturez ps -p PID -o args= avant kill. Si rien n’écoute mais les clients échouent, vérifiez HTTPS client contre HTTP passerelle.
Pour IPv6 uniquement, ajoutez lsof -nP -i6TCP:8787 ; certaines piles Node dupliquent l’écoute dual-stack.
ProgramArguments LaunchAgent et drapeaux de port
Les plists passent souvent --port deux fois : wrapper et modèle copié. Le dernier argument gagne silencieusement. Une seule source de vérité : variables d’environnement ou arguments explicites. Après édition, launchctl bootout puis bootstrap pour fermer l’ancien socket.
Validez WorkingDirectory vers le checkout contenant la package.json attendue ; cwd erroné + npx peut recréer un écouteur par défaut.
127.0.0.1 versus 0.0.0.0 versus IP LAN
La loopback limite le scan LAN mais casse les sondes depuis d’autres hôtes. 0.0.0.0 exige discipline pare-feu. Une IP bureau fixe casse au renouvellement DHCP. Documentez le contrat dans le runbook et reflétez-le dans les attentes openclaw doctor.
Sondes de santé trompeuses
Des moniteurs qui curl http://127.0.0.1:8787/readyz restent verts quand les utilisateurs distants échouent sur 10.0.40.12:8787 à cause de VPN split ou routage. Alignez l’IP source des sondes sur le chemin réel ou tunnelisez via le même bastion. Exportez gateway_bind_interface au démarrage pour Grafana.
Un health L4 peut rester vert alors que l’auth L7 échoue : combinez socket + petit appel HTTP authentifié.
Matrice de décision
| Scénario | Bind préféré | Point de vigilance |
|---|---|---|
| Lab portable solo | 127.0.0.1 | Bascule avant démos distantes |
| Mac mini partagé derrière pare-feu | IP LAN + liste blanche | Réservations DHCP |
| Bord public avec reverse proxy | loopback + nginx frontal | Éviter d’exposer la passerelle sur l’interface publique |
TIME_WAIT et redémarrages rapides
Les scripts de déploiage qui redémarrent toutes les 30 secondes laissent l’ancien PID en TIME_WAIT jusqu’à ~60 secondes ou épuisent les ports éphémères. Insérez ~5 secondes entre bootout et bootstrap, ou incrémentez temporairement le port admin.
Pièges du pare-feu applicatif
macOS demande l’autorisation entrante pour chaque nouveau chemin binaire Node. Refus local = bind OK mais SYN distants en timeout, comme un conflit de port. Standardisez chemins ou signatures pour éviter les dialogues en cascade lors des upgrades.
Plusieurs passerelles sur un Mac
Le blue/green exige des ports distincts (8787/8788) et des labels uniques. Réservez des plages : 8700–8799 OpenClaw, 8800–8899 mocks—sans feuille partagée, les prestataires choisissent au hasard.
Staging + production sur un hôte : séparez utilisateurs ou journaux pour garder lsof lisible.
launchctl kickstart et écouteurs résiduels
Après libération, préférez launchctl kickstart -k gui/$UID/com.example.openclaw pour que launchd envoie SIGKILL aux enfants récalcitrants. Sans -k, un thread middleware peut garder le FD malgré « shutdown complete ». Archivez un extrait de launchctl print avant/après pour prouver running → not running.
Ports clients éphémères et tempêtes sortantes
Le fan-out d’outils ouvre des milliers de connexions sortantes ; macOS peut épuiser les plages éphémères alors que LISTEN semble sain. Ne confondez pas EADDRINUSE côté client avec un conflit d’écouteur. Surveillez sysctl net.inet.ip.portrange.hifirst pour les runners CI colocalisés.
Logs structurés sur échec de bind
Émettez du JSON avec event="bind_failed", errno, hôte, port, hash d’argv. Les post-mortems ne doivent pas redécouvrir par SSH. Associez errno 48 (EADDRINUSE) à la commande lsof sur la même ligne de log.
Pourquoi la CI Linux rate les courses macOS
Les conteneurs redémarrent vite ; les namespaces réseau diffèrent des sessions GUI macOS. Traitez Linux comme contrôle de compilation ; gardez un smoke bind sur matériel Apple avant de fusionner des plists. Une location Mac mini d’une journée coûte environ une heure-ingénieur et boucle la preuve.
FAQ
macOS réutilise-t-il un port instantanément ?
Non ; attendez après des redémarrages à haut churn ou changez de port admin.
Pourquoi la santé est verte et les utilisateurs échouent ?
Les interfaces des sondes et des clients divergent.
0.0.0.0 est-il plus sûr que la loopback ?
Non—surface plus large ; ajoutez des règles pare-feu.
Quand louer un Mac mini ?
Quand il faut reproduire la sémantique des sockets macOS hors portable.
Les guerres de ports sont ennuyeuses mais coûteuses. Un Mac mini Apple Silicon loué chez MacHTML—environ 16,9 USD par jour—offre le même cycle launchd, les mêmes défauts de socket et les mêmes invites pare-feu que la production, sans expédier du matériel. Montez-le pour une semaine de release, collectez des preuves lsof, puis arrêtez la location.
Le silence thermique aide lors de longues sessions SSH de tests de bind répétés.
Reproduire les problèmes de bind OpenClaw sur macOS réel
Louez un Mac mini cloud pour valider ports, plists LaunchAgent et sondes avec un comportement de sockets fidèle à macOS.