Skip to content

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:

Terminal window
export NAMESPACE=dreadnode

The 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.

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
fromAddress: [email protected]
fromName: Dreadnode
smtp:
host: smtp.example.com
port: 587
user: apikey
useTls: true
existingSecret: dreadnode-smtp-password
passwordKey: password

Create the referenced Secret in the Helm release namespace:

Terminal window
kubectl -n "$NAMESPACE" create secret generic dreadnode-smtp-password \
--from-literal=password='<smtp-password>'

Local password authentication remains available when you configure OAuth. Each provider can be enabled independently.

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 profile

Create the referenced Secret:

Terminal window
kubectl -n "$NAMESPACE" create secret generic dreadnode-oidc-oauth \
--from-literal=clientSecret='<oidc-client-secret>'

Register this redirect URI with the provider:

https://<your-domain>/auth/oidc/callback

Use 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:

ServerMetadata URL
Orghttps://<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 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: clientSecret

Create one Secret for each configured provider:

Terminal window
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>'

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.

Raise the minimum password length or restrict new accounts to email patterns:

dreadnode-api:
config:
auth:
minPasswordLength: 12
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:

Terminal window
sudo install -D -m 0644 /path/to/GeoLite2-Country.mmdb \
/var/lib/dreadnode/geolite/GeoLite2-Country.mmdb

Configure 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.mmdb

Set NAMESPACE to the Helm release namespace before applying the workload patch below.

Add the read-only hostPath mount that the chart does not currently represent:

Terminal window
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: File
YAML
kubectl -n kotsadm patch deployment dreadnode-api \
--type=strategic \
--patch-file /tmp/dreadnode-geolite2-patch.yaml
kubectl -n kotsadm rollout status deployment/dreadnode-api