Configuration overview
Choose how to configure networking, data stores, sandboxes, authentication, and advanced settings for self-hosted Dreadnode.
Everything in the Configure group is chart configuration. It is declarative, it is applied by a redeploy, and it rolls pods. Dreadnode exposes the same chart settings through three configuration interfaces:
| Interface | Use it for | Configuration shape |
|---|---|---|
| Helm | Existing Kubernetes clusters | Umbrella-chart values overlay |
| Admin Console | Interactive Embedded Cluster installs and edits | Labeled fields under Config |
| KOTS ConfigValues | Automated Embedded Cluster installation | Replicated ConfigValues YAML |
Settings that live in the running product instead — model deployments, credentials, users, organizations, signup rules — are not here. See Model deployments and Users and organizations.
Every configuration section below uses the same three tabs. Your selection follows you across
this section. A KOTS ConfigValues file uses the Admin Console field’s internal item name, not the
Helm value path. Every ConfigValues scalar is a string, including numbers and booleans; password
items use valuePlaintext so KOTS encrypts them during installation.
Start with the domain, scheme, ingress class, and resource preset on this page. Use the focused guides for settings that need additional infrastructure or verification.
Domain and scheme
Section titled “Domain and scheme”The domain appears in every URL Dreadnode generates, including OAuth redirects, presigned S3 URLs, and password reset links.
Set both values in your Helm overlay:
global: domain: dreadnode.example.com scheme: https # http (default) or httpsOpen Config → Dreadnode Identity. Set Domain to dreadnode.example.com and URL
Scheme to HTTPS.
A ConfigValues-only Embedded Cluster installation should start on HTTP because the TLS Secret does not exist in the new cluster yet:
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: domain: value: dreadnode.example.com scheme: value: httpSet both values correctly before first use. When you change either value, redeploy the release and access Dreadnode through the newly configured URL. Before changing an Embedded Cluster install from HTTP to HTTPS, create the TLS Secret and follow TLS certificates.
The domain also seeds the OpenSandbox runtime authority: leaving the sandbox domain empty derives
sandbox.<domain>, so changing the platform domain moves the wildcard that browsers use to reach
runtimes. Update DNS and the certificate alongside it — see Route browsers to OpenSandbox
runtimes.
Ingress
Section titled “Ingress”The chart emits standard Kubernetes Ingress resources. Set the class to the controller that should reconcile them:
global: ingress: className: traefik annotations: {} httpsRedirect: auto # auto | traefik | noneOpen Config → Networking & TLS. Set Ingress Class Name, Ingress Annotations, and
HTTP to HTTPS Redirect. Keep the default class, traefik, for Embedded Cluster.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: ingress_class_name: value: traefik https_redirect: value: autoAdd ingress_annotations to the same document only when your controller requires them:
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: ingress_class_name: value: traefik https_redirect: value: auto ingress_annotations: value: | nginx.ingress.kubernetes.io/ssl-redirect: "true"Global annotations cascade to the API, frontend, docs, and MinIO Ingress resources. Use subchart-specific annotations only when one route needs different controller behavior.
Choosing https decides what URLs Dreadnode generates. It does not by itself
stop the ingress controller answering on port 80, so a bookmarked http://
link still loads a working UI whose API calls travel in cleartext. The
httpsRedirect setting is what closes that:
| Value | Behavior |
|---|---|
auto | Default. Renders a Traefik redirect Middleware when an enabled Ingress resolves to class traefik. Covers Embedded Cluster, which bundles Traefik. |
traefik | Always renders it. Use when Traefik is the cluster’s default class and you left className empty. |
none | Renders nothing. Use only when a load balancer or proxy ahead of the cluster already redirects. |
On a Helm install using another controller, the chart cannot render a portable redirect, so you own it through annotations. For ingress-nginx:
global: ingress: className: nginx annotations: nginx.ingress.kubernetes.io/ssl-redirect: 'true'Gateway API
Section titled “Gateway API”If your cluster routes traffic through the Kubernetes Gateway API — Istio, Envoy
Gateway, Cilium, or Traefik’s gateway provider — the chart can expose the
platform as HTTPRoute resources attached to your existing Gateway instead of
Ingress:
global: httproute: parentRefs: - name: main-gateway namespace: gateway-system
dreadnode-api: ingress: enabled: false httproute: enabled: true
dreadnode-frontend: ingress: enabled: false httproute: enabled: true
dreadnode-base: minio: apiIngress: enabled: false httproute: enabled: true
dreadnode-sandbox-server: gateway: ingress: enabled: false httproute: enabled: trueIf the LiteLLM proxy is enabled, switch dreadnode-litellm the same way.
Each service accepts its own httproute.parentRefs, hostnames, matches,
and filters when the shared cascade is not enough — see the chart README
for the full key reference.
Open Config → Networking & TLS. Set Traffic Routing to Gateway API (HTTPRoute), then set Gateway Name, and optionally Gateway Namespace and Gateway Listener Name. The ingress-only fields (TLS Secret, class, annotations, redirect) disappear — they do not apply in this mode.
Embedded Cluster does not show this option: it bundles Traefik serving Ingress, and ships no Gateway API CRDs.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: exposure_mode: value: exposure_gateway gateway_name: value: main-gateway gateway_namespace: value: gateway-systemThe chart never creates the Gateway — your cluster operator owns it, along with its listeners and certificates. Ingress and HTTPRoute are mutually exclusive per service, and the chart fails the render with a pointed error if both are enabled.
Requirements on the Gateway side:
- The Gateway API CRDs and a controller must be installed, and the Gateway you
reference must exist. Cross-namespace attachment requires the Gateway’s
allowedRoutesto admit the install namespace. - Listeners must cover
<domain>,storage.<domain>(the MinIO S3 endpoint), and the wildcard sandbox authority*.sandbox.<domain>used for per-sandbox URLs — a wildcard*.<domain>listener alongside the<domain>one covers storage, but the sandbox authority nests one level deeper and needs its own*.sandbox.<domain>listener with a matching wildcard certificate. - Under
scheme: https, TLS terminates on the Gateway’s listener (mode: TerminatewithcertificateRefs), so the chart does not requireglobal.tls.secretName. The HTTP-to-HTTPS redirect is also the Gateway’s job — an HTTP listener answering with aRequestRedirectfilter, or your controller’s equivalent.
After deploying, confirm the routes attached:
kubectl -n <namespace> get httproute# NAME HOSTNAMES AGE# dreadnode-api ["dreadnode.example.com"] 1m# dreadnode-frontend ["dreadnode.example.com"] 1m# dreadnode-docs ["dreadnode.example.com"] 1m# dreadnode-minio ["storage.dreadnode.example.com"] 1m# dreadnode-sandbox-server-gateway ["*.sandbox.dreadnode.example.com"] 1mA route that never becomes Accepted in its status conditions usually means no
listener matches its hostname, or the Gateway’s allowedRoutes rejects the
namespace.
Documentation
Section titled “Documentation”Plane: chart values / Admin Console. The documentation you are reading ships inside the
release and is served by the deployment at /docs on your domain, so every help link in the
application resolves without leaving your network. It is on by default and needs nothing from
you.
Disable it only if your users should read documentation somewhere else, and name that
place at the same time. The application’s help links resolve against docsUrl, so the chart
refuses to render the bundled docs turned off with nothing to replace them.
dreadnode-docs: enabled: falsedreadnode-api: config: docsUrl: https://docs.internal.example.com/There is no dedicated field. Set both keys under Advanced Helm Values; this overrides dedicated fields.
dreadnode-docs: enabled: falsedreadnode-api: config: docsUrl: https://docs.internal.example.com/apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: advanced_helm_values: value: | dreadnode-docs: enabled: false dreadnode-api: config: docsUrl: https://docs.internal.example.com/If you run your own ingress with the chart’s disabled, route /docs to the dreadnode-docs
Service the way you already route /api. In Gateway API mode the route is created for you.
What the bundled copy leaves out on an isolated network is described under
Air-gapped installation.
Client IP resolution
Section titled “Client IP resolution”dreadnode-api: config: network: trustedProxyHops: 1Open Config → Networking & TLS and set Trusted Proxy Hops.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: trusted_proxy_hops: value: "1"Dreadnode reads the client address this many hops from the right of
X-Forwarded-For. The default of 1 is correct when your ingress controller
is the only thing in front of the platform. Add one for each additional load
balancer or CDN. Setting it too low attributes activity to your load balancer
instead of the user; setting it too high lets a client spoof its own address in
the audit trail.
Outbound finding submissions
Section titled “Outbound finding submissions”Item submission integrations deliver findings to external systems — Linear, Jira, bug bounty platforms, and arbitrary webhooks. Turn them off if findings must not leave your network:
dreadnode-api: config: integrations: enabled: falseThere is no dedicated field. Open Config → Advanced → Advanced Helm Values and add:
dreadnode-api: config: integrations: enabled: falseapiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: advanced_helm_values: value: | dreadnode-api: config: integrations: enabled: falseThis is a hard stop rather than a display preference. The integrations API refuses every request while it is off, so a user driving the API directly cannot submit either, and a submission already in progress when you apply the change is recorded as failed instead of being delivered.
Existing connections and submission history are kept. Turning integrations back on makes them reachable again with nothing to reconfigure — but read the audit trail first if you switched off in response to an incident, because the history is unreachable through the product while the switch is off.
Storage volumes
Section titled “Storage volumes”Bundled PostgreSQL, ClickHouse, and object storage each get their own volume:
dreadnode-base: postgresql: primary: persistence: size: 8Gi storageClass: '' # empty uses the cluster default clickhouse: persistence: size: 10Gi minio: persistence: size: 10GiOpen Config → Data Stores. Set PostgreSQL Volume Size, ClickHouse Volume Size, and Object Storage Volume Size while each store remains in its in-cluster mode. Embedded Cluster manages the StorageClass.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: postgres_storage_size: value: 8Gi clickhouse_storage_size: value: 10Gi minio_storage_size: value: 10GiSize these before the first deploy. Growing a volume afterward requires a
StorageClass with allowVolumeExpansion plus a manual edit, and shrinking one
is not possible at all.
ClickHouse is the volume that fills first, because every agent run writes trace spans to it. If you would rather cap growth than add disk, see the retention settings in Operations.
Resource sizing
Section titled “Resource sizing”global: resourcesPreset: small # small | medium | largeOpen Config → Scaling & Resources and set Resource Preset.
apiVersion: kots.io/v1beta1kind: ConfigValuesspec: values: resources_preset: value: small # small | medium | largeThe preset applies a component-specific resource profile across the release:
| Preset | Suggested deployment size | API requests | API limits |
|---|---|---|---|
small | Up to about 50 users | 250m, 1536Mi | 500m, 2Gi |
medium | About 50–200 users | 500m, 2Gi | 1000m, 3Gi |
large | More than 200 users | 1000m, 3Gi | 4000m, 8Gi |
The small preset is the default. See
Install with Helm — Resource guidance for cluster
capacity guidance. Resource presets do not size dynamically created OpenSandbox pods. Configure
their scheduling requests separately under Sandbox Runtime; see Size OpenSandbox
pods.
Apply changes
Section titled “Apply changes”Keep your overlay in source control and apply it with helm upgrade:
helm upgrade dreadnode oci://registry.replicated.com/dreadnode/dreadnode \ --version <version> \ --namespace <namespace> \ -f values.yamlSelect Save config, review the pending changes, then select Deploy. Saving without deploying does not update the running application.
Pass the complete ConfigValues document during the initial Embedded Cluster installation:
sudo ./dreadnode install \ --license license.yaml \ --config-values dreadnode-config.yaml \ --admin-console-password '<admin-console-password>'Preflight checks run as part of the command. After installation, make configuration changes through the Admin Console.
For settings without a dedicated Admin Console field or ConfigValues item, use Advanced Helm Values. For every available Helm value and its default, pull the chart’s values file:
helm show values oci://registry.replicated.com/dreadnode/dreadnode --version <version>