@@ -96,6 +96,49 @@ type Options struct {
9696 // OIDCIssuer optionally enables full OIDC enrollment.
9797 OIDCIssuer string
9898 AllowedAudiences []string
99+ // OIDCClientID is the OAuth client id advertised via /info.
100+ OIDCClientID string
101+
102+ // ControlPlane and Router forward operator tunables to the embedded
103+ // components; zero values keep each component's defaults.
104+ ControlPlane ControlPlaneTunables
105+ Router RouterTunables
106+ }
107+
108+ // ControlPlaneTunables are the embedded control plane's operator knobs.
109+ type ControlPlaneTunables struct {
110+ // LeaseDuration bounds how long a router lease stays valid.
111+ LeaseDuration time.Duration
112+ // KeyRotationInterval is how often the biscuit signing key rotates.
113+ KeyRotationInterval time.Duration
114+ // KeyGracePeriod keeps rotated-out keys valid for verification.
115+ KeyGracePeriod time.Duration
116+ // BiscuitTTL is the lifespan minted into issued biscuits.
117+ BiscuitTTL time.Duration
118+ // ManualEnrollment queues bootstrap enrollments for admin approval
119+ // instead of auto-approving them.
120+ ManualEnrollment bool
121+ }
122+
123+ // RouterTunables are the embedded router's operator knobs.
124+ type RouterTunables struct {
125+ // KeysSyncInterval is how often biscuit public keys are refreshed.
126+ KeysSyncInterval time.Duration
127+ // LeaseRenewInterval is how often the router renews its lease.
128+ LeaseRenewInterval time.Duration
129+ // LowWaterMark / HighWaterMark bound the connection manager.
130+ LowWaterMark int
131+ HighWaterMark int
132+ // ConnsPerSourceIP scales libp2p's per-source-IP budgets; defaults to
133+ // the connection manager high watermark (proxied deployments share
134+ // source IPs, so the global cap should be what binds).
135+ ConnsPerSourceIP int
136+ // DHTProviderAddrTTL / DHTMaxRecordAge tune DHT record lifetimes.
137+ DHTProviderAddrTTL time.Duration
138+ DHTMaxRecordAge time.Duration
139+ // DisallowLoopback stops advertising loopback addresses (useful on
140+ // public deployments; the default keeps local development working).
141+ DisallowLoopback bool
99142}
100143
101144// Default fills unset options with development-friendly values.
@@ -117,6 +160,12 @@ func (o *Options) Default() {
117160 if len (o .AllowedAudiences ) == 0 {
118161 o .AllowedAudiences = []string {api .DefaultAudience }
119162 }
163+ if o .Router .HighWaterMark == 0 {
164+ o .Router .HighWaterMark = router .DefaultHighWaterMark
165+ }
166+ if o .Router .ConnsPerSourceIP == 0 {
167+ o .Router .ConnsPerSourceIP = o .Router .HighWaterMark
168+ }
120169}
121170
122171// Validate rejects option combinations Start could not honor.
@@ -191,10 +240,15 @@ func (s *Server) Start(ctx context.Context) error {
191240 DriverName : s .opts .DBDriver ,
192241 DataSourceName : s .opts .DBDSN ,
193242 OIDCIssuer : s .opts .OIDCIssuer ,
243+ OIDCClientID : s .opts .OIDCClientID ,
194244 AllowedAudiences : s .opts .AllowedAudiences ,
245+ LeaseDuration : s .opts .ControlPlane .LeaseDuration ,
246+ KeyRotationInterval : s .opts .ControlPlane .KeyRotationInterval ,
247+ KeyGracePeriod : s .opts .ControlPlane .KeyGracePeriod ,
248+ BiscuitTTL : s .opts .ControlPlane .BiscuitTTL ,
195249 BiscuitTimeout : 10 * time .Second ,
196250 AdminToken : s .adminToken ,
197- AutoApproveEnrollment : true ,
251+ AutoApproveEnrollment : ! s . opts . ControlPlane . ManualEnrollment ,
198252 }, store )
199253 if err != nil {
200254 return fmt .Errorf ("failed to create control plane: %w" , err )
@@ -260,18 +314,23 @@ func (s *Server) Start(ctx context.Context) error {
260314 }
261315
262316 rtr , err := router .NewRouter (ctx , router.Options {
263- ControlPlaneURL : "http://" + cp .Addr (),
264- ListenAddrs : append ([]string {wsAddr }, s .opts .P2PListen ... ),
265- ExternalAddrs : externalAddrs ,
266- AllowLoopback : true ,
267- KeysDBPath : filepath .Join (s .opts .DataDir , routerKeyFile ),
268- BootstrapToken : routerToken ,
317+ ControlPlaneURL : "http://" + cp .Addr (),
318+ ListenAddrs : append ([]string {wsAddr }, s .opts .P2PListen ... ),
319+ ExternalAddrs : externalAddrs ,
320+ AllowLoopback : ! s .opts .Router .DisallowLoopback ,
321+ KeysDBPath : filepath .Join (s .opts .DataDir , routerKeyFile ),
322+ BootstrapToken : routerToken ,
323+ KeysSyncInterval : s .opts .Router .KeysSyncInterval ,
324+ LeaseRenewInterval : s .opts .Router .LeaseRenewInterval ,
325+ LowWaterMark : s .opts .Router .LowWaterMark ,
326+ HighWaterMark : s .opts .Router .HighWaterMark ,
327+ DHTProviderAddrTTL : s .opts .Router .DHTProviderAddrTTL ,
328+ DHTMaxRecordAge : s .opts .Router .DHTMaxRecordAge ,
269329 // Single-port deployments typically sit behind a TLS-terminating
270330 // proxy (Cloud Run, L7 LBs) or NAT where every peer shares a few
271331 // source IPs; libp2p's default 8-conns-per-IP cap would throttle
272- // the whole listener. Matches the conn manager's high watermark so
273- // the global cap, not the per-IP one, is what binds.
274- ConnsPerSourceIP : router .DefaultHighWaterMark ,
332+ // the whole listener.
333+ ConnsPerSourceIP : s .opts .Router .ConnsPerSourceIP ,
275334 HTTPFallbackHandler : mux ,
276335 })
277336 if err != nil {
0 commit comments