From c86559abdd8681847a6459366b6c59a7173d6721 Mon Sep 17 00:00:00 2001 From: Leopere Date: Wed, 1 Apr 2026 12:08:36 -0400 Subject: [PATCH] fixing tunnel_host --- cmd/client/main.go | 56 ++++++++++++++++++++++++++++++++++++++-------- ship.sh | 15 +++---------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/cmd/client/main.go b/cmd/client/main.go index b4e434c..9d7ee33 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -1,11 +1,13 @@ package main import ( + "fmt" "log" "os" "strconv" "strings" "time" + "unicode" "github.com/nixc/reverse-ssh-traefik/internal/buildinfo" "github.com/nixc/reverse-ssh-traefik/internal/client" @@ -26,6 +28,45 @@ func envOr(key, fallback string) string { return fallback } +// cleanHost strips BOM, NULs, and all Unicode whitespace (including NBSP) from ends. +func cleanHost(s string) string { + s = strings.ReplaceAll(s, "\x00", "") + s = strings.TrimPrefix(s, "\ufeff") + s = strings.TrimFunc(s, unicode.IsSpace) + return s +} + +// resolveBackendHost picks backend hostname. Priority: +// 1) TUNNEL_HOST_FILE (path to a file containing hostname, e.g. Docker secret mount) +// 2) TUNNEL_HOST +// 3) TUNNEL_BACKEND_HOST (alias for stacks that reserve TUNNEL_HOST) +// 4) 127.0.0.1 +func resolveBackendHost() (host string, source string) { + path := cleanHost(os.Getenv("TUNNEL_HOST_FILE")) + if path != "" { + b, err := os.ReadFile(path) + if err != nil { + log.Fatalf("TUNNEL_HOST_FILE %q: %v", path, err) + } + h := cleanHost(string(b)) + if h != "" { + return h, fmt.Sprintf("TUNNEL_HOST_FILE(%s)", path) + } + log.Fatalf("TUNNEL_HOST_FILE %q is empty after trim", path) + } + for _, key := range []string{"TUNNEL_HOST", "TUNNEL_BACKEND_HOST"} { + raw := os.Getenv(key) + h := cleanHost(raw) + if h != "" { + return h, key + } + if raw != "" && h == "" { + log.Printf("tunnel-client: %s is set but only whitespace/control after clean (len=%d); trying next key / default", key, len(raw)) + } + } + return "127.0.0.1", "default(127.0.0.1)" +} + func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) log.Printf("tunnel-client starting commit=%s", buildinfo.Commit) @@ -38,13 +79,8 @@ func main() { authUser := envOr("TUNNEL_AUTH_USER", "") authPass := envOr("TUNNEL_AUTH_PASS", "") - // Backend: trim so compose/YAML stray spaces do not defeat the override (empty → default). - rawHost := strings.TrimSpace(os.Getenv("TUNNEL_HOST")) - localHost := rawHost - if localHost == "" { - localHost = "127.0.0.1" - } - localPortStr := strings.TrimSpace(os.Getenv("TUNNEL_PORT")) + localHost, hostSrc := resolveBackendHost() + localPortStr := cleanHost(os.Getenv("TUNNEL_PORT")) if localPortStr == "" { localPortStr = "8080" } @@ -52,8 +88,10 @@ func main() { if err != nil { log.Fatalf("Invalid TUNNEL_PORT=%q: %v", localPortStr, err) } - log.Printf("tunnel-client config: TUNNEL_HOST env raw=%q → backend host %q; TUNNEL_PORT=%q → %d", - os.Getenv("TUNNEL_HOST"), localHost, os.Getenv("TUNNEL_PORT"), localPort) + log.Printf("tunnel-client config: backend host %q (source=%s); port=%d (TUNNEL_PORT raw=%q)", + localHost, hostSrc, localPort, os.Getenv("TUNNEL_PORT")) + log.Printf("tunnel-client env (for debugging): TUNNEL_HOST=%q TUNNEL_BACKEND_HOST=%q TUNNEL_HOST_FILE=%q", + os.Getenv("TUNNEL_HOST"), os.Getenv("TUNNEL_BACKEND_HOST"), os.Getenv("TUNNEL_HOST_FILE")) // Load the private key. signer, err := client.LoadPrivateKey(keyPath) diff --git a/ship.sh b/ship.sh index deb5dfb..0a3efd2 100755 --- a/ship.sh +++ b/ship.sh @@ -4,7 +4,7 @@ # 1. git add -A # 2. git commit (or --allow-empty if nothing staged) # 3. GIT_COMMIT → Docker --build-arg (baked into binaries) -# 4. docker login ghcr.io — always: gh api user + gh auth token (no other auth path) +# 4. docker login ghcr.io — gh auth token + gh api user (one step; fails if gh/docker not ready) # 5. buildx --push per arch + imagetools manifest (server + client) — always, no skips # 6. git push — always # @@ -103,17 +103,8 @@ GIT_COMMIT="$(git rev-parse HEAD)" BA=(--build-arg "GIT_COMMIT=${GIT_COMMIT}") echo "==> GIT_COMMIT=${GIT_COMMIT}" -echo "==> [3/6] docker login ghcr.io (gh api user + gh auth token)" -GH_LOGIN="$(gh api user -q .login)" -if [[ -z "${GH_LOGIN}" ]]; then - echo "ship: fatal: gh not logged in" >&2 - exit 1 -fi -if ! token="$(gh auth token)" || [[ -z "${token}" ]]; then - echo "ship: fatal: gh auth token empty" >&2 - exit 1 -fi -if ! printf '%s' "$token" | docker login ghcr.io -u "$GH_LOGIN" --password-stdin; then +echo "==> [3/6] docker login ghcr.io" +if ! printf '%s' "$(gh auth token)" | docker login ghcr.io -u "$(gh api user -q .login)" --password-stdin; then echo "ship: fatal: docker login ghcr.io failed" >&2 exit 1 fi