Skip to content

Commit bc502b5

Browse files
ethanndicksonjohnstcndeansheather
authored
chore: cherry-pick coder desktop + corporate vpn fixes for 2.24 (#19177)
This backports the coder/coder fixes for coder/coder-desktop-windows#147 and coder/coder-desktop-macos#201 to v2.24, and fixes a bug where Coder Desktop logs were duplicated on Windows. 1. #19124 (`c64b3c0d8327edbfad4cc7bc373bdb873cd7e26b`) - Required for CI to pass. 2. #19125 (`9f2dc72d9a3d9feecf28bc30cd1234394a0e5c37`) - Required for CI to pass. 3. #19143 (`914daac2dcf700817d4ae248a6e8014f64654fe7`) - Required for CI to pass. 4. #19023 (`618121cba39833db7c1ca4653d7ce7745d5aff57`) - First implementation of fix for coder/coder-desktop-windows#147 5. #19069 (`ba0b124a1daaddde590f5839afebe803330981be`) - Partially reverts previous commit, actual fix for coder/coder-desktop-windows#147 6. #19052 (`19171e27c9624c435f97d4ae5e3b61c649bc7063`) - Avoid duplicating logs on Coder Desktop Windows 7. #19080 (`18b037d0086cd6eca11e6180b36a302badaa5a5f`) - Updates coder/tailscale reference, lets Coder Desktop macOS use the slim binary to run Coder Connect. I've tested my latest build of Coder Desktop against a Coder server running this branch, just as a sanity check. --------- Co-authored-by: Cian Johnston <cian@coder.com> Co-authored-by: Dean Sheather <dean@deansheather.com>
1 parent d6b2ca1 commit bc502b5

File tree

9 files changed

+98
-19
lines changed

9 files changed

+98
-19
lines changed

.github/workflows/ci.yaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,11 @@ jobs:
428428
- name: Disable Spotlight Indexing
429429
if: runner.os == 'macOS'
430430
run: |
431+
enabled=$(sudo mdutil -a -s | grep "Indexing enabled" | wc -l)
432+
if [ $enabled -eq 0 ]; then
433+
echo "Spotlight indexing is already disabled"
434+
exit 0
435+
fi
431436
sudo mdutil -a -i off
432437
sudo mdutil -X /
433438
sudo launchctl bootout system /System/Library/LaunchDaemons/com.apple.metadata.mds.plist
@@ -1082,7 +1087,7 @@ jobs:
10821087
- name: Switch XCode Version
10831088
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
10841089
with:
1085-
xcode-version: "16.0.0"
1090+
xcode-version: "16.1.0"
10861091

10871092
- name: Setup Go
10881093
uses: ./.github/actions/setup-go

.github/workflows/release.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
- name: Switch XCode Version
6161
uses: maxim-lobanov/setup-xcode@60606e260d2fc5762a71e64e74b2174e8ea3c8bd # v1.6.0
6262
with:
63-
xcode-version: "16.0.0"
63+
xcode-version: "16.1.0"
6464

6565
- name: Setup Go
6666
uses: ./.github/actions/setup-go
@@ -655,7 +655,7 @@ jobs:
655655
detached_signature="${binary}.asc"
656656
gcloud storage cp "./site/out/bin/${binary}" "gs://releases.coder.com/coder-cli/${version}/${binary}"
657657
gcloud storage cp "./site/out/bin/${detached_signature}" "gs://releases.coder.com/coder-cli/${version}/${detached_signature}"
658-
done
658+
done
659659
660660
- name: Publish release
661661
run: |

cli/vpndaemon_darwin.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//go:build darwin
2+
3+
package cli
4+
5+
import (
6+
"golang.org/x/xerrors"
7+
8+
"cdr.dev/slog"
9+
"github.com/coder/coder/v2/vpn"
10+
"github.com/coder/serpent"
11+
)
12+
13+
func (r *RootCmd) vpnDaemonRun() *serpent.Command {
14+
var (
15+
rpcReadFD int64
16+
rpcWriteFD int64
17+
)
18+
19+
cmd := &serpent.Command{
20+
Use: "run",
21+
Short: "Run the VPN daemon on macOS.",
22+
Middleware: serpent.Chain(
23+
serpent.RequireNArgs(0),
24+
),
25+
Options: serpent.OptionSet{
26+
{
27+
Flag: "rpc-read-fd",
28+
Env: "CODER_VPN_DAEMON_RPC_READ_FD",
29+
Description: "The file descriptor for the pipe to read from the RPC connection.",
30+
Value: serpent.Int64Of(&rpcReadFD),
31+
Required: true,
32+
},
33+
{
34+
Flag: "rpc-write-fd",
35+
Env: "CODER_VPN_DAEMON_RPC_WRITE_FD",
36+
Description: "The file descriptor for the pipe to write to the RPC connection.",
37+
Value: serpent.Int64Of(&rpcWriteFD),
38+
Required: true,
39+
},
40+
},
41+
Handler: func(inv *serpent.Invocation) error {
42+
ctx := inv.Context()
43+
44+
if rpcReadFD < 0 || rpcWriteFD < 0 {
45+
return xerrors.Errorf("rpc-read-fd (%v) and rpc-write-fd (%v) must be positive", rpcReadFD, rpcWriteFD)
46+
}
47+
if rpcReadFD == rpcWriteFD {
48+
return xerrors.Errorf("rpc-read-fd (%v) and rpc-write-fd (%v) must be different", rpcReadFD, rpcWriteFD)
49+
}
50+
51+
pipe, err := vpn.NewBidirectionalPipe(uintptr(rpcReadFD), uintptr(rpcWriteFD))
52+
if err != nil {
53+
return xerrors.Errorf("create bidirectional RPC pipe: %w", err)
54+
}
55+
defer pipe.Close()
56+
57+
tunnel, err := vpn.NewTunnel(ctx, slog.Make().Leveled(slog.LevelDebug), pipe,
58+
vpn.NewClient(),
59+
vpn.UseOSNetworkingStack(),
60+
vpn.UseAsLogger(),
61+
)
62+
if err != nil {
63+
return xerrors.Errorf("create new tunnel for client: %w", err)
64+
}
65+
defer tunnel.Close()
66+
67+
<-ctx.Done()
68+
return nil
69+
},
70+
}
71+
72+
return cmd
73+
}

cli/vpndaemon_other.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//go:build !windows
1+
//go:build !windows && !darwin
22

33
package cli
44

cli/vpndaemon_windows.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ func (r *RootCmd) vpnDaemonRun() *serpent.Command {
6363
defer pipe.Close()
6464

6565
logger.Info(ctx, "starting tunnel")
66-
tunnel, err := vpn.NewTunnel(ctx, logger, pipe, vpn.NewClient(),
67-
vpn.UseOSNetworkingStack(),
68-
vpn.UseCustomLogSinks(sinks...),
69-
)
66+
tunnel, err := vpn.NewTunnel(ctx, logger, pipe, vpn.NewClient(), vpn.UseOSNetworkingStack())
7067
if err != nil {
7168
return xerrors.Errorf("create new tunnel for client: %w", err)
7269
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ replace github.com/tcnksm/go-httpstat => github.com/coder/go-httpstat v0.0.0-202
3636

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

4141
// This is replaced to include
4242
// 1. a fix for a data race: c.f. https://github.com/tailscale/wireguard-go/pull/25

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -926,8 +926,8 @@ github.com/coder/serpent v0.10.0 h1:ofVk9FJXSek+SmL3yVE3GoArP83M+1tX+H7S4t8BSuM=
926926
github.com/coder/serpent v0.10.0/go.mod h1:cZFW6/fP+kE9nd/oRkEHJpG6sXCtQ+AX7WMMEHv0Y3Q=
927927
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788 h1:YoUSJ19E8AtuUFVYBpXuOD6a/zVP3rcxezNsoDseTUw=
928928
github.com/coder/ssh v0.0.0-20231128192721-70855dedb788/go.mod h1:aGQbuCLyhRLMzZF067xc84Lh7JDs1FKwCmF1Crl9dxQ=
929-
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c h1:d/qBIi3Ez7KkopRgNtfdvTMqvqBg47d36qVfkd3C5EQ=
930-
github.com/coder/tailscale v1.1.1-0.20250611020837-f14d20d23d8c/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
929+
github.com/coder/tailscale v1.1.1-0.20250729141742-067f1e5d9716 h1:hi7o0sA+RPBq8Rvvz+hNrC/OTL2897OKREMIRIuQeTs=
930+
github.com/coder/tailscale v1.1.1-0.20250729141742-067f1e5d9716/go.mod h1:l7ml5uu7lFh5hY28lGYM4b/oFSmuPHYX6uk4RAu23Lc=
931931
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e h1:JNLPDi2P73laR1oAclY6jWzAbucf70ASAvf5mh2cME0=
932932
github.com/coder/terraform-config-inspect v0.0.0-20250107175719-6d06d90c630e/go.mod h1:Gz/z9Hbn+4KSp8A2FBtNszfLSdT2Tn/uAKGuVqqWmDI=
933933
github.com/coder/terraform-provider-coder/v2 v2.7.1-0.20250623193313-e890833351e2 h1:vtGzECz5CyzuxMODexWdIRxhYLqyTcHafuJpH60PYhM=

tailnet/conn.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,9 @@ const EnvMagicsockDebugLogging = "CODER_MAGICSOCK_DEBUG_LOGGING"
6565

6666
func init() {
6767
// Globally disable network namespacing. All networking happens in
68-
// userspace.
68+
// userspace unless the connection is configured to use a TUN.
69+
// NOTE: this exists in init() so it affects all connections (incl. DERP)
70+
// made by tailscale packages by default.
6971
netns.SetEnabled(false)
7072
// Tailscale, by default, "trims" the set of peers down to ones that we are
7173
// "actively" communicating with in an effort to save memory. Since
@@ -100,6 +102,7 @@ type Options struct {
100102
BlockEndpoints bool
101103
Logger slog.Logger
102104
ListenPort uint16
105+
103106
// CaptureHook is a callback that captures Disco packets and packets sent
104107
// into the tailnet tunnel.
105108
CaptureHook capture.Callback
@@ -154,7 +157,14 @@ func NewConn(options *Options) (conn *Conn, err error) {
154157
return nil, xerrors.New("At least one IP range must be provided")
155158
}
156159

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

159169
var telemetryStore *TelemetryStore
160170
if options.TelemetrySink != nil {

vpn/tunnel.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,6 @@ func UseAsLogger() TunnelOption {
192192
}
193193
}
194194

195-
func UseCustomLogSinks(sinks ...slog.Sink) TunnelOption {
196-
return func(t *Tunnel) {
197-
t.clientLogger = t.clientLogger.AppendSinks(sinks...)
198-
}
199-
}
200-
201195
func WithClock(clock quartz.Clock) TunnelOption {
202196
return func(t *Tunnel) {
203197
t.clock = clock

0 commit comments

Comments
 (0)