Authentication and email
Configure SMTP delivery, OAuth providers, and signup policy for self-hosted Dreadnode.
The authentication, email, and signup settings on this page are chart configuration, applied by a redeploy. Configure them in a Helm overlay, under Authentication & Email in the Admin Console, or with matching KOTS ConfigValues items. The email allow-list and other settings without a dedicated field use Advanced Helm Values. The cluster shell is only needed to mount the GeoLite2 database; every credential on this page has a protected Embedded Cluster field.
Helm commands on this page use $NAMESPACE. Set it to your release namespace before creating
Secrets:
export NAMESPACE=dreadnodeThe runtime signup controls under Admin → Security — IP rate limits, CIDR blocks, and disposable-domain rules — are a separate plane and need no redeploy. See Users and organizations.
Email delivery
Section titled “Email delivery”By default, Dreadnode does not send email. The API logs invitation, password-reset, and any
verification links at WARNING level so an operator can deliver them manually.
Configure the API chart:
dreadnode-api: config: email: provider: smtp fromName: Dreadnode smtp: host: smtp.example.com port: 587 user: apikey useTls: true existingSecret: dreadnode-smtp-password passwordKey: passwordCreate the referenced Secret in the Helm release namespace:
kubectl -n "$NAMESPACE" create secret generic dreadnode-smtp-password \ --from-literal=password='<smtp-password>'Open Config → Authentication & Email, enable SMTP email delivery, then enter the relay and sender settings. The Admin Console stores the password as a protected value and creates the Kubernetes Secret.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: smtp_enabled: value: "1" smtp_host: value: smtp.example.com smtp_port: value: "587" smtp_user: value: apikey smtp_password: valuePlaintext: '<smtp-password>' smtp_use_tls: value: "1" smtp_from_address: smtp_from_name: value: DreadnodeOAuth providers
Section titled “OAuth providers”Local password authentication remains available when you configure OAuth. Each provider can be enabled independently.
OpenID Connect
Section titled “OpenID Connect”Use the generic provider for Authentik, Keycloak, Okta, and other OpenID
Connect issuers. metadataUrl, clientId, and the client Secret are all
required.
dreadnode-api: config: oauth: oidc: clientId: <oidc-client-id> metadataUrl: https://idp.example.com/.well-known/openid-configuration existingSecret: dreadnode-oidc-oauth clientSecretKey: clientSecret displayName: Authentik scopes: openid email profileCreate the referenced Secret:
kubectl -n "$NAMESPACE" create secret generic dreadnode-oidc-oauth \ --from-literal=clientSecret='<oidc-client-secret>'Open Config → Authentication & Email, enable OpenID Connect, then enter OIDC Client ID, Client Secret, Metadata URL, Login Button Label, and Scopes.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: oidc_enabled: value: "1" oidc_client_id: value: '<oidc-client-id>' oidc_client_secret: valuePlaintext: '<oidc-client-secret>' oidc_metadata_url: value: https://idp.example.com/.well-known/openid-configuration oidc_display_name: value: Authentik oidc_scopes: value: openid email profileRegister this redirect URI with the provider:
https://<your-domain>/auth/oidc/callbackUse the scheme and domain configured for Dreadnode. The scopes must include
openid and must cause the issuer to return an email claim in either the ID
token or userinfo response; openid email profile is the usual configuration.
New users receive the default role on first login; group and role claim mapping
is not currently supported. An issuer that sends group claims logs in normally,
and Dreadnode ignores those claims.
Create an OIDC Web Application in Okta. Dreadnode authenticates with a
client secret, so do not choose the SPA application type. Keep the default
Client secret authentication method (client_secret_basic); post-only
client authentication is not supported. Configure:
- Sign-in redirect URI:
https://<your-domain>/auth/oidc/callback, matching exactly - Grant type: Authorization Code
- Scopes:
openid email profile
Okta exposes two authorization-server shapes:
| Server | Metadata URL |
|---|---|
| Org | https://<your-okta-domain>/.well-known/openid-configuration |
Custom (including default) | https://<your-okta-domain>/oauth2/<server-id>/.well-known/openid-configuration |
Use the org authorization server for ordinary Okta sign-in. Choose a custom authorization server only when you need its customized claims or access policies, and make sure that server has an access policy covering the Dreadnode application. The generic connector accepts either discovery URL.
Dreadnode matches returning users by email address. The sub claim is retained
with the identity data and is checked when ID-token claims are supplemented
from the userinfo endpoint, but it is not used for account lookup. Changing a
user’s Okta email can therefore create a separate Dreadnode account.
OAuth-created accounts are treated as email-confirmed even when Okta omits
email_verified. Restrict the Okta application’s assignment and authorization
policy to users whose email addresses your organization trusts.
GitHub and Google
Section titled “GitHub and Google”GitHub and Google use the same secret-backed pattern:
dreadnode-api: config: oauth: github: clientId: <github-client-id> existingSecret: dreadnode-github-oauth clientSecretKey: clientSecret google: clientId: <google-client-id> existingSecret: dreadnode-google-oauth clientSecretKey: clientSecretCreate one Secret for each configured provider:
kubectl -n "$NAMESPACE" create secret generic dreadnode-github-oauth \ --from-literal=clientSecret='<github-client-secret>'
kubectl -n "$NAMESPACE" create secret generic dreadnode-google-oauth \ --from-literal=clientSecret='<google-client-secret>'Open Config → Authentication & Email, enable GitHub login or Google login, then enter the client ID and client secret for each provider.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: github_oauth_enabled: value: "1" github_client_id: value: '<github-client-id>' github_client_secret: valuePlaintext: '<github-client-secret>' google_oauth_enabled: value: "1" google_client_id: value: '<google-client-id>' google_client_secret: valuePlaintext: '<google-client-secret>'Remove the provider you do not use. The Embedded Cluster secrets are protected in stored configuration and written to Kubernetes Secrets without a cluster-shell step.
Register these callback URLs with each provider:
- GitHub:
https://<your-domain>/auth/github/callback - Google:
https://<your-domain>/auth/google/callback
Both providers reach the public GitHub and Google endpoints, so neither works on an airgapped install. To use Google Workspace as your enterprise identity provider, prefer OpenID Connect instead, which centralizes sign-in at your own tenant. Dreadnode does not currently map identity-provider groups to platform or organization roles.
Signup policy
Section titled “Signup policy”Raise the minimum password length or restrict new accounts to email patterns:
dreadnode-api: config: auth: minPasswordLength: 12 emailRegexes: - '^.*@example\.com$'Open Config → Authentication & Email, enable Set a custom password policy, then set
Minimum Password Length. Put dreadnode-api.config.auth.emailRegexes under Advanced Helm
Values when you also need an email allow-list.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: signup_policy_customize: value: "1" min_password_length: value: "12" advanced_helm_values: value: | dreadnode-api: config: auth: emailRegexes: - '^.*@example\.com$'An empty emailRegexes list allows any email address. Omitting minPasswordLength uses the API
default of 8.
Self-hosted deployments default to an explicit, unchecked marketing-email
consent option for every signup. Geo-based treatment (an auto opt-in notice
for US signups) activates when a GeoLite2 Country database is mounted into the
API container and SIGNUP_GEO_PROVIDER=maxmind_local and
SIGNUP_GEOIP_LOCAL_PATH are set through
additional environment variables.
Lookup failures fall back to the manual opt-in default.
The chart has no first-class volume value for this database. Copy the database to the same path on every node that can run the API pod:
sudo install -D -m 0644 /path/to/GeoLite2-Country.mmdb \ /var/lib/dreadnode/geolite/GeoLite2-Country.mmdbConfigure the API environment for your deployment path:
Add the environment variables to your values overlay:
dreadnode-api: extraEnv: - name: SIGNUP_GEO_PROVIDER value: maxmind_local - name: SIGNUP_GEOIP_LOCAL_PATH value: /var/lib/dreadnode/geolite/GeoLite2-Country.mmdbSet NAMESPACE to the Helm release namespace before applying the workload patch below.
Under Config → Advanced Helm Values, add:
dreadnode-api: extraEnv: - name: SIGNUP_GEO_PROVIDER value: maxmind_local - name: SIGNUP_GEOIP_LOCAL_PATH value: /var/lib/dreadnode/geolite/GeoLite2-Country.mmdbSave and deploy, enter sudo ./dreadnode shell, and set NAMESPACE=kotsadm before applying
the workload patch below.
Add the environment variables through advanced_helm_values during the initial install:
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: advanced_helm_values: value: | dreadnode-api: extraEnv: - name: SIGNUP_GEO_PROVIDER value: maxmind_local - name: SIGNUP_GEOIP_LOCAL_PATH value: /var/lib/dreadnode/geolite/GeoLite2-Country.mmdbAfter installation, enter sudo ./dreadnode shell and set NAMESPACE=kotsadm before applying
the workload patch below.
Add the read-only hostPath mount that the chart does not currently represent:
cat > /tmp/dreadnode-geolite2-patch.yaml <<'YAML'spec: template: spec: containers: - name: dreadnode-api volumeMounts: - name: signup-geolite2 mountPath: /var/lib/dreadnode/geolite/GeoLite2-Country.mmdb readOnly: true volumes: - name: signup-geolite2 hostPath: path: /var/lib/dreadnode/geolite/GeoLite2-Country.mmdb type: FileYAML
kubectl -n kotsadm patch deployment dreadnode-api \ --type=strategic \ --patch-file /tmp/dreadnode-geolite2-patch.yaml
kubectl -n kotsadm rollout status deployment/dreadnode-api