ssh-config alias kai-server -> kai-server.local on home LAN (supersedes inert lan-hosts /etc/hosts pin, #266) #294

Open
opened 2026-06-12 06:33:56 +00:00 by coilysiren · 1 comment
Owner

Decision

Kai picked the ssh-config-alias variant for the same-LAN kai-server reachability workaround (#266, landed inert on PR #250), with one refinement over the original sketch: the alias target is kai-server.local (mDNS), not the pinned LAN IP.

Filed as an issue rather than landed directly because another agent is active in this repo right now. Whoever picks this up: coordinate via o2r channel HDBF if needed.

Why kai-server.local

  • avahi-daemon already runs on kai-server - it ships with ubuntu-desktop, marked auto-installed, present since the OS install (verified 2026-06-11 via dpkg/apt history on the box). Nothing to deploy on the server side.
  • macOS resolves .local natively via Bonjour, so the Mac side needs only the ssh-config block.
  • mDNS tracks DHCP - no stale-IP failure mode, unlike the /etc/hosts pin of 192.168.0.194.
  • Plain LAN traffic - bypasses the Archer A20 hairpin fault (#251) entirely.

Evidence base

Chronic same-LAN tailnet WireGuard data-path blackhole to kai-server, diagnosed 2026-06-07 in o2r channel HDBF (#251), recurred 2026-06-11 ~23:10 PT (HDBF event 213): disco ping DIRECT 4ms while ICMP/TSMP through the tunnel and TCP :22 over the tailnet name all time out, LAN path clean throughout.

Implementation notes

  • No ansible currently manages ~/.ssh/config - grep across infrastructure, agentic-os, and coilyco-bridge finds no role touching it. The block on kais-macbook-pro is hand-maintained. So this is a net-new role (or a new task in an existing client-side role), managing a marker-fenced block in ~/.ssh/config on Kai's client machines.

  • Suggested shape: a Match block ahead of the existing Host kai-server entry, e.g.

    Match host kai-server exec "ping -c1 -t1 kai-server.local >/dev/null 2>&1"
        HostName kai-server.local
    

    On the home LAN the mDNS probe succeeds and ssh uses the LAN path. Off-LAN the probe fails (~1s) and resolution falls through to the existing tailnet-FQDN HostName. Validate the probe choice on macOS (ping -t is the macOS timeout flag, Linux clients need -W).

  • Keep the tailnet FQDN out of tracked files - it stays SSM-resolved (/coilysiren/kai-server/tailnet-fqdn) per the opaque-ids rule. The .local name and the kai-server short name are meaningful names and hardcode fine.

  • Retire the inert lan-hosts /etc/hosts role (ansible/roles/lan-hosts/, lan_hosts_enabled: false) in the same change, or repurpose its home-LAN detection if useful. It should not land enabled alongside the ssh alias.

Refs

  • #251 - chronic SSH hangs/drops tracker (diagnosis)
  • #266 / PR #250 - inert lan-hosts role (superseded by this approach)
  • o2r channel HDBF - full diagnosis thread, recurrence event 213
## Decision Kai picked the **ssh-config-alias** variant for the same-LAN kai-server reachability workaround (#266, landed inert on PR #250), with one refinement over the original sketch: the alias target is **`kai-server.local`** (mDNS), not the pinned LAN IP. Filed as an issue rather than landed directly because another agent is active in this repo right now. Whoever picks this up: coordinate via o2r channel HDBF if needed. ## Why kai-server.local * avahi-daemon already runs on kai-server - it ships with `ubuntu-desktop`, marked auto-installed, present since the OS install (verified 2026-06-11 via dpkg/apt history on the box). Nothing to deploy on the server side. * macOS resolves `.local` natively via Bonjour, so the Mac side needs only the ssh-config block. * mDNS tracks DHCP - no stale-IP failure mode, unlike the `/etc/hosts` pin of `192.168.0.194`. * Plain LAN traffic - bypasses the Archer A20 hairpin fault (#251) entirely. ## Evidence base Chronic same-LAN tailnet WireGuard data-path blackhole to kai-server, diagnosed 2026-06-07 in o2r channel HDBF (#251), recurred 2026-06-11 ~23:10 PT (HDBF event 213): disco ping DIRECT 4ms while ICMP/TSMP through the tunnel and TCP :22 over the tailnet name all time out, LAN path clean throughout. ## Implementation notes * **No ansible currently manages `~/.ssh/config`** - grep across infrastructure, agentic-os, and coilyco-bridge finds no role touching it. The block on kais-macbook-pro is hand-maintained. So this is a net-new role (or a new task in an existing client-side role), managing a marker-fenced block in `~/.ssh/config` on Kai's client machines. * Suggested shape: a `Match` block ahead of the existing `Host kai-server` entry, e.g. ``` Match host kai-server exec "ping -c1 -t1 kai-server.local >/dev/null 2>&1" HostName kai-server.local ``` On the home LAN the mDNS probe succeeds and ssh uses the LAN path. Off-LAN the probe fails (~1s) and resolution falls through to the existing tailnet-FQDN HostName. Validate the probe choice on macOS (`ping -t` is the macOS timeout flag, Linux clients need `-W`). * Keep the tailnet FQDN out of tracked files - it stays SSM-resolved (`/coilysiren/kai-server/tailnet-fqdn`) per the opaque-ids rule. The `.local` name and the `kai-server` short name are meaningful names and hardcode fine. * Retire the inert `lan-hosts` `/etc/hosts` role (`ansible/roles/lan-hosts/`, `lan_hosts_enabled: false`) in the same change, or repurpose its home-LAN detection if useful. It should not land enabled alongside the ssh alias. ## Refs * #251 - chronic SSH hangs/drops tracker (diagnosis) * #266 / PR #250 - inert lan-hosts role (superseded by this approach) * o2r channel HDBF - full diagnosis thread, recurrence event 213
Author
Owner

Recurrence 2026-06-12 ~04:45 PT, reproduced from kais-macbook-pro while standing up the eco-app local dev loop (agent: claude-macos-kais-macbook-pro-ve79-she-her).

Same signature as the 2026-06-11 event:

  • tailscale ping from kai-server to the Mac: pong DIRECT via link-local IPv6 %enp1s0 in 4ms, tx/rx both nonzero.
  • From the Mac, TCP to the kai-server tailnet IP on :22 / :80 / :443 / :3001 all time out (route correctly via utun4, MagicDNS resolves and matches the SSM-cached IP).
  • LAN path clean throughout: kai-server.local:3001/info answers HTTP 200 in 0.16s, public eco.coilysiren.me:3001 200 in 0.39s.
  • EcoServer binds 0.0.0.0:3001 and self-curl on its own tailnet IP returns 200, so the drop is in the Mac-to-server tunnel data path only.

Workaround used: pointed the eco-app dev loop at kai-server.local:3001 via env (ECO_INFO_URL etc.), mirroring the ssh-config mDNS alias this issue landed.

Recurrence 2026-06-12 ~04:45 PT, reproduced from kais-macbook-pro while standing up the eco-app local dev loop (agent: claude-macos-kais-macbook-pro-ve79-she-her). Same signature as the 2026-06-11 event: * `tailscale ping` from kai-server to the Mac: pong DIRECT via link-local IPv6 `%enp1s0` in 4ms, tx/rx both nonzero. * From the Mac, TCP to the kai-server tailnet IP on :22 / :80 / :443 / :3001 all time out (route correctly via utun4, MagicDNS resolves and matches the SSM-cached IP). * LAN path clean throughout: `kai-server.local:3001/info` answers HTTP 200 in 0.16s, public `eco.coilysiren.me:3001` 200 in 0.39s. * EcoServer binds `0.0.0.0:3001` and self-curl on its own tailnet IP returns 200, so the drop is in the Mac-to-server tunnel data path only. Workaround used: pointed the eco-app dev loop at `kai-server.local:3001` via env (`ECO_INFO_URL` etc.), mirroring the ssh-config mDNS alias this issue landed.
coilysiren added
P3
and removed
P2
labels 2026-06-17 08:39:31 +00:00
Sign in to join this conversation.
No description provided.