Migration: server bind address & loopback metrics default¶
This batch threads a bind address through the managed server stack, hardens a
default that previously exposed a diagnostics surface on all interfaces, and turns
a silently-swallowed port error into a hard failure. It ships as part of the
transport-stack follow-ups (go/transport v0.2.0, go/transport-metrics
v0.4.0).
What changed¶
1. Bind address is now configurable (additive)¶
pkg/http and pkg/grpc server settings gain a Host field, surfaced as the
config keys server.http.host and server.grpc.host (and any custom prefix,
e.g. server.admin.host). Both default to "", which binds all interfaces
(0.0.0.0 / [::]) — unchanged from previous releases.
server:
http:
port: 8080
host: 127.0.0.1 # NEW: restrict the HTTP listener to loopback
grpc:
port: 9090
host: 127.0.0.1 # NEW: restrict the gRPC listener to loopback
The transport constructors also accept a programmatic
transporthttp.WithHost(...) / transportgrpc.WithHost(...) option (alias
WithBindAddress) which overrides the configured value.
Action: none required. Opt in by setting host on any listener that should
not be reachable off-host — management, admin, metrics, and pprof endpoints in
particular.
2. Standalone metrics server now defaults to loopback¶
Behaviour change — the metrics/pprof server binds loopback by default
The standalone metrics server shipped by
go/transport-metrics
(v0.4.0) now defaults its bind host to 127.0.0.1 instead of the
previous implicit all-interfaces bind. A WithPprof() metrics server exposes
heap dumps and 30-second CPU profiles — an information-disclosure and DoS
surface — so loopback is the safe default.
If you scrape a standalone metrics server over the network today, it will stop being reachable after this upgrade. Restore the previous behaviour explicitly:
// all interfaces (previous default)
srv := metricsserver.New(reg, metricsserver.WithBindAddress(""))
// or a specific address
srv := metricsserver.New(reg, metricsserver.WithHost("10.0.0.5"))
Prefer keeping the loopback default and scraping via a sidecar or an SSH/localhost tunnel where possible.
The managed HTTP and gRPC servers (items above) keep the all-interfaces default for compatibility; only the standalone metrics server changes its default.
3. An out-of-range explicit port is now a hard error¶
Previously, passing an out-of-range port to the pkg/http adapters
(NewServerFromReader / RegisterFromReader) via WithPort short-circuited to
an empty settings value — an OS-assigned ephemeral port (:0) — so a typo'd
port produced a "healthy" server on an unpredictable port nobody could find. The
adapter now forwards the value to the transport constructor's validation, which
rejects it:
// before: returned a server bound to a random ephemeral port
// after: returns a descriptive error
srv, err := gtbhttp.NewServerFromReader(ctx, cfg, handler, gtbhttp.WithPort(70000))
// err: "http: invalid port 70000 (must be 0-65535)"
Action: none for valid ports. If you relied on an out-of-range port silently
becoming an ephemeral bind, pass WithPort(0) explicitly to request an ephemeral
port.
4. Unsupported adapter options no longer vanish silently¶
The pkg/http and pkg/grpc server adapters previously ignored any option value
outside their accepted families — so a mis-targeted interceptor/middleware chain
could be dropped, leaving a server unconfigured. Constructors that return an error
(NewServerFromReader) now error naming the rejected concrete type; surfaces
without an error return (StartFromReader) log a WARN. Passing only
supported option types is unaffected.