From fa7b54f5ab0b1c445053b2a8dc629e5c32a208b2 Mon Sep 17 00:00:00 2001 From: Minseong Choi Date: Tue, 22 Sep 2026 14:08:11 +0900 Subject: [PATCH] fix(bootstrap): refuse an unbracketed ipv6 nano listen address validate_listen checked only the port, so FELIS_NANO_LISTEN=::1:8081 passed. Go refuses that form ("too many colons in address") and needs [::1]:8081, so the unit crash-looped on every start. A host part that contains a colon must now be in brackets. With that, the bare ::1 pattern in nano_listen_is_loopback can no longer match an address that gets this far, so it goes. [::1] stays. The harness adds ::1:8081 to the refused addresses, and [::]:8081 and :8081, both of which Go binds, to the accepted ones. --- deploy/bootstrap.sh | 8 ++++++-- deploy/bootstrap_test.sh | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/deploy/bootstrap.sh b/deploy/bootstrap.sh index 7a72529..b9bfbab 100644 --- a/deploy/bootstrap.sh +++ b/deploy/bootstrap.sh @@ -453,12 +453,16 @@ validate_nodeport() { # port 8081 while nano binds nothing, 127.0.0.1 prints http://127.0.0.1:127.0.0.1/..., and # the unit crash-loops either way. validate_listen() { - local name="$1" value="$2" port="${2##*:}" + local name="$1" value="$2" port="${2##*:}" host="${2%:*}" case "$value" in *:*) ;; *) port="" ;; esac case "$port" in ''|*[!0-9]*) die "${name} must be host:port (for example 127.0.0.1:8081), got: ${value}" ;; esac [ "$port" -ge 1 ] && [ "$port" -le 65535 ] || die "${name} port must be 1-65535, got: ${value}" + # Go takes a colon in the host only inside brackets; ::1:8081 would crash-loop the unit. + case "$host" in + *:*) case "$host" in "["*"]") ;; *) die "${name} needs an IPv6 host in brackets (for example [::1]:8081), got: ${value}" ;; esac ;; + esac } validate_settings() { @@ -2410,7 +2414,7 @@ resolve_nano_listen() { nano_listen_is_loopback() { case "${FELIS_NANO_LISTEN%:*}" in - 127.*|localhost|::1|"[::1]") return 0 ;; + 127.*|localhost|"[::1]") return 0 ;; *) return 1 ;; esac } diff --git a/deploy/bootstrap_test.sh b/deploy/bootstrap_test.sh index e363859..0157bbf 100644 --- a/deploy/bootstrap_test.sh +++ b/deploy/bootstrap_test.sh @@ -295,10 +295,10 @@ check_listen() { # value validate_listen FELIS_NANO_LISTEN "$1" && echo VALID' _ "$1" 2>&1 } -for v in 8081 127.0.0.1 127.0.0.1:0 127.0.0.1:65536 127.0.0.1:x; do +for v in 8081 127.0.0.1 127.0.0.1:0 127.0.0.1:65536 127.0.0.1:x ::1:8081; do expect "listen address $v is refused" "DIE: FELIS_NANO_LISTEN" "$(check_listen "$v")" done -for v in '[::1]:8081' 0.0.0.0:8081 127.0.0.1:8081; do +for v in '[::1]:8081' '[::]:8081' :8081 0.0.0.0:8081 127.0.0.1:8081; do expect "listen address $v is accepted" VALID "$(check_listen "$v")" done