Configuration Reference
This page is a structured reference to the full configuration surface for a Marshal install — every Terraform variable (Terraform path) and its corresponding raw Helm chart value (ArgoCD / GitOps path). For task-oriented walkthroughs, see the Installing Marshal guides; for the onboarding credentials themselves, see Prerequisites — this page assumes you already have them and covers everything else.
Both installers configure the same underlying Helm chart. The Terraform
variable names below are how you set things when installing via Terraform;
the “Chart value” noted in each row is the equivalent raw Helm value, useful
if you’re on the ArgoCD/GitOps path and writing valuesObject (or a
values.yaml) directly.
Almost everything here has a sensible default. Only three settings are required with no default: the installation JWT, the chart version, and the ingress hostname.
Release identity & chart
| Setting | Values | Default | Notes |
|---|---|---|---|
release_name | string | marshal | Helm release name. |
namespace | string | marshal | Control-plane namespace. |
create_namespace | bool | true | Whether Terraform creates the namespace. On the ArgoCD path this is instead syncOptions: [CreateNamespace=true] on the Application — but the seeded Secrets (below) still need the namespace to exist beforehand. |
chart | string | marshal | Chart name inside the OCI registry. You won’t normally change this. |
chart_version | string | (none — required) | Exact product version to install. Chart value: targetRevision on the ArgoCD Application. Always the version given in your onboarding materials. |
Credentials
The three onboarding credentials (installation_jwt, deployment_id,
registry_pull_token) are explained in full in
Prerequisites → Onboarding credentials —
this table only maps them to their settings.
| Setting | Values | Default | Notes |
|---|---|---|---|
installation_jwt | JWT string | (none — required) | Your license. Stored as a K8s Secret. Chart value: not set directly — on the ArgoCD path this is a pre-seeded Secret referenced by license.secretName / license.key. |
deployment_id | dep_... | (none — required) | Registry username (convention only — the registry ignores the username and authenticates on the token). |
registry_pull_token | mrpt_... | (none — required) | Registry password. Authenticates chart pulls, product image pulls, and (in secret registry mode) session tool-image pulls. |
Registry & image pulls
Controls where product and session tool images are pulled from. The
effective image prefix is image_cache_registry when set, else registry.
| Setting | Values | Default | Notes |
|---|---|---|---|
image_cache_registry | registry host/path | (empty) | Your shared pull-through cache. Recommended, required at scale. One per customer, set up once, reused by every install (prod, staging, …). Chart value: global.registry. |
registry | registry host | registry.marshal.codes | Direct-pull registry. Only used when image_cache_registry is unset. |
registry_auth_mode | secret | workloadIdentity | none | secret | secret: chart builds a dockerconfigjson from your pull token and stamps it on pods — simplest, good for a single-node eval. workloadIdentity: nodes pull via GKE Workload Identity / EKS IRSA — no in-cluster secret, pairs with a pull-through cache. none: an open in-network mirror, anonymous pulls. Chart value: registryAuth.mode. |
registry_secret_server | string | derived | Name of the generated image-pull Secret replicated into the sessions namespace when registry_auth_mode = secret. |
Direct pull (registry_auth_mode = secret) shares Marshal’s registry rate
limit across every customer pulling at once. It’s fine for a single-node
eval; for a real install, run a pull-through cache and set
image_cache_registry.
Datastores
Postgres and Redis are configured independently. Recommended posture: external Postgres + bundled Redis.
| Setting | Values | Default | Notes |
|---|---|---|---|
database_mode | external | bundled | external | external (recommended): supply database_url; Postgres is the source of truth for sessions, orgs, credentials, manifests, and audit, and needs real backups/HA. bundled is demo/eval only. |
database_url | Postgres DSN | (none) | Required when database_mode = external. Stored as a K8s Secret; never enters Helm release state. Chart value: externalDatabaseSecret.name / .key, pointing at a Secret you (or the module) create. |
redis_mode | bundled | external | bundled | bundled (default, recommended): in-cluster Redis. Everything Marshal keeps in Redis is ephemeral/TTL’d/reconstructible (WS tokens, SSE streams, pod addresses, OAuth state, usage buffers) — nothing durable lives only in Redis, so a managed instance buys durability you don’t need. external: supply redis_url to point at managed Redis. |
redis_url | Redis URL | (none) | Required when redis_mode = external. Chart value: bundledDeps.redis.enabled: false plus your own Redis connection value. |
Ingress & TLS
| Setting | Values | Default | Notes |
|---|---|---|---|
ingress_host | hostname | (none — required) | Required on day one — plans fail without it even before real DNS exists. Point DNS at the load balancer whenever convenient. Chart value: ingress.host. |
ingress_enabled | bool | true | Whether the chart creates an Ingress at all. Chart value: ingress.enabled. |
ingress_class_name | string | cloud-specific | The IngressClass to use (e.g. gce-internal, nginx, alb). Chart value: ingress.className. |
ingress_annotations | map | (empty) | Extra annotations merged onto the Ingress object — useful for controller-specific config (e.g. a cert-manager issuer annotation). |
ingress_tls | list | (empty) | Low-level TLS escape hatch — always wins over any higher-level TLS option below. Use this if you manage TLS via your own ingress controller / cert-manager instead of a cloud flavor’s built-in TLS handling. |
preview_domain | domain | (empty) | Base domain for per-session preview subdomains (*.<preview_domain>). Leave unset if you don’t use preview URLs. |
preview_scheme | http | https | https | Scheme used when constructing preview URLs. |
Some cloud flavors layer additional, more opinionated TLS handling on top of
the shared ingress_tls escape hatch. For example, the GKE flavor exposes a
tls_mode variable:
| Setting | Values | Default | Notes |
|---|---|---|---|
tls_mode (GKE flavor) | self_signed | inline | secret | none | self_signed | self_signed: Terraform generates a clearly-marked placeholder cert and manages the Secret for you — HTTPS works out of the box, with a browser warning until you replace it. inline: paste real PEM cert/key into tfvars. secret: point tls_secret_name at a Secret you manage yourself (e.g. via cert-manager). none: HTTP-only. Switching between these needs no other config change. |
If you use preview_domain, the certificate needs to cover
*.<preview_domain>, not just ingress_host. GKE-managed certificates
don’t support wildcard domains at all, and cert-manager needs a DNS-01
solver (not the default HTTP-01) to issue one. The self_signed default
covers the wildcard correctly out of the box. See
Troubleshooting if a wildcard cert request is stuck.
Secrets management
Controls how the two critical app secrets — JWT_SECRET (signs session/API
tokens) and KMS_LOCAL_KEY (envelope-encrypts every stored credential) — are
sourced. Chart value: secrets.provider.
secrets_provider value | Chart value | What it means | When to use it |
|---|---|---|---|
generated | secrets.provider: generated | The chart generates random values on first install and (via Helm’s lookup function) reuses the same ones on every subsequent helm upgrade. | Terraform installs only — Terraform actually runs helm install/helm upgrade, so lookup works. Default for the Terraform path. |
existing | secrets.provider: existing | You create a stable Secret yourself, once; the chart only references it via secrets_existing_secret and never manages or rotates it. | Required for the ArgoCD/GitOps path. ArgoCD renders and applies manifests directly — it never runs helm install, so lookup never executes, and generated would mint fresh secrets on every sync. |
externalSecrets | secrets.provider: externalSecrets | An External Secrets Operator installation populates the Secret from your own cloud secret manager. | GitOps installs that already run External Secrets Operator and want the app secrets sourced from a central secret store instead of a manually-seeded Secret. |
| Setting | Values | Default | Notes |
|---|---|---|---|
secrets_provider | generated | existing | externalSecrets | generated | See table above. |
secrets_existing_secret | Secret name | (none) | Required when secrets_provider = existing. The Secret must carry JWT_SECRET and KMS_LOCAL_KEY keys. |
secrets_external_secrets | config | (none) | Required when secrets_provider = externalSecrets. |
kms_backend | backend identifier | module default | Selects the backend that manages the key used to envelope-encrypt stored credentials. |
Never switch secrets_provider back to generated on an install that’s
already running, and never delete the Secret backing existing /
externalSecrets — losing KMS_LOCAL_KEY makes every stored credential
permanently unrecoverable, and rotating JWT_SECRET invalidates every
issued session and API token. See Troubleshooting for
the failure mode this causes.
Session namespace & marketplace
| Setting | Values | Default | Notes |
|---|---|---|---|
spaces_namespace | string | derived from namespace | The namespace session pods run in, separate from the control-plane namespace. |
marketplace_upstream | URL | Marshal’s default catalog | Where the marketplace pulls its default catalog of tools, agents, and MCP servers from. |
marketplace_token_exchange_url | URL | Marshal’s default | Endpoint the marketplace uses to exchange for short-lived credentials when installing a catalog item into a session. |
marketplace_customer_repos | list | (empty) | Additional customer-specific repos to include in the marketplace catalog, beyond the default upstream set. |
License tuning
| Setting | Values | Default | Notes |
|---|---|---|---|
license_jwks_url | URL | https://keys.marshal.codes/.well-known/jwks.json | Where the api fetches the public JWKS used to verify your installation JWT’s signature. |
license_refresh_url | URL | https://tokens.marshal.codes/v1/license | Where the installation JWT is exchanged for a short-lived operational license (online tier). |
license_enforce | bool | true | Whether the api hard-enforces license verification. |
Web sign-in
| Setting | Values | Default | Notes |
|---|---|---|---|
basic_auth_enabled | bool | false | Puts HTTP basic auth in front of the web dashboard, in addition to normal sign-in. |
Escape hatch
| Setting | Values | Default | Notes |
|---|---|---|---|
values_overrides | list of YAML strings (Terraform) | (empty) | Raw Helm values merged on top of everything else — for chart settings that don’t have a first-class Terraform variable yet. On the ArgoCD path, the equivalent is simply adding more keys to valuesObject (or your values.yaml) directly. |
values_overrides = [
<<-EOT
redis:
image:
repository: some/override
EOT
]Every chart value surfaced above is cross-checked against the umbrella
chart’s own values.yaml — if you need something not listed here, it likely
still exists as a raw chart value reachable through this escape hatch.