Skip to content

bug: starting a workspace proxy while built in DERP server disabled causes wsproxy to error and exit #22317

@rowansmithau

Description

@rowansmithau

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

Attempting to start a workspace proxy and connect it to a Coder instance which has the built in DERP server disabled results in the workspace proxy failing to start and the Coder instance emitting a stacktrace.

Relayed from customer:

A MeshKey is only created if the coderd derp server is enabled. When workspace proxies try to register, they need to retrieve the mesh key, but hit a nil pointer exception because the derp server doesn't exist

Relevant Log Output

2026-02-26 01:42:43.760 [warn]  coderd: panic serving http request (recovered)  panic="runtime error: invalid memory address or nil pointer dereference" ...
    stack= goroutine 9569 [running]:
           runtime/debug.Stack()
                /opt/hostedtoolcache/go/1.25.6/x64/src/runtime/debug/stack.go:26 +0x64
           github.com/coder/coder/v2/coderd.New.Recover.func27.1.1()
                /home/runner/work/coder/coder/httpmw/recover.go:28 +0xcc
           panic({0x1142f3940?, 0x1177cc2a0?})
                /opt/hostedtoolcache/go/1.25.6/x64/src/runtime/panic.go:783 +0x120
           tailscale.com/derp.(*Server).MeshKey(...)
                /home/runner/go/pkg/mod/github.com/coder/[email protected]/derp/derp_server.go:369
           github.com/coder/coder/v2/enterprise/coderd.(*API).workspaceProxyRegister(0x14000782200, {0x114c1e080, 0x14014452dc0}, 0x140127f12c0)
                /home/runner/work/coder/coder/enterprise/coderd/workspaceproxy.go:713 +0x7bc
           net/http.HandlerFunc.ServeHTTP(0x14000fd8ff0?, {0x114c1e080?, 0x14014452dc0?}, 0x1401944e0c0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).routeHTTP(0x1400142c600, {0x114c1e080, 0x14014452dc0}, 0x140127f12c0)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:478 +0x250
           net/http.HandlerFunc.ServeHTTP(0x14000a27a40?, {0x114c1e080?, 0x14014452dc0?}, 0x117917b80?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/enterprise/coderd.New.func7.6.2.ExtractWorkspaceProxy.1.1({0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/work/coder/coder/coderd/httpmw/workspaceproxy.go:142 +0x284
           net/http.HandlerFunc.ServeHTTP(0x14001d57988?, {0x114c1e080?, 0x14014452dc0?}, 0x14001d57968?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).ServeHTTP(0x1400142c600, {0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:73 +0x294
           github.com/go-chi/chi/v5.(*Mux).Mount.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:325 +0x1c4
           net/http.HandlerFunc.ServeHTTP(0x14000fd8ff0?, {0x114c1e080?, 0x14014452dc0?}, 0x1401944e0b0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).routeHTTP(0x1400142c540, {0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:478 +0x250
           net/http.HandlerFunc.ServeHTTP(0x11f7b8ae0?, {0x114c1e080?, 0x14014452dc0?}, 0x1401944e0b0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/enterprise/coderd.New.func7.6.(*API).RequireFeatureMW.4.1({0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/work/coder/coder/enterprise/coderd/templates.go:338 +0x74
           net/http.HandlerFunc.ServeHTTP(0x14001d57c58?, {0x114c1e080?, 0x14014452dc0?}, 0x14001d57c38?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).ServeHTTP(0x1400142c540, {0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:73 +0x294
           github.com/go-chi/chi/v5.(*Mux).Mount.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:325 +0x1c4
           net/http.HandlerFunc.ServeHTTP(0x1401a70f752?, {0x114c1e080?, 0x14014452dc0?}, 0x1400138f910?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*ChainHandler).ServeHTTP(0x14000fd8ff0?, {0x114c1e080?, 0x14014452dc0?}, 0x1401a70f740?)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/chain.go:31 +0x2c
           github.com/go-chi/chi/v5.(*Mux).routeHTTP(0x1400141ccc0, {0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:478 +0x250
           net/http.HandlerFunc.ServeHTTP(0x107997275?, {0x114c1e080?, 0x14014452dc0?}, 0x616d65522d74696d?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/httpmw.ReportCLITelemetry.func1.1({0x114c1e080?, 0x14014452dc0?}, 0x14000a27a40)
                /home/runner/work/coder/coder/coderd/httpmw/clitelemetry.go:46 +0x368
           net/http.HandlerFunc.ServeHTTP(0x14000f453b0?, {0x114c1e080?, 0x14014452dc0?}, 0x14000a27a40?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/httprate.(*RateLimiter).Handler-fm.(*RateLimiter).Handler.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/[email protected]/limiter.go:148 +0x98
           net/http.HandlerFunc.ServeHTTP(0x14001d580c8?, {0x114c1e080?, 0x14014452dc0?}, 0x14001d580a8?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).ServeHTTP(0x1400141ccc0, {0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:73 +0x294
           github.com/go-chi/chi/v5.(*Mux).Mount.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:325 +0x1c4
           net/http.HandlerFunc.ServeHTTP(0x14000fd8ff0?, {0x114c1e080?, 0x14014452dc0?}, 0x1401774bce0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).routeHTTP(0x14000de1020, {0x114c1e080, 0x14014452dc0}, 0x14000a27a40)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:478 +0x250
           net/http.HandlerFunc.ServeHTTP(0x14000d65900?, {0x114c1e080?, 0x14014452dc0?}, 0x14000a27a40?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/justinas/nosurf.(*CSRFHandler).handleSuccess(...)
                /home/runner/go/pkg/mod/github.com/justinas/[email protected]/handler.go:178
           github.com/justinas/nosurf.(*CSRFHandler).ServeHTTP(0x14000d65900, {0x114c1e080, 0x14014452dc0}, 0x16?)
                /home/runner/go/pkg/mod/github.com/justinas/[email protected]/handler.go:151 +0x3ec
           github.com/coder/coder/v2/coderd.New.func5.1({0x114c1e080, 0x14014452dc0}, 0x14000a27900)
                /home/runner/work/coder/coder/coderd/coderd.go:933 +0x128
           net/http.HandlerFunc.ServeHTTP(0x14000d0c1e0?, {0x114c1e080?, 0x14014452dc0?}, 0x14000a27900?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/cors.(*Cors).Handler-fm.(*Cors).Handler.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27900)
                /home/runner/go/pkg/mod/github.com/go-chi/[email protected]/cors.go:228 +0x15c
           net/http.HandlerFunc.ServeHTTP(0x114bdc8e0?, {0x114c1e080?, 0x14014452dc0?}, 0x0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/httpmw.Cors.func1.1({0x114c1e080, 0x14014452dc0}, 0x14000a27900)
                /home/runner/work/coder/coder/coderd/httpmw/cors.go:89 +0x184
           net/http.HandlerFunc.ServeHTTP(0x80?, {0x114c1e080?, 0x14014452dc0?}, 0x10517f7fc?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd.New.(*Server).HandleSubdomain.func30.1({0x114c1e080, 0x14014452dc0}, 0x14000a27900)
                /home/runner/work/coder/coder/coderd/workspaceapps/proxy.go:435 +0x88
           net/http.HandlerFunc.ServeHTTP(0x0?, {0x114c1e080?, 0x14014452dc0?}, 0x15?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd.New.func4.1({0x114c1e080, 0x14014452dc0}, 0x14000a27900)
                /home/runner/work/coder/coder/coderd/coderd.go:916 +0x13c
           net/http.HandlerFunc.ServeHTTP(0x14011f0d170?, {0x114c1e080?, 0x14014452dc0?}, 0x10517bb40?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/httpmw.Prometheus.func1.1({0x114c1e080, 0x14014452dc0}, 0x14000a27900)
                /home/runner/work/coder/coder/coderd/httpmw/prometheus.go:89 +0x270
           net/http.HandlerFunc.ServeHTTP(0x114c2e598?, {0x114c1e080?, 0x14014452dc0?}, 0x117917b80?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/httpmw.HTTPRoute.func1({0x114c1e080, 0x14014452dc0}, 0x14000a277c0)
                /home/runner/work/coder/coder/coderd/httpmw/httproute.go:43 +0x144
           net/http.HandlerFunc.ServeHTTP(0x114c2e598?, {0x114c1e080?, 0x14014452dc0?}, 0x117917b80?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/rbac/rolestore.CustomRoleMW.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27540)
                /home/runner/work/coder/coder/coderd/rbac/rolestore/rolestore.go:23 +0x120
           net/http.HandlerFunc.ServeHTTP(0x14000b397c0?, {0x114c1e080?, 0x14014452dc0?}, 0x113d4deb0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd.singleSlashMW.func1({0x114c1e080, 0x14014452dc0}, 0x14000a27540)
                /home/runner/work/coder/coder/coderd/coderd.go:2188 +0x12c
           net/http.HandlerFunc.ServeHTTP(0x14000a272c0?, {0x114c1e080?, 0x14014452dc0?}, 0x14001243a40?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd.New.Logger.func29.1({0x114c1e080, 0x14014452dc0}, 0x14000a272c0)
                /home/runner/work/coder/coder/coderd/httpmw/loggermw/logger.go:106 +0x450
           net/http.HandlerFunc.ServeHTTP(0x1401944e000?, {0x114c1e080?, 0x14014452dc0?}, 0x117917b80?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd.New.ExtractRealIP.func28.1({0x114c1e080, 0x14014452dc0}, 0x14000a26f00)
                /home/runner/work/coder/coder/coderd/httpmw/realip.go:50 +0x128
           net/http.HandlerFunc.ServeHTTP(0x114811600?, {0x114c1e080?, 0x14014452dc0?}, 0x12?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/httpmw.AttachRequestID.func1({0x114c1e080, 0x14014452dc0}, 0x14000a26dc0)
                /home/runner/work/coder/coder/coderd/httpmw/requestid.go:38 +0x3c8
           net/http.HandlerFunc.ServeHTTP(0x0?, {0x114c1e080?, 0x14014452dc0?}, 0x0?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/tracing.Middleware.func1.1({0x114c1e080, 0x14014452dc0}, 0x14000a26c80)
                /home/runner/work/coder/coder/coderd/tracing/httpmw.go:71 +0x664
           net/http.HandlerFunc.ServeHTTP(0x14001d597b8?, {0x114c1e080?, 0x14014452dc0?}, 0x114b3f620?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/tracing.StatusWriterMiddleware.func1({0x114c1e510, 0x14015490780}, 0x14000a26c80)
                /home/runner/work/coder/coder/coderd/tracing/status_writer.go:39 +0x88
           net/http.HandlerFunc.ServeHTTP(0x14001d59828?, {0x114c1e510?, 0x14015490780?}, 0x104f0bae8?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd/httpmw.WithProfilingLabels.func1.1({0x114c2e598, 0x14011f0cc90})
                /home/runner/work/coder/coder/coderd/httpmw/pprof.go:27 +0xf8
           runtime/pprof.Do({0x114c2e598?, 0x14011f0cc60?}, {{0x14018a5bd80?, 0x104778438?, 0x1140d7dc0?}}, 0x14001d59968)
                /opt/hostedtoolcache/go/1.25.6/x64/src/runtime/pprof/runtime.go:51 +0x78
           github.com/coder/coder/v2/coderd/httpmw.WithProfilingLabels.func1({0x114c1e510, 0x14015490780}, 0x14000a26c80)
                /home/runner/work/coder/coder/coderd/httpmw/pprof.go:25 +0x1d4
           net/http.HandlerFunc.ServeHTTP(0x14001d59a18?, {0x114c1e510?, 0x14015490780?}, 0x11f67e628?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/coder/coder/v2/coderd.New.Recover.func27.1({0x114c1e510?, 0x14015490780?}, 0x14001d59ad8?)
                /home/runner/work/coder/coder/httpmw/recover.go:44 +0xa4
           net/http.HandlerFunc.ServeHTTP(0x114c2e5d0?, {0x114c1e510?, 0x14015490780?}, 0x1177ce140?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2322 +0x38
           github.com/go-chi/chi/v5.(*Mux).ServeHTTP(0x14000de1020, {0x114c1e510, 0x14015490780}, 0x14000a26500)
                /home/runner/go/pkg/mod/github.com/go-chi/chi/[email protected]/mux.go:90 +0x254
           net/http.serverHandler.ServeHTTP({0x114c0a690?}, {0x114c1e510?, 0x14015490780?}, 0x1?)
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:3340 +0xb0
           net/http.(*conn).serve(0x14011a77290, {0x114c2e598, 0x14011bfc1e0})
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:2109 +0x528
           created by net/http.(*Server).Serve in goroutine 468
                /opt/hostedtoolcache/go/1.25.6/x64/src/net/http/server.go:3493 +0x384

Expected Behavior

To be able to start a workspace proxy instance with the built in DERP server disabled.

Steps to Reproduce

Version: 2.30.1

coder version
Coder v2.30.1+16408b1 Tue Feb 10 17:11:03 UTC 2026
https://github.com/coder/coder/commit/16408b157bb14b4bc2aeee5904fdb586ab152862

Full build of Coder, supports the  server  subcommand.

Start a coderd instance with derp server disabled:

coder server \
  --http-address :0 \
  --access-url http://192.168.51.15:3000 \
  --derp-server-enable=false \
  --derp-config-url="https://controlplane.tailscale.com/derpmap/default"

Login to it and create a workspace proxy token:

coder login http://192.168.51.15:3000

coder wsproxy create --name jimbob --display-name jimbob --icon "/emojis/1f310.png"

Start the workspace proxy and observe it erroring out and exiting straight away:

CODER_PROXY_SESSION_TOKEN=5ae9c016-5e8d-4e53-b1c3-4cd229c858b2:XKQf9iuA6ZEqwNYQ6OgQTWaAYoPJa8LVd3btFicok4Lal2nLJhPbjtHBX3zOdbR4 coder wsproxy server --primary-access-url http://192.168.51.15:3000 --http-address=0.0.0.0:3001
Coder Workspace Proxy v2.30.1+16408b1 - Your Self-Hosted Remote Development Platform
Started HTTP listener at http://0.0.0.0:3001
╔═══════════════════════════╗
║     View the Web UI:      ║
║   http://127.0.0.1:3001   ║
╚═══════════════════════════╝
Encountered an error running "coder workspace-proxy server", see "coder workspace-proxy server --help" for more information
error: Trace=[create workspace proxy: register proxy: start loop: initial registration: register workspace proxy: ]
An internal server error occurred.

Look at your coderd instance and observe the stacktrace.

Environment

  • Host OS: Tested on Linux, MacOS
  • Coder version: 2.30.1

Additional Context

The issue occurs consistently

Metadata

Metadata

Assignees

Labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions