Skip to content

Commit d16d19d

Browse files
committed
fix: disable relay if built-in DERP is disabled
1 parent e45d511 commit d16d19d

File tree

4 files changed

+69
-50
lines changed

4 files changed

+69
-50
lines changed

coderd/coderd.go

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ func New(options *Options) *API {
284284
if options.PrometheusRegistry == nil {
285285
options.PrometheusRegistry = prometheus.NewRegistry()
286286
}
287-
if options.DERPServer == nil {
287+
if options.DERPServer == nil && options.DeploymentValues.DERP.Server.Enable {
288288
options.DERPServer = derp.NewServer(key.NewNode(), tailnet.Logger(options.Logger.Named("derp")))
289289
}
290290
if options.DERPMapUpdateFrequency == 0 {
@@ -567,8 +567,6 @@ func New(options *Options) *API {
567567
// replicas or instances of this middleware.
568568
apiRateLimiter := httpmw.RateLimit(options.APIRateLimit, time.Minute)
569569

570-
derpHandler := derphttp.Handler(api.DERPServer)
571-
derpHandler, api.derpCloseFunc = tailnet.WithWebsocketSupport(api.DERPServer, derpHandler)
572570
// Register DERP on expvar HTTP handler, which we serve below in the router, c.f. expvar.Handler()
573571
// These are the metrics the DERP server exposes.
574572
// TODO: export via prometheus
@@ -577,7 +575,9 @@ func New(options *Options) *API {
577575
// register multiple times. In production there is only one Coderd and one DERP server per
578576
// process, but in testing, we create multiple of both, so the Once protects us from
579577
// panicking.
580-
expvar.Publish("derp", api.DERPServer.ExpVar())
578+
if options.DERPServer != nil {
579+
expvar.Publish("derp", api.DERPServer.ExpVar())
580+
}
581581
})
582582
cors := httpmw.Cors(options.DeploymentValues.Dangerous.AllowAllCors.Value())
583583
prometheusMW := httpmw.Prometheus(options.PrometheusRegistry)
@@ -627,13 +627,18 @@ func New(options *Options) *API {
627627
api.workspaceAppServer.Attach(r)
628628
})
629629

630-
r.Route("/derp", func(r chi.Router) {
631-
r.Get("/", derpHandler.ServeHTTP)
632-
// This is used when UDP is blocked, and latency must be checked via HTTP(s).
633-
r.Get("/latency-check", func(w http.ResponseWriter, r *http.Request) {
634-
w.WriteHeader(http.StatusOK)
630+
if options.DERPServer != nil {
631+
derpHandler := derphttp.Handler(api.DERPServer)
632+
derpHandler, api.derpCloseFunc = tailnet.WithWebsocketSupport(api.DERPServer, derpHandler)
633+
634+
r.Route("/derp", func(r chi.Router) {
635+
r.Get("/", derpHandler.ServeHTTP)
636+
// This is used when UDP is blocked, and latency must be checked via HTTP(s).
637+
r.Get("/latency-check", func(w http.ResponseWriter, r *http.Request) {
638+
w.WriteHeader(http.StatusOK)
639+
})
635640
})
636-
})
641+
}
637642

638643
// Register callback handlers for each OAuth2 provider.
639644
// We must support gitauth and externalauth for backwards compatibility.
@@ -1056,9 +1061,11 @@ func New(options *Options) *API {
10561061
r.Use(httpmw.ExtractUserParam(options.Database))
10571062
r.Get("/debug-link", api.userDebugOIDC)
10581063
})
1059-
r.Route("/derp", func(r chi.Router) {
1060-
r.Get("/traffic", options.DERPServer.ServeDebugTraffic)
1061-
})
1064+
if options.DERPServer != nil {
1065+
r.Route("/derp", func(r chi.Router) {
1066+
r.Get("/traffic", options.DERPServer.ServeDebugTraffic)
1067+
})
1068+
}
10621069
r.Method("GET", "/expvar", expvar.Handler()) // contains DERP metrics as well as cmdline and memstats
10631070
})
10641071
})

enterprise/cli/server.go

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,42 @@ func (r *RootCmd) Server(_ func()) *clibase.Cmd {
3737
}
3838
}
3939

