Skip to content

chore: cherry-pick coder desktop + corporate vpn fixes for 2.24 #19177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ jobs:
- name: Disable Spotlight Indexing
if: runner.os == 'macOS'
run: |
enabled=$(sudo mdutil -a -s | grep "Indexing enabled" | wc -l)
if [ $enabled -eq 0 ]; then
echo "Spotlight indexing is already disabled"
exit 0
fi
sudo mdutil -a -i off
sudo mdutil -X /
sudo launchctl bootout system /System/Library/LaunchDaemons/com.apple.metadata.mds.plist
Expand Down Expand Up @@ -1082,7 +1087,7 @@ jobs:
- name: Switch XCode Version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: "16.0.0"
xcode-version: "16.1.0"

- name: Setup Go
uses: ./.github/actions/setup-go
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
- name: Switch XCode Version
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
with:
xcode-version: "16.0.0"
xcode-version: "16.1.0"

- name: Setup Go
uses: ./.github/actions/setup-go
Expand Down Expand Up @@ -655,7 +655,7 @@ jobs:
detached_signature="${binary}.asc"
gcloud storage cp "./site/out/bin/${binary}" "gs://releases.coder.com/coder-cli/${version}/${binary}"
gcloud storage cp "./site/out/bin/${detached_signature}" "gs://releases.coder.com/coder-cli/${version}/${detached_signature}"
done
done

- name: Publish release
run: |
Expand Down
73 changes: 73 additions & 0 deletions cli/vpndaemon_darwin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//go:build darwin

package cli

import (
"golang.org/x/xerrors"

"cdr.dev/slog"
"github.com/coder/coder/v2/vpn"
"github.com/coder/serpent"
)

func (r *RootCmd) vpnDaemonRun() *serpent.Command {
var (
rpcReadFD int64
rpcWriteFD int64
)

cmd := &serpent.Command{
Use: "run",
Short: "Run the VPN daemon on macOS.",
Middleware: serpent.Chain(
serpent.RequireNArgs(0),
),
Options: serpent.OptionSet{
{
Flag: "rpc-read-fd",
Env: "CODER_VPN_DAEMON_RPC_READ_FD",
Description: "The file descriptor for the pipe to read from the RPC connection.",
Value: serpent.Int64Of(&rpcReadFD),
Required: true,
},
{
Flag: "rpc-write-fd",
Env: "CODER_VPN_DAEMON_RPC_WRITE_FD",
Description: "The file descriptor for the pipe to write to the RPC connection.",
Value: serpent.Int64Of(&rpcWriteFD),
Required: true,
},
},
Handler: func(inv *serpent.Invocation) error {
ctx := inv.Context()

if rpcReadFD < 0 || rpcWriteFD < 0 {
return xerrors.Errorf("rpc-read-fd (%v) and rpc-write-fd (%v) must be positive", rpcReadFD, rpcWriteFD)
}
if rpcReadFD == rpcWriteFD {
return xerrors.Errorf("rpc-read-fd (%v) and rpc-write-fd (%v) must be different", rpcReadFD, rpcWriteFD)
}

pipe, err := vpn.NewBidirectionalPipe(uintptr(rpcReadFD), uintptr(rpcWriteFD))
if err != nil {
return xerrors.Errorf("create bidirectional RPC pipe: %w", err)
}
defer pipe.Close()

tunnel, err := vpn.NewTunnel(ctx, slog.Make().Leveled(slog.LevelDebug), pipe,
vpn.NewClient(),
vpn.UseOSNetworkingStack(),
vpn.UseAsLogger(),
)
if err != nil {
return xerrors.Errorf("create new tunnel for client: %w", err)
}
defer tunnel.Close()

<-ctx.Done()
return nil
},
}

return cmd
}
2 changes: 1 addition & 1 deletion cli/vpndaemon_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build !windows
//go:build !windows && !darwin

package cli

Expand Down
5 changes: 1 addition & 4 deletions cli/vpndaemon_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,7 @@ func (r *RootCmd) vpnDaemonRun() *serpent.Command {
defer pipe.Close()

logger.Info(ctx, "starting tunnel")
tunnel, err := vpn.NewTunnel(ctx, logger, pipe, vpn.NewClient(),
vpn.UseOSNetworkingStack(),
vpn.UseCustomLogSinks(sinks...),
)
tunnel, err := vpn.NewTunnel(ctx, logger, pipe, vpn.NewClient(), vpn.UseOSNetworkingStack())
if err != nil {
return xerrors.Errorf("create new tunnel for client: %w", err)
}
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ replace github.com/tcnksm/go-httpstat => github.com/coder/go-httpstat v0.0.0-202

// There are a few minor changes we make to Tailscale that we're slowly upstreaming. Compare here:
// https://github.com/tailscale/tailscale/compare/main...coder:tailscale:main
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c
replace tailscale.com => github.com/coder/tailscale v1.1.1-0.20250729141742-067f1e5d9716

// This is replaced to include
// 1. a fix for a data race: c.f. https://github.com/tailscale/wireguard-go/pull/25
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -926,8 +926,8 @@ github.com/coder/serpent v0.10.0 h1:ofVk9FJXSek+SmL3yVE3GoArP83M+1tX+H7S4t8BSuM=
github.com/coder/serpent v0.10.0/go.mod h1:cZFW6/fP+kE9nd/oRkEHJpG6sXCtQ+AX7WMMEHv0Y3Q=
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788 h1:YoUSJ19E8AtuUFVYBpXuOD6a/zVP3rcxezNsoDseTUw=
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788/go.mod h1:aGQbuCLyhRLMzZF067xc84Lh7JDs1FKwCmF1Crl9dxQ=
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c h1:d/qBIi3Ez7KkopRgNtfdvTMqvqBg47d36qVfkd3C5EQ=
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
github.com/coder/tailscale v1.1.1-0.20250729141742-067f1e5d9716 h1:hi7o0sA+RPBq8Rvvz+hNrC/OTL2897OKREMIRIuQeTs=
github.com/coder/tailscale v1.1.1-0.20250729141742-067f1e5d9716/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e h1:JNLPDi2P73laR1oAclY6jWzAbucf70ASAvf5mh2cME0=
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI=
github.com/coder/terraform-provider-coder/v2 v2.7.1-0.20250623193313-e890833351e2 h1:vtGzECz5CyzuxMODexWdIRxhYLqyTcHafuJpH60PYhM=
Expand Down
14 changes: 12 additions & 2 deletions tailnet/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ const EnvMagicsockDebugLogging = "CODER_MAGICSOCK_DEBUG_LOGGING"

func init() {
// Globally disable network namespacing. All networking happens in
// userspace.
// userspace unless the connection is configured to use a TUN.
// NOTE: this exists in init() so it affects all connections (incl. DERP)
// made by tailscale packages by default.
netns.SetEnabled(false)
// Tailscale, by default, "trims" the set of peers down to ones that we are
// "actively" communicating with in an effort to save memory. Since
Expand Down Expand Up @@ -100,6 +102,7 @@ type Options struct {
BlockEndpoints bool
Logger slog.Logger
ListenPort uint16

// CaptureHook is a callback that captures Disco packets and packets sent
// into the tailnet tunnel.
CaptureHook capture.Callback
Expand Down Expand Up @@ -154,7 +157,14 @@ func NewConn(options *Options) (conn *Conn, err error) {
return nil, xerrors.New("At least one IP range must be provided")
}

netns.SetEnabled(options.TUNDev != nil)
useNetNS := options.TUNDev != nil
options.Logger.Debug(context.Background(), "network isolation configuration", slog.F("use_netns", useNetNS))
netns.SetEnabled(useNetNS)
// The Coder soft isolation mode is a workaround to allow Coder Connect to
// connect to Coder servers behind corporate VPNs, and relaxes some of the
// loop protections that come with Tailscale.
// See the comment above the netns function for more details.
netns.SetCoderSoftIsolation(useNetNS)

var telemetryStore *TelemetryStore
if options.TelemetrySink != nil {
Expand Down
6 changes: 0 additions & 6 deletions vpn/tunnel.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,12 +192,6 @@ func UseAsLogger() TunnelOption {
}
}

func UseCustomLogSinks(sinks ...slog.Sink) TunnelOption {
return func(t *Tunnel) {
t.clientLogger = t.clientLogger.AppendSinks(sinks...)
}
}

func WithClock(clock quartz.Clock) TunnelOption {
return func(t *Tunnel) {
t.clock = clock
Expand Down
Loading