Environment Variables for Enterprise SSO
The env vars are only applicable to the Ory Polis service. If you are using the npm library then look for the options below when initializing the library.
General configuration
HOSTNAME
If you need to bind to a specific hostname, you can define HOSTNAME environment variable. For example, if you are planning to
use a Docker health check like wget -q --spider http://localhost:{PORT}/api/health || exit 1 set HOSTNAME=0.0.0.0 to listen to
localhost.
HOST_URL
The hostname used to build the default EXTERNAL_URL when EXTERNAL_URL is not set. It does not change the
address Ory Polis listens on; use HOSTNAME for that.
Default: localhost
PORT
The port to bind to. Default: 5225
EXTERNAL_URL
The public URL to reach this service. This is used internally to construct the callback url at which the SAML/OIDC IdP sends back the authorization response.
Default: http://{HOST_URL}:{PORT}
NPM library option: externalUrl
ACS_URL
The custom ACS URL (if used) to let Ory Polis know which ACS URL to send to in the SAML Request to the IdP. Custom ACS URL can also be defined per SAML connection.
Available from version 1.40.1.
NPM library option: acsUrl
ACS_URL_HOST
The default hostname used for per-connection ACS URLs (acsUrlId). When set, SAML connections that use acsUrlId don't need to
include acsUrlHost in the request body — this value is used instead. On the SAML response path, this value is used for the
connection lookup instead of the HTTP Host header, which avoids mismatches when a reverse proxy rewrites the header.
Because responses are looked up under this value, a connection cannot be created under a different hostname: when this is set, an
acsUrlHost in the request body must either be omitted or match it, and any other value is rejected with a 400.
Self-hosted deployments that use acsUrlId should set this to the public hostname of the Ory Polis instance, for example
sso.example.com.
Do not change this value after connections have been created with it. The hostname is stored on each connection and used to look up the connection during SAML response processing. Changing it causes SAML responses for existing connections to fail because the stored host no longer matches.
NPM library option: acsUrlHost
API_KEYS
A comma-separated list of API keys that will be validated when serving the API requests (/api/v1/).
For example API_KEYS=key1,key2,key3
The API requests will then need to specify an Authorization header which contains one of the API keys above in this format:
Api-Key key1
JACKSON_API_KEYS is still supported but is deprecated, please switch to API_KEYS when you can.
SAML_AUDIENCE
The value of this setting (same as SP EntityID of Ory Polis) allows the Ory Polis instance to verify that it is the intended recipient of a SAML response. The same value is also set in the SAML App created on the IdP end by your customers. Once set do not change this value unless you get your customers to reconfigure their SAML App again. It is case-sensitive. This does not have to be a real URL.
Default: https://saml.boxyhq.com
NPM library option: samlAudience
samlPath
This is only applicable to the Ory Polis npm library.
The ACS path at which the saml response is sent back from the SAML IdP. Set this when using the npm package.
NPM library option: samlPath
For example: /api/oauth/saml
oidcPath
This is only applicable to the Ory Polis npm library.
The redirect_uri at which the Authorization response is sent back from the OpenID Connect IdP. Set this when using the npm
package.
NPM library option: oidcPath
For example: /api/oauth/oidc
idpDiscoveryPath
This is only applicable to the Ory Polis npm library. The Ory Polis service always uses /idp/select.
This is the path for showing the IdP Selection screen in case there are multiple SSO Connections for the same tenant and
product. This path is also used to show the App Selection screen in the case of IdP-initiated SAML login (Different apps using
the same SAML IdP). Set this when using the npm package.
NPM library option: idpDiscoveryPath
For example: /idp/select - You can find an implementation of IdP/App Selection
here.
CLIENT_SECRET_VERIFIER
When tenant and product are used for the SAML flow (and PKCE is not being used) then we use dummy as placeholders for
client_id and client_secret. This is not a security issue because SAML is tenanted and hence your Identity Provider will block
access to anyone trying to log into your SAML tenant. However for additional security you should set CLIENT_SECRET_VERIFIER to a
random secret and use that value as the client_secret during the OAuth 2.0 flow.
Default: dummy
NPM library option: clientSecretVerifier
IDP_ENABLED
Set to true to allow IdP-initiated login for SAML at the deployment level. SP-initiated login is the only recommended flow, but
you might have to support IdP-initiated login at times.
IDP_ENABLED is the deployment-wide switch and works together with the per-connection
idpInitiatedLoginEnabled setting:
- A connection that does not set
idpInitiatedLoginEnabledfollowsIDP_ENABLED. WithIDP_ENABLED=true, IdP-initiated login is allowed for it; withIDP_ENABLED=false, it is not. - Setting
idpInitiatedLoginEnabledon a connection overrides the switch:truealways allows IdP-initiated login for that connection,falsealways blocks it.
Default: false
NPM library option: idpEnabled
IdP-initiated login is inherently open to login CSRF: anyone who can reach the Assertion Consumer Service can start a login for an account they control and try to complete it in another person's browser. Keep it off unless a customer requires it, enable it only on the connections that need it, and make sure the relying application does not treat the first authenticated session after an IdP-initiated login as proof of a deliberate sign-in for security-sensitive actions.
PUBLIC_KEY
This is the public key of the private key used to sign the SAML requests. Ory Polis expects the public key to be base64 encoded.
NPM library option: certs.publicKey
PRIVATE_KEY
This is the private key used to sign the SAML requests. Ory Polis expects the private key to be base64 encoded.
NPM library option: certs.privateKey
To generate a private key and public key pair you can use the following command:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out public.crt -sha256 -days 365 -nodes
# Convert the public key to base64
cat public.crt | base64
# Convert the private key to base64
cat key.pem | base64
FLATTEN_RAW_CLAIMS
Set this config if you want to flatten all the raw claims into the profile instead of grouping them into profile.raw, this is needed for some OIDC providers that do no support nested objects
The claims Ory Polis asserts itself are reserved and are never taken from the upstream provider: id, sub, nonce,
requested, the registered JWT claims iss, aud, exp, iat, nbf and jti, and the token hash claims at_hash, c_hash
and s_hash. A raw claim under one of those names is dropped while flattening, so it reaches neither the ID token nor the
/userinfo response - the provider must not be able to rewrite the nonce that binds an ID token to the authorization request, the
request context, or the validity of a token Ory Polis signed. Every other raw claim is flattened as before.
Note that an OIDC provider normally sends iss, aud, exp, iat, sub and the nonce in its own ID token, so those upstream
values are no longer returned from /userinfo when this config is set.
Default: false
NPM library option: flattenRawClaims
JSON_ERROR_PAGE
Set this to true to send users who hit an error in the SSO, identity federation or single logout flows to /api/error, which
returns the error as JSON, instead of the /error page. Use this when no browser user sees the error page, for example in a
headless integration.
Default: false
NPM library option: jsonErrorPage
Outbound request restrictions
Ory Polis fetches SAML metadata URLs and OIDC discovery, token, userinfo and JWKS endpoints from the internet. To stop these fetches from reaching services on its own network, it only allows HTTPS URLs on public addresses by default.
POLIS_ALLOW_PRIVATE_IP_OUTBOUND
Set this to true if your identity providers run on an internal network. Ory Polis then also allows private IPv4 addresses
(RFC 1918) and IPv6 unique local addresses. HTTPS is still required, and loopback, link-local (including cloud metadata
endpoints), carrier-grade NAT and reserved addresses stay blocked.
Default: false
NPM library option: outbound.allowPrivateIp
POLIS_ALLOW_LOCALHOST_OUTBOUND
Set this to true to allow these fetches to localhost, over HTTP or HTTPS. This is meant for local development and automated
tests with an identity provider running on the same machine. Do not set it in production: anyone who can create a connection, for
example through a setup link, could make Ory Polis send requests to services on its own host.
This is always allowed when NODE_ENV is development.
Default: false
NPM library option: outbound.allowLocalhost. The library does not look at NODE_ENV, so set the option yourself in development.
POLIS_DISABLE_INTERNAL_ORY_FEDERATION
Ory Polis rewrites OIDC URLs of the form <slug>.projects.oryapis:8080 to the in-cluster hydra-public service and skips the
checks above for them. Only Ory Network uses this. Set this to true on a self-hosted deployment to turn the rewrite off, so that
these URLs are checked like any other host.
Default: false
NPM library option: outbound.internalOryFederation, which defaults to true. Set it to false to turn the rewrite off.
OpenID configuration
For supporting OpenID flow, we need to set the algorithm and keys used to sign the ID token JWT.
OPENID_JWS_ALG
The algorithm used to sign the id_token. Ory Polis uses jose to create the ID token. Supported algorithms can be found here.
Default: RS256
NPM library option: openid.jwsAlg
OPENID_RSA_PRIVATE_KEY
Base64 value of private key. To generate one:
openssl genrsa -out private-key.pem 3072
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in private-key.pem -out private_key.pem
cat private_key.pem | base64
NPM library option: openid.jwtSigningKeys.private
OPENID_RSA_PUBLIC_KEY
Base64 value of public key. You can generate the public key from the private key as shown below:
openssl rsa -in private_key.pem -pubout -out public_key.pem
cat public_key.pem | base64
NPM library option: openid.jwtSigningKeys.public
OPENID_REQUEST_PROFILE_SCOPE
By setting this to false, the profile scope will no longer be automatically included in the Authorization request to the OIDC
provider. This will enable apps to request the minimum required authorization permissions from the signed in user. Apps can
explicitly send the profile scope in the request to Ory Polis which will then be forwarded to the OIDC provider.
Default: true
NPM library option: openid.requestProfileScope
OPENID_REQUEST_FORWARD_PARAMS
Set this to true to forward any extra parameters sent to the /api/oauth/authorize endpoint, such as prompt or ui_locales,
to the OIDC provider's authorization endpoint. Parameters that Ory Polis handles itself, such as client_id, redirect_uri,
state, nonce and the PKCE parameters, are never forwarded. login_hint is always forwarded, whatever this is set to.
Default: false
NPM library option: openid.forwardOIDCParams
OPENID_SUBJECT_PREFIX
By setting this to true, the subject of a directly configured SSO connection is prefixed with ${tenant}:${product}:. If the
result is longer than 255 characters it is replaced by a hash of that value.
With the prefix enabled, a subject is unique per tenant and product rather than only per identifier asserted by an identity provider. Enable it on a deployment that serves more than one tenant. The guarantee stops at the tenant and product: two connections configured under the same tenant and product are not distinguished from one another.
The prefixed value is the sub of the ID token, the id claim the ID token carries, and the sub that /oauth/userinfo returns
when the authorization request asked for the openid scope. The id that /oauth/userinfo returns is always the identifier the
identity provider asserted, whether or not the prefix is enabled, so key accounts on sub rather than on that id.
Turning the prefix on changes the subject of every user of every directly configured SSO connection. Applications that store the old subject stop matching their existing accounts, so plan to re-key them as part of the change.
This prefix does not apply to Identity Federation apps. Their subjects are scoped to the upstream connection that authenticated the user, which the tenant and product of the app do not identify.
Default: false
NPM library option: openid.subjectPrefix
OPENID_IDFED_LEGACY_SUBJECT
Identity Federation apps return a subject scoped to the upstream connection that authenticated the user. While this is set to
true, tokens also carry a legacy_sub claim holding the subject the app returned before that change, so that a relying party
can find an account stored under the old identifier and save the new sub in its place.
Set this to false once the applications consuming your Identity Federation apps have finished doing so. A legacy_sub value is
not unique across the connections behind an app, so it must not be used as an account key, and the claim will be removed in a
later release.
Default: true
NPM library option: openid.idfedLegacySubject
OPENID_REDIRECT_EXACT_MATCH
When set to true, redirect URI validation requires an exact match of the full URL, including scheme, host, and path.
By default (false), redirect validation only checks the scheme and host and ignores the path.
Enable this option to enforce stricter and more secure redirect URI checks.
Default: false
NPM library option: openid.redirectExactMatch
OIDC_ALLOW_USERNAME_EMAIL_FALLBACK
When set to true, OIDC email resolution falls back to the preferred_username and then the upn claim (ID token before
userinfo) when the standard email claim is absent. This is primarily needed for Microsoft Entra ID (Azure AD), which often omits
email and carries the address in one of these username claims. Only values that look like an email address are accepted, and an
email resolved from a fallback claim is marked email_verified: false, since a sign-in identifier is not a verified email
address.
By default (false) only the standard email claim is used. Accepting an address from another claim is a behaviour change for
existing connections, so it is opt-in.
Default: false
NPM library option: openid.allowUsernameEmailFallback
OPENID_USERINFO_REJECT_QUERY_TOKEN
When set to true, the userinfo endpoint accepts the access token only from the Authorization request header field and rejects
requests that pass it in the access_token URI query parameter with a 400 invalid_request error. A token in the URL is exposed
to browser history, proxy and access logs, monitoring pipelines and referrer headers, so
RFC 6750 discourages the query form and
RFC 9700 forbids clients from using it at all.
The default is false because OpenID Connect Core still permits
the query form, and enabling it breaks any client that relies on it. Enable it once your clients send the token in the header.
Default: false
NPM library option: openid.userinfoRejectQueryToken. If you serve the userinfo endpoint yourself, call
oauthController.resolveBearerToken({ headerToken, queryToken }) to apply this policy: it returns either the token to pass to
oauthController.userInfo() or the status and OAuth error to return. Send the error and error_description fields only when
error is set — a request that carried no token at all returns status: 401 with error: null, which
RFC 6750 answers with a bare WWW-Authenticate: Bearer challenge and no
error code.
Identity Federation configuration
IDFED_REQUIRE_SIGNED_LOGOUT_REQUESTS
When set to true, the Identity Federation Single Logout endpoint accepts a SAML LogoutRequest only if it carries a signature
that verifies against the certificate registered on the app. Apps without a certificate can no longer start a logout.
By default (false), the signature is verified whenever an app has a certificate, and requests for apps without one are accepted
unverified.
Register the certificate with the logoutRequestSigningCertificate field on the Identity Federation app. It takes an X.509
certificate in PEM or bare base64 DER form, and accepts a comma-separated list so both halves of a key rotation can be trusted at
once.
Default: false
NPM library option: identityFederation.requireSignedLogoutRequests
Database configuration
DB_ENGINE
Supported values are redis, sql, mongo, mem, planetscale, dynamodb
Default: sql
NPM library option: db.engine
If you are using DynamoDB then you also need to set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. For additional options like
region and capacity units check this section
mem DB (In memory database) is useful to test the Ory Polis setup locally and is not intended for production. In a serverless
deployment like Vercel, the mem DB won't persist across API calls since each call is a fresh lambda invocation with an entirely
new context.
DynamoDB cannot skip records, so pageOffset is ignored when DB_ENGINE is dynamodb and a list call returns at most
DB_PAGE_LIMIT records. Management API endpoints return a pageToken for the next page, so pagination works there. The SCIM
endpoints an identity provider calls have no page token and page with startIndex, so on DynamoDB an identity provider reads only
the first DB_PAGE_LIMIT users or groups of a directory. Do not run directory sync on DynamoDB with directories larger than
DB_PAGE_LIMIT.
DB_TYPE
Only needed when DB_ENGINE is sql. Supported values are postgres, cockroachdb, yugabytedb, mysql, mariadb, mssql,
sqlite
Default: postgres
NPM library option: db.type
mssql is not available when running the Ory Enterprise License FIPS 140-3 image, because the driver's NTLM authentication
depends on MD4. See FIPS 140-3 mode.
DB_URL
The database URL to connect to. If you are using self-signed certificates then pass sslmode=no-verify instead of
sslmode=require in the DB_URL. This is because self-signed certs will be rejected as unauthorized in strict mode. Also, set
DB_SSL=true and DB_SSL_REJECT_UNAUTHORIZED=false (see env vars below for more details).
Example: postgres://postgres:postgres@localhost:5432/postgres or
postgres://postgres:postgres@localhost:5432/postgres?sslmode=no-verify
For mssql the URL takes the form of
sqlserver://localhost:1433;database=<db name>;username=<username>;password=<password>;encrypt=true
The mssql URL also accepts trustServerCertificate. It and encrypt take true, false, 1, 0, yes or no, default to
false when absent, and reject any other value at startup. trustServerCertificate=true makes the driver accept the server
certificate without validating it, the SQL Server counterpart of DB_SSL_REJECT_UNAUTHORIZED=false, so set it only for
self-signed certificates.
If you are using DynamoDB then you also need to set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY. For additional options like
region and capacity units check this section
NPM library option: db.url
DB_SSL
This needs to be set to true if you are using SSL with your database (You should definitely be using SSL if the database needs
to be access via a public url).
Default: false
DB_SSL_REJECT_UNAUTHORIZED
If you are using a self-signed certificate then set this to false, otherwise it will be rejected due to Certificate Authority
checks.
Default: true
DB_MANUAL_MIGRATION
Set this to true to trigger execution of migration scripts when you use the Ory Polis docker image.
Optionally you can run the npm scripts present in ./npm/package.json to run db specific migrations.
Make sure you have set the correct value for DB_ENGINE environment variable as the migration script checks that to run correct
command and migration file.
NPM library option: db.manualMigration Default: false
DB_TTL
TTL for the code, session and token stores (in seconds)
Default: 300
NPM library option: db.ttl
DB_CLEANUP_LIMIT
Limit cleanup of TTL entries to this number
Default: 1000
NPM library option: db.cleanupLimit
DB_PAGE_LIMIT
The default and maximum page size for reads from the database. A paginated list request that asks for a larger page, or that does not set a page size, gets a page of this many records. Lookups that return every match, such as fetching the SSO connections or directories for a tenant and product, read page by page until they reach the end, so this does not cap their results.
Default: 50
NPM library option: db.pageLimit
DB_ENCRYPTION_KEY
To encrypt data at rest specify a 32 byte key (encoded in base64)
You can use openssl to generate a random 32 byte key:
openssl rand -base64 32
NPM library option: db.encryptionKey
PGSSLMODE
If you use Heroku to deploy Postgres (or use self-signed certs for Postgres) then set this to no-verify. See
Heroku docs for more details
DB_DYNAMODB_REGION
If you are using DynamoDB then you can specify the region.
Default: us-east-1
NPM library option: db.dynamodb.region
DB_DYNAMODB_RCUS
If you are using DynamoDB then you can specify the read capacity units. Check AWS docs for more details
Default: 5
NPM library option: db.dynamodb.readCapacityUnits
DB_DYNAMODB_WCUS
If you are using DynamoDB then you can specify the write capacity units.
Default: 5
NPM library option: db.dynamodb.writeCapacityUnits
Webhook configuration
WEBHOOK_URL
Specify a webhook URL to receive events about sso and directory connections.
NPM library option: webhook.endpoint
WEBHOOK_SECRET
Specify a secret to be used to sign the webhook payload. This is used to verify the authenticity of the webhook payload.
NPM library option: webhook.secret
Both the WEBHOOK_URL and WEBHOOK_SECRET are required to enable webhook events.
Events are delivered on a best-effort basis: a failed request is retried up to 3 times, 3 seconds apart, and then dropped. The
failure is logged, and recorded as a failed webhook.delivery; it does not fail the
request that made the change, and the event is not sent again later. See Delivery.
DSYNC_DEBUG_WEBHOOKS
Set this to true to log the full payload of every webhook Ory Polis sends, for both Directory Sync and SSO connection events.
Payloads contain personal data such as names, email addresses and the raw attributes from the identity provider, so use this only
while debugging and don't leave it on in production.
Default: false
NPM library option: dsync.debugWebhooks
Pre-loaded Connections
PRE_LOADED_CONNECTION
If you only need a single tenant or a handful of pre-configured tenants then this config will help you read and load IdP (both OpenID and SAML)connections. It works well with the mem DB engine so you don't have to configure any external databases for this to work (though it works with those as well). This is a path (absolute or relative) to a directory that contains files organized in the format described in the next section. Check this section for more details
NPM library option: preLoadedConnection
Opentelemetry configuration
Ory Polis supports observability via OpenTelemetry. The following env vars are available for configuration (along with the rest of the supported ones)
Polis exports three signals: metrics, traces and logs. Each is on when an OTLP endpoint is configured for it, with the general
variable serving all three and the signal-specific one taking precedence. Logs are an Enterprise feature and also need a valid
POLIS_LICENSE_KEY; with one, setting the general variable exports logs as well, so set
OTEL_LOGS_EXPORTER=none to keep them off.
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_OTLP_METRICS_ENDPOINT, OTEL_EXPORTER_OTLP_TRACES_ENDPOINT or OTEL_EXPORTER_OTLP_LOGS_ENDPOINT
Target URL to which the exporter sends metrics, traces and logs. The general variable is the base URL, to which the exporter
appends /v1/metrics, /v1/traces or /v1/logs on the HTTP protocols; a signal-specific variable is used as given.
Example: http://otel-collector:4318
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_METRICS_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS or OTEL_EXPORTER_OTLP_LOGS_HEADERS
Headers relevant for the endpoint, useful for specifying authentication details for providers.
Example: lightstep-access-token=<token>,...
OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_EXPORTER_OTLP_METRICS_PROTOCOL, OTEL_EXPORTER_OTLP_TRACES_PROTOCOL or OTEL_EXPORTER_OTLP_LOGS_PROTOCOL
The transport protocol: grpc, http/protobuf or http/json. Defaults to http/protobuf when none is set. The signal-specific
variable takes precedence over the general one.
OTEL_METRICS_EXPORTER, OTEL_TRACES_EXPORTER or OTEL_LOGS_EXPORTER
Set one to none to turn that signal off while the endpoint keeps serving the others. Any other value, or unset, exports the
signal over OTLP when an endpoint is configured.
OTEL_RESOURCE_ATTRIBUTES
Attributes to attach to every exported metric, span and log record, as a comma-separated list of key=value pairs.
Set service.instance.id to a value that is unique per running instance. Metrics backends identify a time series by
service.name and service.instance.id, so instances that share an ID write to one series and their counters interleave. Ory
Polis generates a random ID at startup when you don't set one, which keeps instances apart but changes on every restart.
On Kubernetes, take the ID from the pod name:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OTEL_RESOURCE_ATTRIBUTES
value: service.instance.id=$(POD_NAME)
Example: service.instance.id=polis-7d9f-kx2mn,deployment.environment=production
OTEL_SERVICE_NAME
The service.name on the resource of every exported metric, span and log record. Defaults to polis for metrics, which a
Prometheus OTLP receiver turns into the job label, and to Ory Polis for traces and logs, the way the other Ory services name
their tracers and loggers (Ory Hydra, Ory Kratos). Setting it overrides all three. The app attribute on every metric point
is polis regardless.
OTEL_METRIC_EXPORT_INTERVAL
How often metrics are exported, in milliseconds. Defaults to 60000.
OTEL_METRIC_EXPORT_TIMEOUT
How long one export may take before it is abandoned, in milliseconds. Defaults to 30000, and is capped at the export interval.
OTEL_TRACES_SAMPLER and OTEL_TRACES_SAMPLER_ARG
Which spans are recorded. Defaults to parentbased_always_on: a request that arrives with a traceparent header follows the
decision made upstream, and one without is always traced. Set parentbased_traceidratio with OTEL_TRACES_SAMPLER_ARG as a
ratio, 0.1 say, to trace a share of the requests that start at Polis. Sampling applies to the traces only; the
HTTP request metrics count every request that matches a route. See the
SDK configuration for every value.
OTEL_BSP_SCHEDULE_DELAY, OTEL_BSP_EXPORT_TIMEOUT, OTEL_BSP_MAX_QUEUE_SIZE and OTEL_BSP_MAX_EXPORT_BATCH_SIZE
How spans are batched before export: the delay between exports in milliseconds (5000), how long one export may take (30000),
how many finished spans are held before new ones are dropped (2048), and the most in one export (512). These variables apply
to traces only; metrics are exported on the schedule set by OTEL_METRIC_EXPORT_INTERVAL.
OTEL_BLRP_SCHEDULE_DELAY, OTEL_BLRP_EXPORT_TIMEOUT, OTEL_BLRP_MAX_QUEUE_SIZE and OTEL_BLRP_MAX_EXPORT_BATCH_SIZE
How log records are batched before export: the delay between exports in milliseconds (1000), how long one export may take
(30000), how many log records are held before new ones are dropped (2048), and the most in one export (512). A value that is
not a positive whole number falls back to the default.
OTEL_LOG_LEVEL
Log level for the OpenTelemetry SDK's own diagnostics: none, error, warn, info, debug, verbose or all. Unset leaves
SDK diagnostics off. This is only meant for debugging the telemetry setup itself.
OTEL_EXPORTER_DEBUG
Deprecated: set OTEL_LOG_LEVEL=debug instead. Any non-empty value enables debug logs for OpenTelemetry when OTEL_LOG_LEVEL is
unset.
Exported metrics, traces and logs
The metrics, spans and log records Polis exports, their attributes and example queries are described in Observability for Enterprise SSO and Observability for Directory Sync.
Admin Portal configuration
Below variables are used to enable Magic link based authentication for Admin Portal. The SMTP_ variables are used for sending email which contain the magic link (one-time use) for sign in.
SMTP_HOST
The SMTP host like smtp.example.com.
SMTP_PORT
The SMTP server port like 587.
SMTP_USER
Username for the SMTP server.
SMTP_PASSWORD
Password for the SMTP server.
SMTP_FROM
From address used to send mail like: [email protected].
NEXTAUTH_URL
When running locally this will point to the local server: http://localhost:5225. When deploying to production, set this to the
canonical URL of the site. More details here.
NEXTAUTH_SECRET
Set this to a random string. You can use openssl rand -base64 32 to get one. This secret is used to encrypt JWT and hash the
email verification token. More details here.
NEXTAUTH_ACL
Set this to a comma separated string of email addresses or glob patterns like: [email protected],*@marvel.com. Access will be
denied to email addresses which don't match. If you don't specify any value access is denied to all and magic links are turned
off.
NEXTAUTH_ADMIN_CREDENTIALS
Set this to a comma separated string of the pattern email:password to enable login to the Admin Portal, for example
[email protected]:Password123. If you don't specify any value access is denied to all.
ADMIN_PORTAL_HIDE_DIRECTORY_SYNC
Set this to true if you want to hide the Directory Sync product in the sidebar.
Default: false
ADMIN_PORTAL_HIDE_IDENTITY_FEDERATION
Set this to true if you want to hide the Identity Federation product in the sidebar.
Default: false
ADMIN_PORTAL_SSO_TENANT
This will be used as the tenant for the SSO connections (added from Settings tab) used to login into the Admin portal itself. Set this to a value that is less likely to conflict with the main Enterprise SSO connections.
Default: _jackson_boxyhq
ADMIN_PORTAL_SSO_PRODUCT
This will be used as the product for the SSO connections (added from Settings tab) used to login into the Admin portal itself. Set this to a value that is less likely to conflict with the main Enterprise SSO connections.
Default: _jackson_admin_portal
SETUP_LINK_EXPIRY_DAYS
The number of days a new setup link stays valid. A setup link created through the API can set its own expiry instead.
Default: 3
NPM library option: setupLinkExpiryDays
Anonymous Analytics
POLIS_NO_ANALYTICS or DO_NOT_TRACK
Set one of these to 1 or true to turn off anonymous analytics. Once a day, Ory Polis sends a random installation ID and the
number of SSO connections and Directory Sync connections. It sends no information that can identify you.
NPM library option: noAnalytics
SSO Traces
SSO_TRACES_DISABLE
Set this to true to disable SSO Traces collection.
NPM library option: ssoTraces.disable
SSO_TRACES_REDACT
Set this to true to redact profile information and the raw SAML request and response documents in SSO Traces. The OpenTelemetry
log records have their own setting, SSO_TELEMETRY_REDACT.
NPM library option: ssoTraces.redact
SSO_TRACES_TTL
Set this to control how long SSO Traces are stored, as a number of hours or as a duration such as 720h, 30d or 1d 12h.
Default: 7 days.
Set it to an empty value to keep traces indefinitely, for a deployment that investigates failures reported long after they happen.
Polis logs a warning at startup when it does, because the trace table then grows for as long as the deployment runs. Anything that
is not a duration end to end, including a zero such as 0h and a value that merely contains a duration such as 1d garbage,
falls back to the 7-day default and logs a warning, so a typo never silently changes retention.
NPM library option: ssoTraces.ttl, in seconds, where 0 keeps traces indefinitely.
SSO_TELEMETRY_REDACT
Set this to true to leave the payloads of single sign-on out of the OpenTelemetry log records: the SAML requests and responses,
the profile Polis extracted from the IdP response and the OIDC ID token. The user's ID and email address are still logged. See
Payloads.
When it is unset or false, those payloads are exported with the logs, personal data and ID tokens included. The Helm chart sets
it to true by default (monitoring.sso.redact.enabled).
NPM library option: ssoTraces.telemetryRedact
Directory Sync
The following env vars are used to configure the directory sync feature.
DSYNC_GOOGLE_ env vars are only applicable if you are using Google Workspace as a directory sync provider.
DSYNC_WEBHOOK_BATCH_SIZE
Enable batch processing of directory sync events. The value represents the number of events to batch together instead of sending
each event individually. With batching, failed deliveries are retried and each directory's events are delivered in the order they
were made; see batch processing. This requires you to configure a
cron job to process the queued events. Alternatively you can set
DSYNC_WEBHOOK_BATCH_CRON_INTERVAL below if you are not deploying the service in an Edge environment.
By default, batching is off and each event is sent as soon as it happens.
NPM library option: dsync.webhookBatchSize
DSYNC_WEBHOOK_BATCH_CRON_INTERVAL
The cron interval at which to process the queued events. Provide a number in seconds. By default, the cron job is disabled.
NPM library option: dsync.webhookBatchCronInterval
DSYNC_WEBHOOK_BATCH_MAX_RETRIES
How many times a queued event is retried after its first failed delivery attempt. Any response outside the 2xx range, and any
request that fails outright, counts as a failed attempt.
By default there is no ceiling: the queue holds an event until the endpoint accepts it, with the attempts spaced further and
further apart. Set this to a number if you would rather shed events than keep them forever. An event that exhausts the budget is
moved out of the delivery queue into a dead-letter store, where it is kept for inspection and is never sent again. 0 makes the
first failed attempt final.
A 400 or 422 response is final whatever this is set to. The endpoint has read the payload and will not take it, so sending the
same bytes again cannot change the answer: the event is moved to the dead-letter store straight away and the events queued behind
it for that connection carry on. Every other response, including 401, 403, 404, 413, 429, and anything 5xx, can
succeed later with the same payload and is retried. If an endpoint answers 413 because the batch is too large for it, lower
DSYNC_WEBHOOK_BATCH_SIZE and the queued events go out in smaller requests.
NPM library option: dsync.webhookBatchMaxRetries
DSYNC_WEBHOOK_BATCH_RETRY_INTERVAL
The base delay in seconds before a failed event is retried. The delay doubles with each attempt and is jittered, up to a maximum
of one hour between attempts. Events waiting on their backoff are skipped, so a single unreachable endpoint does not hold up the
events of other connections. Within a connection, events are delivered in the order they were queued: an event that is waiting to
be retried also holds back the events queued behind it. That ordering relies on the database returning queued events in the order
they were written, which every engine does except DynamoDB, where the queue is keyed by a random id and events for one connection
can be delivered out of order. Defaults to 30.
NPM library option: dsync.webhookBatchRetryInterval
DSYNC_WEBHOOK_LOGS_TTL
Controls how long SCIM (directory sync) webhook event logs are retained. Provide a duration string such as 720h, 30d or
1d 12h.
- Unset (default): logs keep the existing 7-day retention.
- Empty string: logs are kept indefinitely (no expiry). Polis logs a warning at startup, because the table then grows for as long as the deployment runs.
- Anything that is not a duration end to end, including a value that merely contains one such as
1d garbage: falls back to the 7-day default and logs a warning, so a typo never silently changes retention.
NPM library option: dsync.webhookLogsTTL
DSYNC_TELEMETRY_REDACT
Set this to true to leave the SCIM request bodies and the webhook event payloads out of the OpenTelemetry log records of
directory sync; see Payloads. The IDs, names and email addresses of the users and
groups are still logged.
When it is unset or false, those payloads are exported with the logs, personal data included. The Helm chart sets it to true
by default (monitoring.dsync.redact.enabled).
NPM library option: dsync.telemetryRedact
DSYNC_GOOGLE_CRON_INTERVAL
The cron interval at which to sync the Google Workspace. Provide a number in seconds. By default, the cron job is disabled.
Each run syncs the active Google Workspace directories in turn; a deactivated directory is skipped until it is activated again. A
directory that fails, such as one whose Google grant was revoked, is logged and recorded as a failed
polis.dsync.sync, and the run goes on to the next; the failed
directory is tried again on the next run. When Polis shuts down during a run, the run ends after the directory it is syncing, and
the directories it had not reached are synced on the next run.
NPM library option: dsync.providers.google.cronInterval
DSYNC_MAX_INLINE_GROUP_MEMBERS
When includeMembers=true is set and a group has more than 500 members, the request returns a 400 error and directs you to the
paginated group members endpoint, rather than returning a partial or oversized response. The 500-member limit is configurable.
Default: 500
NPM library option: dsync.maxInlineGroupMembers
DSYNC_GOOGLE_CLIENT_ID
The Google authentication client ID.
NPM library option: dsync.providers.google.clientId
DSYNC_GOOGLE_CLIENT_SECRET
The Google authentication client secret.
NPM library option: dsync.providers.google.clientSecret
dsync.providers.google.authorizePath
The authorization endpoint for Google SCIM.
NPM library option: dsync.providers.google.authorizePath
For example: /api/scim/oauth/authorize
dsync.providers.google.callbackPath
The path to redirect to after completing the authorization request for Google SCIM.
NPM library option: dsync.providers.google.callbackPath
For example: /api/scim/oauth/callback
Enterprise Features
POLIS_LICENSE_KEY
Unlocks the enterprise features: identity federation, branding, products, and OpenTelemetry logs. Please reach out to obtain a license for enterprise features.
Deployments that use the Ory Polis Enterprise License Helm chart get this variable from the chart.
NPM library option: polisLicenseKey
The former name of this variable, BOXYHQ_LICENSE_KEY, still applies when POLIS_LICENSE_KEY is not set.
POLIS_REQUIRE_FIPS
Set to 1 or true to make Polis refuse to start, and its database migration job refuse to run, when FIPS 140-3 mode is not
active. Leave it unset, or set it to 0 or false, to turn the check off. Any other value also turns the check on, and Polis
logs a warning about it. The polis-oel-fips image sets it to 1. See
FIPS 140-3 mode.
NPM library option: requireFips, which takes a boolean or a string parsed the same way.
Logger options
LOG_FILE
Log file to write to
LOG_LEVEL
Log levels - "fatal" | "error" | "warn" | "info" (default) | "debug" | "trace"