40-
options.DERPServer = derp.NewServer(key.NewNode(), tailnet.Logger(options.Logger.Named("derp")))
41-
42-
var meshKey string
43-
err := options.Database.InTx(func(tx database.Store) error {
44-
// This will block until the lock is acquired, and will be
45-
// automatically released when the transaction ends.
46-
err := tx.AcquireLock(ctx, database.LockIDEnterpriseDeploymentSetup)
47-
if err != nil {
48-
return xerrors.Errorf("acquire lock: %w", err)
49-
}
40+
if options.DeploymentValues.DERP.Server.Enable {
41+
options.DERPServer = derp.NewServer(key.NewNode(), tailnet.Logger(options.Logger.Named("derp")))
42+
var meshKey string
43+
err := options.Database.InTx(func(tx database.Store) error {
44+
// This will block until the lock is acquired, and will be
45+
// automatically released when the transaction ends.
46+
err := tx.AcquireLock(ctx, database.LockIDEnterpriseDeploymentSetup)
47+
if err != nil {
48+
return xerrors.Errorf("acquire lock: %w", err)
49+
}
5050

51-
meshKey, err = tx.GetDERPMeshKey(ctx)
52-
if err == nil {
51+
meshKey, err = tx.GetDERPMeshKey(ctx)
52+
if err == nil {
53+
return nil
54+
}
55+
if !errors.Is(err, sql.ErrNoRows) {
56+
return xerrors.Errorf("get DERP mesh key: %w", err)
57+
}
58+
meshKey, err = cryptorand.String(32)
59+
if err != nil {
60+
return xerrors.Errorf("generate DERP mesh key: %w", err)
61+
}
62+
err = tx.InsertDERPMeshKey(ctx, meshKey)
63+
if err != nil {
64+
return xerrors.Errorf("insert DERP mesh key: %w", err)
65+
}
5366
return nil
54-
}
55-
if !errors.Is(err, sql.ErrNoRows) {
56-
return xerrors.Errorf("get DERP mesh key: %w", err)
57-
}
58-
meshKey, err = cryptorand.String(32)
67+
}, nil)
5968
if err != nil {
60-
return xerrors.Errorf("generate DERP mesh key: %w", err)
69+
return nil, nil, err
6170
}
62-
err = tx.InsertDERPMeshKey(ctx, meshKey)
63-
if err != nil {
64-
return xerrors.Errorf("insert DERP mesh key: %w", err)
71+
if meshKey == "" {
72+
return nil, nil, xerrors.New("mesh key is empty")
6573
}
66-
return nil
67-
}, nil)
68-
if err != nil {
69-
return nil, nil, err
70-
}
71-
if meshKey == "" {
72-
return nil, nil, xerrors.New("mesh key is empty")
74+
options.DERPServer.SetMeshKey(meshKey)
7375
}
74-
options.DERPServer.SetMeshKey(meshKey)
7576

7677
options.Auditor = audit.NewAuditor(
7778
options.Database,

enterprise/coderd/coderd.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
418418
if err != nil {
419419
return nil, xerrors.Errorf("create DERP mesh TLS config: %w", err)
420420
}
421+
// We always want to run the replica manager even if we don't have DERP
422+
// enabled, since it's used to detect other coder servers for licensing.
421423
api.replicaManager, err = replicasync.New(ctx, options.Logger, options.Database, options.Pubsub, &replicasync.Options{
422424
ID: api.AGPL.ID,
423425
RelayAddress: options.DERPServerRelayAddress,
@@ -428,7 +430,9 @@ func New(ctx context.Context, options *Options) (_ *API, err error) {
428430
if err != nil {
429431
return nil, xerrors.Errorf("initialize replica: %w", err)
430432
}
431-
api.derpMesh = derpmesh.New(options.Logger.Named("derpmesh"), api.DERPServer, meshTLSConfig)
433+
if api.DERPServer != nil {
434+
api.derpMesh = derpmesh.New(options.Logger.Named("derpmesh"), api.DERPServer, meshTLSConfig)
435+
}
432436

433437
// Moon feature init. Proxyhealh is a go routine to periodically check
434438
// the health of all workspace proxies.
@@ -666,11 +670,18 @@ func (api *API) updateEntitlements(ctx context.Context) error {
666670
}
667671

668672
api.replicaManager.SetCallback(func() {
669-
addresses := make([]string, 0)
670-
for _, replica := range api.replicaManager.Regional() {
671-
addresses = append(addresses, replica.RelayAddress)
673+
// Only update DERP mesh if the built-in server is enabled.
674+
if api.Options.DeploymentValues.DERP.Server.Enable {
675+
addresses := make([]string, 0)
676+
for _, replica := range api.replicaManager.Regional() {
677+
// Don't add replicas with an empty relay address.
678+
if replica.RelayAddress == "" {
679+
continue
680+
}
681+
addresses = append(addresses, replica.RelayAddress)
682+
}
683+
api.derpMesh.SetAddresses(addresses, false)
672684
}
673-
api.derpMesh.SetAddresses(addresses, false)
674685
_ = api.updateEntitlements(ctx)
675686
})
676687
} else {

enterprise/replicasync/replicasync.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"golang.org/x/xerrors"
1818

1919
"cdr.dev/slog"
20-
2120
"github.com/coder/coder/v2/buildinfo"
2221
"github.com/coder/coder/v2/cli/cliutil"
2322
"github.com/coder/coder/v2/coderd/database"
@@ -38,8 +37,9 @@ type Options struct {
3837
TLSConfig *tls.Config
3938
}
4039

41-
// New registers the replica with the database and periodically updates to ensure
42-
// it's healthy. It contacts all other alive replicas to ensure they are reachable.
40+
// New registers the replica with the database and periodically updates to
41+
// ensure it's healthy. It contacts all other alive replicas to ensure they are
42+
// reachable.
4343
func New(ctx context.Context, logger slog.Logger, db database.Store, ps pubsub.Pubsub, options *Options) (*Manager, error) {
4444
if options == nil {
4545
options = &Options{}

0 commit comments

Comments
 (0)