From a4ec76605e1b45e5e01f52545c3b7eab34a016ba Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Fri, 26 Jun 2026 13:16:43 +0000 Subject: [PATCH] integration/tsic: add WithDERPOverHTTP for the non-TLS embedded DERP Sets TS_DEBUG_DERP_WS_CLIENT + TS_DEBUG_USE_DERP_HTTP so a client can reach hsic's plain-HTTP embedded DERP over websockets; the counterpart to hsic.WithoutTLS. --- integration/tsic/tsic.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/integration/tsic/tsic.go b/integration/tsic/tsic.go index 901a263e..3e19d2b1 100644 --- a/integration/tsic/tsic.go +++ b/integration/tsic/tsic.go @@ -98,6 +98,7 @@ type TailscaleInContainer struct { caCerts [][]byte headscaleHostname string withWebsocketDERP bool + withDERPOverHTTP bool withSSH bool withTags []string withEntrypoint []string @@ -160,6 +161,18 @@ func WithWebsocketDERP(enabled bool) Option { } } +// WithDERPOverHTTP makes the client reach the DERP server over plain-HTTP +// websockets (TS_DEBUG_DERP_WS_CLIENT + TS_DEBUG_USE_DERP_HTTP). It is the +// counterpart to [hsic.WithoutTLS]: a Headscale serving its embedded DERP without +// TLS is otherwise unreachable, because the client defaults to dialing DERP over +// HTTPS. +func WithDERPOverHTTP() Option { + return func(tsic *TailscaleInContainer) { + tsic.withWebsocketDERP = true + tsic.withDERPOverHTTP = true + } +} + // WithSSH enables SSH for the Tailscale instance. func WithSSH() Option { return func(tsic *TailscaleInContainer) { @@ -372,6 +385,12 @@ func New( tailscaleOptions.Env, fmt.Sprintf("TS_DEBUG_DERP_WS_CLIENT=%t", tsic.withWebsocketDERP), ) + + // Plain-HTTP DERP additionally needs the client to dial http:// instead of + // the default https://; see [WithDERPOverHTTP]. + if tsic.withDERPOverHTTP { + tailscaleOptions.Env = append(tailscaleOptions.Env, "TS_DEBUG_USE_DERP_HTTP=true") + } } tailscaleOptions.ExtraHosts = append(tailscaleOptions.ExtraHosts,