New Ory Agent Security is now live! Claim your complimentary test drive. Get Started!

Skip to main content

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 idpInitiatedLoginEnabled follows IDP_ENABLED. With IDP_ENABLED=true, IdP-initiated login is allowed for it; with IDP_ENABLED=false, it is not.
  • Setting idpInitiatedLoginEnabled on a connection overrides the switch: true always allows IdP-initiated login for that connection, false always blocks it.

Default: false

NPM library option: idpEnabled

warning

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

note

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.

note

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

note

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

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.

warning

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.

warning

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"