hscontrol: name listener bind failures via ListenerBindError

Replace the three "binding to TCP address" wraps with typed
ListenerBindError values that carry the listener role, the YAML key
that drove the address, and the resolved address. The wrapped error
chain still walks to syscall.EADDRINUSE / EACCES so existing callers
that match those sentinels keep working; the difference is that the
operator now sees which listener failed instead of an unattributed
"binding to TCP address" line.

Updates #3227
This commit is contained in:
Kristoffer Dalby
2026-04-30 08:25:57 +00:00
parent 43ad10da52
commit 37e1904924
+12 -2
View File
@@ -711,7 +711,12 @@ func (h *Headscale) Serve() error {
}
if err != nil {
return fmt.Errorf("binding to TCP address: %w", err)
return &types.ListenerBindError{
Listener: "main HTTP",
YAMLKey: "listen_addr",
Addr: h.cfg.Addr,
Err: err,
}
}
errorGroup.Go(func() error { return httpServer.Serve(httpListener) })
@@ -727,7 +732,12 @@ func (h *Headscale) Serve() error {
if h.cfg.MetricsAddr != "" {
debugHTTPListener, err = (&net.ListenConfig{}).Listen(ctx, "tcp", h.cfg.MetricsAddr)
if err != nil {
return fmt.Errorf("binding to TCP address: %w", err)
return &types.ListenerBindError{
Listener: "metrics",
YAMLKey: "metrics_listen_addr",
Addr: h.cfg.MetricsAddr,
Err: err,
}
}
debugHTTPServer = h.debugHTTPServer()