Configuration¶
Stegflow is configured through environment variables. Every setting has a safe default, so a container runs with no configuration at all.
All variables use the STEGFLOW_ prefix. Nested settings are separated by a
double underscore (__), and array entries use a numeric index. Names are
case-insensitive; they are shown here in mixed case, with acronyms in uppercase,
which reads more easily than all-uppercase and matches the
configuration file keys.
Booleans are true / false, durations use the hh:mm:ss format (for example
00:00:30), and provider names are case-insensitive.
Hosting and ports
The listening port, HTTPS and related host settings are handled by the
ASP.NET runtime, not by Stegflow. They use the standard ASPNETCORE_
prefix, for example ASPNETCORE_HTTP_PORTS=8080. The container listens on
port 8080 (HTTP) by default.
Reverse proxy¶
Behind a TLS-terminating reverse proxy, Stegflow honours the X-Forwarded-For,
X-Forwarded-Proto and X-Forwarded-Host headers, so it builds absolute URLs
(notably the OIDC redirect_uri) with the public scheme and host. Pin the proxy
to stop anyone else from spoofing those headers.
STEGFLOW_ReverseProxy__KnownProxies__0,__1, ...- IP addresses of the trusted proxies. Default: none.
STEGFLOW_ReverseProxy__KnownNetworks__0,__1, ...- Networks (CIDR) the trusted proxies sit in. Default: none.
Empty means trust anyone
When both lists are empty, forwarded headers are accepted from any source. That assumes only the reverse proxy can reach Stegflow's port. If the port is reachable more widely, set at least one of these; a malformed entry fails at startup rather than silently trusting the wrong source.
Engine¶
STEGFLOW_Engine__StrictAwsMode- Enforce strict AWS States Language compatibility. Default:
false. STEGFLOW_Engine__AdminEmails__0,__1, ...- Email addresses of the global administrators. Default: none.
STEGFLOW_Engine__DefaultTimeZone- Time zone used to display dates when a user has no explicit or provider value. Default:
UTC. STEGFLOW_Engine__MaxTenantsAllowed- Per-user quota: how many tenants a user may own. A per-user override set by a global administrator takes precedence over this global default.
0means the user may create none. Default:2. STEGFLOW_Engine__AllowTenantCreationForAllIdentities- Who may create tenants at all.
true: any authenticated user.false: only global administrators (STEGFLOW_Engine__AdminEmails). Default:true. STEGFLOW_Engine__AllowPrivateNetworkHttpTargets- Allow HTTP tasks to reach private, loopback and link-local addresses. Off by default to prevent SSRF. Default:
false. STEGFLOW_Engine__ExecutionRetentionDays- Days a terminated execution is kept before the cleanup worker purges it and its events.
0or less disables cleanup. Default:90.
How the two tenant-creation settings combine
Creating a tenant passes two independent checks. First permission:
STEGFLOW_Engine__AllowTenantCreationForAllIdentities decides who may attempt it
(everyone, or only global administrators). Second quota: the user's
effective STEGFLOW_Engine__MaxTenantsAllowed (their per-user override,
otherwise the global default) must be above the number of tenants they
already own. The quota applies to everyone, administrators included, so a
global default of 0 blocks creation for anyone without a per-user
override, even when permission is granted.
Database¶
Set both variables below to persist data. A fully durable deployment also needs Valkey (see below).
STEGFLOW_Engine__Database__Provider- Storage provider. One of
SqliteorPostgreSql. Default: none (in-memory). STEGFLOW_Engine__Database__ConnectionString- Connection string for the selected provider. For SQLite, point it at a file on a mounted, writable volume (for example
Data Source=/data/stegflow.db). Default: none.
Valkey¶
STEGFLOW_Engine__Valkey__ConnectionString- Valkey/Redis connection string. It backs the async job dispatcher and the activity task queue, and stores the Data Protection key ring. When empty, both queues stay in memory and are lost on restart. Default: (empty).
What Valkey holds, and what it does not
Valkey carries the queues (async jobs, activity tasks) and the Data Protection key ring, which protects auth cookies and the credential secrets stored in the database.
Authorization cache¶
STEGFLOW_Engine__AuthorizationCache__Enabled- Enable the authorization decision cache. Default:
true. STEGFLOW_Engine__AuthorizationCache__TTL- How long a decision is trusted. Keep it short. Default:
00:00:30. STEGFLOW_Engine__AuthorizationCache__MaxEntries- Hard cap on cached decisions. Least-recently-used entries are evicted past this limit. Default:
50000.
Metrics (Prometheus)¶
Controls access to the /metrics endpoint.
STEGFLOW_Metrics__BearerToken- Token a scraper must present as
Authorization: Bearer <token>. Default: (empty). STEGFLOW_Metrics__AllowedNetworks__0,__1, ...- Source networks (CIDR) allowed to scrape without a token. Default: none.
STEGFLOW_Metrics__AllowAnonymous- Serve
/metricswith no token and no source check. Default:false.
/metrics is closed by default
With the defaults, /metrics returns 401. To enable scraping, set a
BearerToken, or list trusted AllowedNetworks, or set AllowAnonymous to
true on a network you already isolate.
OpenTelemetry¶
The /metrics Prometheus endpoint always exposes the meters. Pushing to an OTLP
collector is opt-in, per signal, and needs an endpoint.
STEGFLOW_OpenTelemetry__ServiceName- Service name reported on the OpenTelemetry resource. Default:
Stegflow. STEGFLOW_OpenTelemetry__OTLP__Endpoint- OTLP collector endpoint, for example
http://collector:4317. Default: (empty). STEGFLOW_OpenTelemetry__OTLP__Protocol- OTLP transport. One of
GrpcorHttpProtobuf. Default: the exporter's own default (Grpc). STEGFLOW_OpenTelemetry__OTLP__Headers__<NAME>- Headers sent with each OTLP export, for example an authentication token. Default: none.
STEGFLOW_OpenTelemetry__OTLP__Traces- Export traces for ASP.NET Core, outgoing HTTP, Entity Framework Core and the engine's own spans. Default:
false. STEGFLOW_OpenTelemetry__OTLP__Metrics- Also push metrics to the collector, on top of the Prometheus endpoint. Default:
false. STEGFLOW_OpenTelemetry__OTLP__Logs- Export logs to the collector. Default:
false.
Standard OTEL_ variables
Leave OTLP__Endpoint, __Protocol and __Headers empty and the exporter
falls back to the SDK defaults, which read the standard
OTEL_EXPORTER_OTLP_* environment variables. Handy when a collector sidecar
or platform already sets them. You still need to switch on the signals you
want (__Traces, __Metrics, __Logs).
Single-identity auth¶
When no OIDC authority is configured, Stegflow runs in single-identity mode:
every request is authenticated as one fixed identity (admin@stegflow.local by
default). If no administrator is configured either, that identity is promoted to
global administrator on startup, with a loud warning in the logs, so a fresh
container is usable with no setup. Setting OIDC or
STEGFLOW_Engine__AdminEmails turns the auto-promotion off. This mode has no
real authentication and must never be exposed to untrusted networks.
STEGFLOW_SingleIdentityAuth__Email- Email that identifies the signed-in user. Default:
admin@stegflow.local. STEGFLOW_SingleIdentityAuth__Name- Display name of the signed-in user. Default:
Default Administrator. STEGFLOW_SingleIdentityAuth__Sub- Subject identifier of the signed-in user. Falls back to the email when unset. Default:
admin@stegflow.local.
Testing access control. Set a real administrator with
STEGFLOW_Engine__AdminEmails__0 so the single-user identity is not
auto-promoted, then point STEGFLOW_SingleIdentityAuth__Email at a non-admin user.
Change that email to sign in as different users and check what each one is
allowed to do, without setting up an identity provider.
OpenID Connect (OIDC)¶
Single sign-on against an external identity provider. The client authenticates with a shared secret, or with a signed assertion when a certificate is set.
STEGFLOW_OIDC__Authority- Issuer/authority URL of the provider. Default: (empty).
STEGFLOW_OIDC__ClientId- Client identifier. Default: (empty).
STEGFLOW_OIDC__ClientSecret- Client secret. Leave empty when using a certificate. Default: (empty).
STEGFLOW_OIDC__RequireHttpsMetadata- Require the discovery and JWKS endpoints over HTTPS. Set to
falseonly for local development. Default:true. STEGFLOW_OIDC__RequireEmailVerified- Refuse sign-in when the provider does not report the email as verified. Since identities are keyed by email, turning this off lets a provider that allows unverified addresses impersonate another user. Default:
true. STEGFLOW_OIDC__Certificate__Path- Path to a PFX/PKCS#12 or PEM file with the certificate and private key, for
private_key_jwt. Default: (empty). STEGFLOW_OIDC__Certificate__Password- Password protecting the PFX file. Ignored for PEM. Default: (empty).
Claim mapping¶
Maps the claims returned by the identity provider onto user attributes.
STEGFLOW_OIDC__Claims__Name- Claim holding the display name. Default:
name. STEGFLOW_OIDC__Claims__Email- Claim holding the email address. Default:
email. STEGFLOW_OIDC__Claims__EmailVerified- Claim telling whether the provider verified the email address. Default:
email_verified. STEGFLOW_OIDC__Claims__TimeZone- Claim holding the time zone. Default:
timezone. STEGFLOW_OIDC__Claims__AvatarUrl- Claim holding the avatar URL. Default:
picture. STEGFLOW_OIDC__Claims__DebugClaims- Log the received claims to help diagnose mapping issues. Default:
false.
Example¶
PostgreSQL, Valkey for durable async tasks, OIDC sign-on, and one global admin:
docker run -p 8080:8080 \
-e STEGFLOW_Engine__AdminEmails__0="admin@example.com" \
-e STEGFLOW_Engine__Database__Provider=PostgreSql \
-e STEGFLOW_Engine__Database__ConnectionString="Host=db;Database=sf;Username=sf;Password=secret" \
-e STEGFLOW_Engine__Valkey__ConnectionString="valkey:6379" \
-e STEGFLOW_OIDC__Authority="https://id.example.com/realms/stegflow" \
-e STEGFLOW_OIDC__ClientId="stegflow" \
-e STEGFLOW_OIDC__ClientSecret="..." \
stegflow/stegflow:beta
Configuration file (JSON)¶
Instead of environment variables, the same settings can be supplied as a JSON
file mounted at /app/appsettings.Production.json. Use the section names (the
"setting" column) as nested keys. An environment variable always overrides the
same key from the file.
{
"Engine": {
"AdminEmails": [ "admin@example.com" ],
"Database": {
"Provider": "PostgreSql",
"ConnectionString": "Host=db;Database=sf;Username=sf;Password=secret"
},
"Valkey": { "ConnectionString": "valkey:6379" }
},
"OIDC": {
"Authority": "https://id.example.com/realms/stegflow",
"ClientId": "stegflow",
"ClientSecret": "..."
}
}