Skip to content

Pre-release. v0.1 is not out yet, so there is nothing to install and no public source to clone — the quickstart builds from a checkout.

Configuration

Every setting is configuration and every setting has an environment variable: Onbe:Section:Key becomes Onbe__Section__Key. Nothing is read from a file the server wrote, and nothing is inferred from the environment it happens to be running in.

Misconfiguration is a startup failure, not a warning, and the failure names every key that is wrong at once rather than one per restart. A startup error names the key and never repeats the value, because the value is sometimes a secret and a log line is not a safe place for one.

How a value is read:

  • An empty value is an unset value. Onbe__Admin__ApiKey= disables the admin API; it is not a key of length zero.
  • A list is comma-separated, and Onbe:RateLimit:TrustedProxies is the only one. Signing keys are numbered instead.
  • The command line overrides the environment. --Onbe:RateLimit:Burst=5 beats Onbe__RateLimit__Burst; that is for trying something out, not for a deployment.
Setting Required Default What it is
Onbe:Issuer yes This control plane’s own issuer URL, as it publishes it
Onbe:UpstreamIdp:Issuer one of The identity provider’s realm URL; discovery is derived from it
Onbe:UpstreamIdp:MetadataUrl one of The discovery document directly, for a provider shaped differently
Onbe:UpstreamIdp:Audience yes The audience a subject token must carry
Onbe:UpstreamIdp:SponsorCheck:UsersUrl yes Where to ask whether a user is still active
Onbe:UpstreamIdp:SponsorCheck:TokenUrl yes Where the control plane gets its own token to ask with
Onbe:UpstreamIdp:SponsorCheck:ClientId yes The client it asks as
Onbe:UpstreamIdp:SponsorCheck:CacheTtl no 30s How long a sponsor’s status is reused. Never longer than Tokens:DefaultTokenTtl

Exactly one of UpstreamIdp:Issuer and UpstreamIdp:MetadataUrl. Setting both is a startup failure rather than a quiet precedence rule, because the two disagreeing is exactly the situation somebody would otherwise debug for an afternoon.

The sponsor cache is bounded by the token lifetime for a reason: a disabled user’s tasks have to die within one token lifetime, so a cached “still active” may not outlive the token it would have been used to mint.

Setting Required Default What it is
Onbe:Database:Provider no postgres postgres, or sqlite for the embedded database
Onbe:Database:ConnectionString postgres A secret
Onbe:Database:MigrationConnectionString no the above Postgres only: a role that may change the schema. A secret
Onbe:Database:Path sqlite Where the embedded database file lives

A setting the chosen provider does not use is a startup failure, not a value silently ignored: a leftover connection string usually means somebody believes a different database is in use.

Setting Required Default What it is
Onbe:Signing:Keys:N:Path yes* Path to a PEM, typically a mounted secret. A secret
Onbe:Signing:Keys:N:Pem yes* The PEM inline. Exactly one of Path or Pem per key
Onbe:Signing:Keys:N:Kid no a thumbprint An explicit key id; omit for the RFC 7638 thumbprint
Onbe:Signing:ActiveKid no the only key Which key signs. Required once more than one is configured

* Outside the Development environment, at least one key is required and a missing one stops the server. In Development an ephemeral key is generated and logged loudly.

Every configured key is published in JWKS; only the active one signs. The indices need not run from zero — a rotation adds a number and later removes another, so gaps are normal.

Setting Required Default Bounds
Onbe:Tokens:DefaultTaskTtl no 30m Must not be shorter than the token TTL
Onbe:Tokens:DefaultTokenTtl no 5m Must not exceed the task TTL
Onbe:Tasks:SweepInterval no 1m 1 second to 1 day
Onbe:Tasks:SweepBatchSize no 20 Positive

These are what a registration that names no lifetime is given. A registration that names its own gets its own — max_task_ttl: PT6H runs six-hour tasks whatever the default says — and is held only by the Onbe:Agents:* bounds. A token is always cut to what remains of its task, and a task with under five seconds left is refused a token.

Setting Required Default What it is
Onbe:Agents:MinTaskTtl no PT1M Shortest max_task_ttl a registration may set
Onbe:Agents:MaxTaskTtl no P1D Longest max_task_ttl a registration may set
Onbe:Agents:MinTokenTtl no PT30S Shortest max_token_ttl a registration may set
Onbe:Agents:MaxTokenTtl no PT1H Longest max_token_ttl a registration may set

Each Min* must not exceed its Max*, and each Tokens:Default* must sit within them; this is where an operator holds the whole deployment to something shorter, not by lowering a default.

Durations here take either form. 00:05:00 and PT5M are both five minutes. A duration the loader cannot parse is a startup failure naming the key, and years and months are refused outright — P1M is not a length of time a token lifetime can be made of. Durations in an agent registration are ISO 8601 only, because that is what the API contract says.

Setting Required Default What it is
Onbe:Admin:ApiKey no Enables the admin API. At least 32 characters. A secret
Onbe:Audit:Sink:Url no Where to copy audit records
Onbe:Audit:Sink:BearerToken no Sent to the sink. Requires an HTTPS sink. A secret
Onbe:Audit:DrainInterval no 5s 1 second to 1 hour
Onbe:Audit:DrainBatchSize no 100 Positive

Without Admin:ApiKey the admin API is disabled entirely and every /admin request answers 503 — off, rather than open. A sink URL may not carry credentials in its user info, and a bearer token for a plaintext sink is refused at startup rather than sent in the clear every drain tick.

Setting Required Default Bounds
Onbe:Audit:Chains no 16 1 to 256
Onbe:Audit:Aggregation:Enabled no true true or false
Onbe:Audit:Aggregation:Window no PT1M PT1S to PT15M

The ledger is that many hash chains, each with its own lock, and a record is placed on one by the human it names; a denial that names nobody is written once per reason per window and the rest counted into one summary record, so turning aggregation off is logged as a warning.

Setting Required Default What it is
Onbe:RateLimit:Enabled no true A token bucket per source, per instance
Onbe:RateLimit:PermitsPerMinute no 600 Sustained requests from one source
Onbe:RateLimit:Burst no 120 Most permits the bucket holds. Never below one second of PermitsPerMinute
Onbe:RateLimit:TrustedProxies no Comma-separated CIDR networks whose X-Forwarded-For is believed

A refused request is 429 with Retry-After and slow_down; /healthz and /readyz are never limited, and 0.0.0.0/0 is refused as a trusted proxy because it would let any caller pick its own bucket.

The database connection string, the migration connection string, the signing key (Pem), the admin API key and the sink’s bearer token. None of them is ever logged, returned in an error response, or committed: the options types that hold them print a fixed placeholder instead of their contents, so they cannot leak through a log line that formatted an object. The same applies at runtime to task tokens, task grants and subject tokens.

Onbe.Server doctor reads this configuration exactly as the server would and reports what is wrong before anything depends on it — see the command line.

Variable What it does
ASPNETCORE_HTTP_PORTS The port the server listens on. The container image sets 5100
ASPNETCORE_ENVIRONMENT Development is the one host that generates an ephemeral signing key when none is configured
ONBE_ADMIN_KEY Read by agent apply, not by the server
OnbePre-release. v0.1 is not out yet.

© 2026 Onbe