Skip to content

Commit f3e9234

Browse files
hhfrancoisclaude
andcommitted
fix(tun): skip host-key pinning for localhost + surface daemon errors
Two dev-ergonomics fixes found while testing the daemon against a local agent: - TOFU host-key pinning is pointless for a loopback agent (nothing to intercept) and caused false "host key changed" failures every time a local dev agent (e.g. a recreated container) came up with a fresh key. Skip pinning for localhost / 127.0.0.1 / ::1; keep pinning real hosts. - When the detached macOS daemon fails to come up, the launcher printed an opaque "daemon did not come up (see <log>)". Surface the daemon's actual last log line (e.g. the connect error) directly on the terminal. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c52a709 commit f3e9234

2 files changed

Lines changed: 42 additions & 6 deletions

File tree

cli/daemon_darwin.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os/exec"
1010
"os/signal"
1111
"path/filepath"
12+
"strings"
1213
"syscall"
1314
"time"
1415

@@ -158,9 +159,25 @@ func startDaemonDetached(cfg config) error {
158159
if n, _ := r.Read(buf); n == 1 {
159160
return nil // ready
160161
}
162+
// Surface the daemon's own failure reason (its last log line) instead of an
163+
// opaque "did not come up".
164+
if reason := lastLogLine(logPath); reason != "" {
165+
return fmt.Errorf("%s", reason)
166+
}
161167
return fmt.Errorf("daemon did not come up (see %s)", logPath)
162168
}
163169

170+
// lastLogLine returns the last non-empty line of the daemon log — its failure
171+
// reason — stripped of the "[plug] " prefix.
172+
func lastLogLine(path string) string {
173+
b, err := os.ReadFile(path)
174+
if err != nil {
175+
return ""
176+
}
177+
lines := strings.Split(strings.TrimRight(string(b), "\n"), "\n")
178+
return strings.TrimPrefix(strings.TrimSpace(lines[len(lines)-1]), "[plug] ")
179+
}
180+
164181
// cmdDown stops the running datapath daemon for the resolved cluster (`plug down`).
165182
func cmdDown(args []string) {
166183
opts, _ := parseArgs(args)

cli/socks_run.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,39 @@
11
package main
22

33
import (
4+
"net"
45
"os"
56
"path/filepath"
67

78
"github.com/softwarity/plug/cli/internal/tunnel"
89
)
910

10-
// dialTunnel opens the SSH transport to the cluster agent (TOFU host-key pin next
11-
// to the profiles). Shared by coreRun (Linux/Windows) and the macOS datapath
12-
// daemon. coreRun itself is per-OS (socks_run_darwin.go / socks_run_other.go):
13-
// macOS routes through a persistent daemon, elsewhere each launch is autonomous.
11+
// dialTunnel opens the SSH transport to the cluster agent. Shared by coreRun
12+
// (Linux/Windows) and the macOS datapath daemon. coreRun itself is per-OS
13+
// (socks_run_darwin.go / socks_run_other.go): macOS routes through a persistent
14+
// daemon, elsewhere each launch is autonomous.
1415
func dialTunnel(cfg config) (*tunnel.Transport, error) {
1516
knownHosts := ""
16-
if home, err := os.UserHomeDir(); err == nil {
17-
knownHosts = filepath.Join(home, ".plug", "known_hosts")
17+
// TOFU host-key pinning is pointless for a loopback agent (there is no network
18+
// to intercept) and just causes false "host key changed" errors when a local
19+
// dev agent is recreated with a fresh key — so skip it for localhost. For real
20+
// hosts, pin the key next to the profiles.
21+
if !isLoopback(cfg.host) {
22+
if home, err := os.UserHomeDir(); err == nil {
23+
knownHosts = filepath.Join(home, ".plug", "known_hosts")
24+
}
1825
}
1926
return tunnel.Dial(cfg.host, cfg.port, sshUser, embeddedKey, knownHosts, info)
2027
}
28+
29+
// isLoopback reports whether host is the local machine (no network to intercept).
30+
func isLoopback(host string) bool {
31+
switch host {
32+
case "localhost", "127.0.0.1", "::1":
33+
return true
34+
}
35+
if ip := net.ParseIP(host); ip != nil {
36+
return ip.IsLoopback()
37+
}
38+
return false
39+
}

0 commit comments

Comments
 (0)