Configuration overview configuration¶
The flat configuration hub remains the compatibility route. This page is the canonical source-checked field reference for its family, including nested tables and list rows.
Paths in the tables are relative to the section heading. Each row gives the
serde type and source default or unset meaning; secrets stay in protected files
or the supported environment overlay. Check parsing, unknown keys, and
cross-field rules with gdsgate doctor --config <PATH> --json, then follow the
configuration templates.
Layering¶
The effective config is built in three layers:
- Defaults. The loopback development profile and each source-defined field default. Fields without a source default remain unset until configured.
- TOML file from
--config. Any field present overwrites the default. - Environment overlay. Any
GDSGATE_*variable present overwrites the file. An unset variable changes nothing.
Use the layers to keep secrets and per-host values out of committed files. See Environment overrides.
Secret references¶
A configuration value that is a secret, or a path to one, can name where the
value actually lives instead of holding it directly. A value written as the
whole string ${scheme:argument} is a reference; every other value is read
literally, so a file written before the notation existed keeps working
unchanged. Only a value that both opens with ${ and closes with } is
parsed as a reference at all: ${file:unclosed and $TOKEN are literal
values, not broken ones.
| Scheme | Value |
|---|---|
| (no prefix) | The value itself; for a parameter that names a path, the file at that path. |
file:PATH |
The file's contents, trailing newline stripped. |
env:NAME |
An environment variable of the process. |
exec:COMMAND ARG... |
Standard output of a command, trailing newline stripped. |
[audit]
anchor_key_path = "/var/lib/gdsgate/anchor.key" # bare path, unchanged
approval_key_path = "${file:/var/lib/gdsgate/approval.key}" # the same thing, written out
revocation_key_path = "${env:REVOCATION_KEY_MATERIAL}" # a variable of this process
delegation_key_path = "${exec:/usr/local/bin/gdsgate-unwrap delegation}" # a helper's standard output
Which reading a bare value gets depends on the parameter, not on the notation.
A parameter that names a path reads a bare value as a file, exactly as before
the notation existed: anchor_key_path = "/var/lib/gdsgate/anchor.key" and
anchor_key_path = "${file:/var/lib/gdsgate/anchor.key}" mean the same thing.
A parameter whose value is not a path, an agent delegation profile's env
entries, the one-time enrollment token, reads a bare value as the value
itself.
What accepts it¶
| Parameter | Documented at |
|---|---|
[audit].anchor_key_path |
Operations |
[audit].approval_key_path |
Operations |
[audit].revocation_key_path |
Operations |
[audit].delegation_key_path |
Operations |
[audit].inventory_key_path |
Operations |
[authority].enroll_key_file |
Authority |
[proxy].web_key_file |
Proxy |
[proxy].webapps_key_file |
Proxy |
[proxy].public_key_file |
Proxy |
store_password_file |
Top level |
[enroll].token |
Enrollment |
[[connector.backends]].service_account_password_file |
Connector |
[[connector.backends]].token_path |
Connector |
[[connector.backends]].credential_file |
Connector |
[connector.backends.discovery].password_file |
Connector |
Running a command¶
exec: starts a helper and takes what it prints, which is how an operator
reaches a hardware module or a secret store this process has no driver for.
- The command runs without a shell. The string is split on whitespace and the first word is executed directly; a pipeline, a redirect, or a second command cannot be written this way, and neither can an argument that contains a space. A helper that needs one is a wrapper script that takes none.
- Nothing travels in the arguments. What the reference resolves to is read from the command's standard output, and the command is given nothing on its standard input. An argument is readable by every account on the host and is kept by the shell history of whoever runs the command by hand.
- A nonzero exit code is a refusal. The parameter is treated as unresolved and the process does not start; nothing is substituted for a secret the command could not produce.
- The environment is inherited unchanged. Whatever authenticates the helper to wherever the secret lives is expected to already be there; gdsgate adds no authentication scheme of its own for this.
- The command has 30 seconds to answer before it is killed and the reference refused.
A reference is resolved while configuration loads, never on a session's data
path. The one exception is a listener's certificate key: the pair is re-read
whenever the certificate file changes, so a helper or variable behind
web_key_file, webapps_key_file, public_key_file, or enroll_key_file
runs again at each rotation, not only at start-up.
env: and where it shows up¶
env: reads a variable of the process's own environment. It stays the right
choice where a value has to reach a child process that would receive it in its
own environment regardless, an agent delegation profile's env entries being
the example. For a parameter in the table above, prefer file: or exec:: a
process's environment is visible to anyone who can read /proc/<pid>/environ
on the host, and it routinely ends up in a crash dump.
gdsgate doctor reports which form
each covered parameter is using, without reading the material behind it.
Wrapping a source: ${kms.<name>+<source>}¶
Any of the three sources above can itself be ciphertext, held under a key an
external service holds rather than one this process has.
${kms.<name>+file:PATH} says the file's contents are that ciphertext, and
that the key <name>, one of the keys [[kms_keys]] declares,
is what turns it back into a value; env: and exec: take the same prefix
the same way. <name> can be left out, ${kms+file:PATH}, only while
[[kms_keys]] declares exactly one key; naming a key that is not declared, or
leaving the name out while more than one is declared, is refused when the
configuration loads rather than resolved to a guess.
| Written | Means |
|---|---|
${kms.<name>+file:PATH} |
The file holds ciphertext; the key <name> unwraps it. |
${kms.<name>+env:VAR} |
The variable holds ciphertext; the key <name> unwraps it. |
${kms.<name>+exec:CMD} |
The command's standard output is ciphertext; the key <name> unwraps it. |
${kms+file:PATH} (name left out) |
As above, meaning the single key [[kms_keys]] declares. |
A wrapper cannot sit on another wrapper: ${kms.a+kms.b+file:PATH} is refused
rather than read as double protection. And a source under a wrapper that turns
out to hold a keyring document rather than ciphertext is refused too, before
the key is even asked: what came back is parsed as a keyring, and a parse that
succeeds means there was nothing to unwrap, the material sitting in the open
under a reference that claimed otherwise.
Only a parameter that reads a whole keyring accepts this prefix today:
[security.integrity].control_keyring and
.audit_keyring. Every other parameter in
What accepts it reads a ${kms...} value and refuses it
outright, naming the parameter and pointing at the plain form as the fix.
A wrapping key answers to three actions and no more:
| Action | Given | Gets back |
|---|---|---|
unwrap |
ciphertext | the material |
wrap |
the material | ciphertext |
generate |
nothing | fresh material and its ciphertext, together, in one answer |
generate is what a first authority init or a keys rotate --prepare calls
under a wrapped keyring: the pair comes back from the service in one call, so
the material never has to exist anywhere it is not needed, on its way to being
encrypted. wrap is what writes a wrapped keyring back: a keyring is wrapped
whole, as one document, so adding a key to one, or converting one off the five
legacy key files, goes through it. No material crosses in an argument, in
either direction, on any of the three: an argument is readable by every
account on the host and is kept in the shell history of whoever ran the
command by hand. A non-zero exit is a refusal and nothing else; a start that
could not reach the key stops rather than carrying on under material invented
locally, and what a refused call printed is never read back into an error
message.
For the exec kind, the three actions are a command run three ways. Whatever
command declares is run with one word appended, and everything
else about it is unchanged from running a command
above: no shell, nothing split beyond the declared words, a 30-second timeout.
| Action | Argument appended | Standard input | Standard output |
|---|---|---|---|
unwrap |
unwrap |
the ciphertext | the material |
wrap |
wrap |
the material | the ciphertext |
generate |
generate |
nothing | {"ciphertext":"...","plaintext":"..."}, both base64 |
The native kinds answer the same three actions over their own service's
protocol; see [[kms_keys]] for which build carries which.
[[kms_keys]]¶
Used by: Authority.
The external keys this deployment's wrapped material sits under: what a
${kms.<name>+...} reference names, and what
[authority].ca_kms_key names by
itself. A key here belongs to a service that only ever wraps and unwraps: it
takes ciphertext and gives back the material that was sealed under it, or
takes material and gives back ciphertext, and the key itself never leaves the
service. That is a narrower thing than a secret store that hands out a whole
secret on request, and the two are not interchangeable: a key-value store has
nothing to unwrap, so it is reached through exec:
directly, as a source, rather than through this array. The transit engine of
one product can be both at once. Vault and OpenBao's transit mount wraps and
unwraps, which is what provider = "vault" means here; the same product's
key-value store hands out whole secrets, which is a different mount reached a
different way.
| Key | Type | Default | Purpose |
|---|---|---|---|
name |
string | required | What a wrapper names between kms. and +. See naming below. |
provider |
string | required | exec, vault, aws, or gcp. Which of the fields below this row reads. |
command |
array of strings | [] |
exec only, and required for it: the program and its arguments, the action word appended when it runs. An array rather than a line, so a path or an argument with a space in it needs no quoting. |
key |
string | "" |
Required for the three native kinds: the service's own name for the key. The key's name inside the transit engine (vault), an ARN, alias, or key id (aws), or the key's full resource name (gcp). |
address |
string | "" |
Where the service answers, as a base URL. Required for vault, reached nowhere else. Optional for aws, to name an interface endpoint or a separate compliance-regime endpoint in place of the region's public one. Unused by gcp, whose address is fixed. |
mount |
string | "" |
vault only: where the transit engine is mounted. Empty means transit. |
region |
string | "" |
aws only: which region the key lives in. |
[[kms_keys]]
name = "audit"
provider = "exec"
command = ["/usr/local/bin/gdsgate-kms", "--key", "audit"]
[[kms_keys]]
name = "audit"
provider = "vault"
address = "https://vault.example.invalid:8200"
mount = "kms-transit"
key = "gdsgate-audit"
[[kms_keys]]
name = "control"
provider = "aws"
region = "eu-central-1"
key = "arn:aws:kms:eu-central-1:123456789012:key/2f1c"
[[kms_keys]]
name = "ca"
provider = "gcp"
key = "projects/p/locations/europe-west1/keyRings/r/cryptoKeys/k"
Authentication for all three native kinds comes from the process environment;
gdsgate keeps no credential of its own for any of them, matching exec. Read
in the order given, first found wins:
vault: the token,VAULT_TOKEN, or the file~/.vault-tokenwhere that is unset. Separately,VAULT_NAMESPACEnames a request's namespace where the deployment uses them, andVAULT_CACERTnames a private root of trust where the service's certificate is not signed by a public one.aws:AWS_ACCESS_KEY_IDwithAWS_SECRET_ACCESS_KEY(AWS_SESSION_TOKENalongside them for a temporary pair), then the credentials a container runtime hands out, then the role the instance is running under, asked of its metadata service.gcp: a service-account file named byGOOGLE_APPLICATION_CREDENTIALS, exchanged for a token by signing an assertion; failing that, the identity of the instance itself, asked of its metadata service.
Each native kind is carried only by a build compiled with its own feature,
kms-vault, kms-aws, or kms-gcp, because each links a client for somebody
else's service and a binary carrying all three carries most of them unused.
exec is in every build. A row naming a kind the running binary was not built
with is still parsed, not rejected as an unknown name; it is refused when the
declared keys are assembled, and the refusal names the feature that would
carry it, so the operator reads "this binary does not have it" rather than
"this name is wrong".
There is no native pkcs11 kind. The shipped binary is statically linked, and
a statically linked binary cannot dlopen a vendor's module, which is how
PKCS#11 is reached; the module itself is built against glibc regardless. A
hardware module, a KMIP device, or a key service with no native kind here is
reached through provider = "exec" instead: a small helper the operator
builds against the vendor's own library links it directly, on a host free to
be linked dynamically.
Naming a key¶
A name is a boundary of revocation. [[kms_keys]] can declare more than one
key, and naming them apart is what makes withdrawing this cluster's access to
one of them stop only what that key covers, rather than everything any
${kms...} reference points at. One key for everything would put the split the
two keyrings exist for back together a layer down, in whichever service holds
the key: the audit journal that outlives the decisions it records, and may be
handed to somebody outside the cluster, would unwrap under the same access as
those decisions themselves. See
[security.integrity] for what the split is
for. Declaring keys under different providers costs nothing extra and is
written the same way as declaring them under the same one.
A reference may leave the name out only while there is a single key to mean; Wrapping a source has the grammar.
What is checked against a running service¶
exec asks nothing external: the contract is a process boundary, and tests
hold down both sides of it. The three native kinds each speak a real
service's protocol, and each has been run against one, though not to the same
depth:
| Kind | Checked against a running service | Not exercised |
|---|---|---|
vault |
Vault 1.18.5 and OpenBao 2.6.2: a keyring wrapped, read back, rotated, CA seeds wrapped, Authority restarted on ciphertext. | A namespace (VAULT_NAMESPACE), a private root of trust (VAULT_CACERT), and a token read from ~/.vault-token rather than the environment. |
aws |
The same chain, plus the service's own request validation (a wrong signature, a wrong region, a stale timestamp, headers signed out of order, or a body changed after signing each draw its own refusal; a wrong action name draws another), a ciphertext refused under a key that did not produce it, and the direct-encryption limit measured at the service itself. | The role of an EC2 instance, credentials a container runtime hands out, refreshing a temporary credential before it expires, key policies and grants, an interface or compliance endpoint reached through address, and a region outside the default partition. |
gcp |
The same chain, plus the exact shape of the three calls, that protectionLevel = "HSM" is the only level the service accepts from any location, and the signed-assertion exchange for a token. |
The real metadata server (this run supplied its own), a token actually expiring in real time rather than exercising the below-margin branch, the other kinds of service-account credential file, and telling "not enough permission" apart from "the request is malformed" on a live refusal. |
The direct-encryption limit¶
AWS KMS encrypts at most 4096 bytes of plaintext in one call to Encrypt or
Decrypt; GenerateDataKey is unaffected, since it returns its own
ciphertext already inside that limit. A CA seed is 32 bytes and is nowhere
near it. What can reach the limit is a wrapped keyring, which travels as one
document: it holds 20 keys that only seal, or 14 that sign and so carry a
public half, before the document stops fitting in one call. A keyring under
ordinary rotation holds far fewer, since keys rotate --retire removes a key
once nothing seals under it any more; the limit is reachable only by keeping
verify-only keys around rather than retiring them. Either way the refusal
happens on this side, before anything is sent: it names the limit and the size
that was handed to it, and nothing is sent or written.
Top level¶
Used by: Authority, Proxy, Connector, and the foreground Resident client
(profile); Authority (store_url, store_password_file, store_auto_migrate).
| Key | Type | Default | Purpose |
|---|---|---|---|
profile |
string (optional) | unset, no deployment label | Deployment name. Labels service metrics, logs, and exported traces. The foreground Resident client labels its journal but exports no service metrics or traces. |
store_url |
string (optional) | unset, ~/.gdsgate/state/store.db (persistent file SQLite) |
State backend Authority consumes: audit chain, the transport CA's private key, the SSH CAs, registration tokens, resource catalog. SQLite (file or :memory:) or PostgreSQL. Unset persists next to the node identity so a restart keeps the same CA; set :memory: only for ephemeral tests. |
store_password_file |
string (optional) | unset | The state backend's password, kept out of store_url. A path, or a secret reference. PostgreSQL only. |
store_auto_migrate |
bool | true |
Whether a starting service may bring the store's schema up to date itself. false means a service start never changes the schema: a store with pending migrations stops the process, naming how many are pending and the command that applies them. |
profile security endpoints store_url store_password_file store_auto_migrate enroll authority transport client proxy policy mcp mfa oidc identity workload ca_rotation ha approvals discovery connector recording admin audit telemetry doctor agent_profiles delegation_profiles kms_keys
profile = "prod-eu"
store_url = "postgres://gdsgate@store-db.example.invalid:5432/gdsgate"
store_auto_migrate = false # schema changes are a step of the rollout
profile names the deployment. Authority, Proxy and Connector each read it and
label their own telemetry with it. Set it and each service Prometheus series
carries profile="<value>", each structured service log line carries a
profile field, and each exported service trace carries a profile resource
attribute. A foreground Resident client also labels its journal, but exports no
service metrics or traces. Leave the value unset to omit the label.
See Metrics and health.
The value must be non-empty, at most 64 bytes, and drawn from
A-Z a-z 0-9 . _ -. It comes from the configuration only: a request, a header
or a token cannot set it, and it is read once, at startup. Environment overlay:
GDSGATE_PROFILE.
Anything else stops a service (authority, proxy, connector, all, and
gdsgate up --foreground) at start, naming the character it refused. Those are
the processes that publish under the label. Every other command runs without a
label and says so on stderr, since it exports nothing, and
gdsgate doctor reports the value as a
config.profile finding.
Left unset, store_url defaults to a persistent file SQLite at
~/.gdsgate/state/store.db; set it explicitly for PostgreSQL or a custom path.
sqlite::memory: loses everything on restart and is only useful for tests.
store_password_file names the state backend's password separately from
store_url, so store_url itself carries only the user
(postgres://gdsgate@store-db.example.invalid:5432/gdsgate) and the two are
joined only to open a connection. It applies to PostgreSQL only; a SQLite store
has no password, and naming both this field and a password inside store_url
at once is refused at start-up. A password written directly into store_url
still works and is redacted wherever the URL is printed, and
gdsgate doctor warns and names this field as the
place to move it. Environment overlay: GDSGATE_STORE_PASSWORD_FILE.
store_auto_migrate is on by default, so a start applies whatever the store is
missing. Turn it off where a schema change is a scheduled step: the operator
runs gdsgate authority migrate once, then
starts the fleet. Either way a start refuses a store whose schema is newer than
the binary, since that database was migrated by a newer build. Environment
overlay: GDSGATE_STORE_AUTO_MIGRATE.
admin admin.endpoint admin.identity_dir admin.transport agent_profiles agent_profiles[].checked agent_profiles[].config_args agent_profiles[].config_env agent_profiles[].config_format agent_profiles[].config_path agent_profiles[].model_config_key agent_profiles[].model_url_env agent_profiles[].model_url_path agent_profiles[].name agent_profiles[].note agent_profiles[].source agent_profiles[].tools_entry agent_profiles[].tools_key approvals approvals.min_approvers approvals.per_environment audit audit.anchor_key_path audit.approval_key_path audit.checkpoint_interval_secs audit.delegation_key_path audit.export_path audit.inventory_key_path audit.revocation_key_path audit.verify_interval_secs authority authority.ca_kms_key authority.emergency_socket authority.enroll_cert_file authority.enroll_key_file ca_rotation ca_rotation.check_secs ca_rotation.enabled ca_rotation.interval_secs ca_rotation.proactive_secs ca_rotation.propagation_secs ca_rotation.retire_secs client client.access client.allow_insecure_http client.direct client.direct.basic_port_range client.direct.catalog_sync_secs client.direct.v4_pool client.intercept_names client.notify client.resolver client.step_up_on_denial client.transparent client.transparent.dns_zone client.transparent.reuse_grace_secs client.transparent.v4_pool client.transparent.v6_pool client.transport_ca client.transport_sni client.warm_access connector connector.authority_transport connector.backends connector.backends[].addr connector.backends[].admin connector.backends[].allow connector.backends[].allow_agent_forward connector.backends[].allow_elicitation_url connector.backends[].allow_encoded_separator connector.backends[].allow_fastpath_function connector.backends[].allow_local_forward connector.backends[].allow_port_forward connector.backends[].allow_remote_forward connector.backends[].allow_unpinned_upstream connector.backends[].allowed_backend_hosts connector.backends[].allowed_input_requests connector.backends[].allowed_models connector.backends[].allowed_query_params connector.backends[].allowed_request_headers connector.backends[].allowed_tools connector.backends[].api_url connector.backends[].audit connector.backends[].auth_mode connector.backends[].ca_path connector.backends[].cage connector.backends[].cage.allow_degraded connector.backends[].cage.cpu_quota connector.backends[].cage.memory_max connector.backends[].cage.private_network connector.backends[].cage.private_tmp connector.backends[].cage.protect_home connector.backends[].cage.read_only_paths connector.backends[].cage.read_write_paths connector.backends[].cage.report_denied_paths connector.backends[].cage.restrict_address_families connector.backends[].cage.tasks_max connector.backends[].command connector.backends[].command_env connector.backends[].credential connector.backends[].credential_file connector.backends[].credential_format connector.backends[].credential_header connector.backends[].db_roles connector.backends[].db_roles[].db_user connector.backends[].db_roles[].name connector.backends[].db_roles[].read_only connector.backends[].decider_ca_path connector.backends[].decider_command connector.backends[].decider_command_env connector.backends[].decider_fail_closed connector.backends[].decider_timeout_ms connector.backends[].decider_url connector.backends[].decision_cache_ttl_secs connector.backends[].discovery connector.backends[].discovery.allowlist connector.backends[].discovery.connection connector.backends[].discovery.denylist connector.backends[].discovery.freshness_secs connector.backends[].discovery.interval_secs connector.backends[].discovery.mode connector.backends[].discovery.password_file connector.backends[].enforce_query_categories connector.backends[].enforce_tool_policy connector.backends[].forwarded_headers connector.backends[].host_key_fingerprints connector.backends[].host_key_fingerprints_file connector.backends[].identity connector.backends[].identity_headers_trust_the_network connector.backends[].inspect connector.backends[].kind connector.backends[].login_user connector.backends[].max_request_bytes connector.backends[].pin_tool_descriptors connector.backends[].record_request connector.backends[].record_response connector.backends[].refuse_unfiltered_tool_listing connector.backends[].resource connector.backends[].routed_ranges connector.backends[].routes connector.backends[].routes[].audit connector.backends[].routes[].match connector.backends[].routes[].name connector.backends[].service_account connector.backends[].service_account_password_file connector.backends[].service_account_tls_ca_file connector.backends[].settable_parameters connector.backends[].statement_timeout_ms connector.backends[].token_path connector.backends[].url connector.backends[].websocket connector.id delegation_profiles delegation_profiles[].agent_profile delegation_profiles[].can delegation_profiles[].env delegation_profiles[].exec delegation_profiles[].exec_args delegation_profiles[].model delegation_profiles[].name delegation_profiles[].renewable delegation_profiles[].sandbox delegation_profiles[].sandbox_allow delegation_profiles[].sandbox_cpu delegation_profiles[].sandbox_memory delegation_profiles[].sandbox_processes delegation_profiles[].ttl_secs discovery discovery.import_rules discovery.import_rules[].environment discovery.import_rules[].labels discovery.import_rules[].match discovery.resources discovery.resources[].aliases discovery.resources[].hostname discovery.resources[].id discovery.resources[].kind discovery.resources[].min_approvers discovery.resources[].native_name discovery.resources[].pin_tool_descriptors discovery.resources[].port discovery.resources[].project doctor doctor.check_interval_secs endpoints endpoints.authority endpoints.authority_enroll endpoints.authority_failover endpoints.proxy_internal endpoints.proxy_join endpoints.proxy_public endpoints.proxy_ws enroll enroll.background_renewal enroll.endpoint enroll.node_name enroll.renew_endpoint enroll.state_dir enroll.token enroll.transport_ca ha ha.enabled ha.lease_ttl_secs ha.owner ha.renew_secs identity identity.allow_system_groups identity.max_groups identity.max_length kms_keys kms_keys[].address kms_keys[].command kms_keys[].key kms_keys[].mount kms_keys[].name kms_keys[].provider kms_keys[].region mcp mcp.destructive_patterns mfa mfa.webauthn mfa.webauthn.allow_any_port mfa.webauthn.allow_localhost mfa.webauthn.origins mfa.webauthn.rp_id mfa.webauthn.rp_origin oidc oidc.allow_insecure_http oidc.audience oidc.client_id oidc.id_token_signing_algs oidc.issuer oidc.jwks_refresh_secs oidc.request_timeout_secs policy policy.editor policy.editor.break_glass_policy_file policy.editor.min_approvers policy.path profile proxy proxy.internal_accept_burst proxy.internal_accept_rate_per_ip proxy.join_accept_burst proxy.join_accept_rate_per_ip proxy.join_idle_timeout_secs proxy.join_max_connections proxy.join_peek_timeout_secs proxy.max_bytes_per_second_per_session proxy.max_public_connections proxy.max_sessions proxy.max_streams_per_tunnel proxy.public_admin_max_connections proxy.public_anonymous_burst proxy.public_anonymous_rate_per_ip proxy.public_cert_file proxy.public_join proxy.public_join_burst proxy.public_join_rate_per_ip proxy.public_key_file proxy.public_origin proxy.public_proxy_protocol_from proxy.public_renewal_max_connections proxy.session_rate_burst_bytes proxy.single_port proxy.web_addr proxy.web_cert_file proxy.web_key_file proxy.webapps_addr proxy.webapps_cert_file proxy.webapps_key_file proxy.webapps_proxy_protocol_from proxy.webapps_session_ttl_secs proxy.webapps_zone recording recording.capture_stdin recording.mode security security.integrity security.integrity.audit_keyring security.integrity.control_keyring security.profile store_auto_migrate store_password_file store_url telemetry telemetry.metrics_listen telemetry.otel_endpoint transport transport.cert_ttl_secs transport.front_sni workload workload.cert_ttl_secs workload.issuers workload.issuers[].audience workload.issuers[].groups workload.issuers[].issuer workload.issuers[].owner_claim workload.issuers[].owner_service workload.issuers[].path_template workload.issuers[].single_use_jti workload.issuers[].slug workload.trust_domain
profile|None security|Security::default() endpoints|Endpoints::default() store_url|None store_password_file|None store_auto_migrate|true enroll|Enroll::default() authority|Authority::default() transport|Transport::default() client|Client::default() proxy|Proxy::default() policy|Policy::default() mcp|Mcp::default() mfa|Mfa::default() oidc|Oidc::default() identity|Identity::default() workload|Workload::default() ca_rotation|CaRotation::default() ha|Ha::default() approvals|Approvals::default() discovery|Discovery::default() connector|Connector::default() recording|Recording::default() admin|Admin::default() telemetry|Telemetry::default() doctor|Doctor::default() agent_profiles|Vec::new() delegation_profiles|Vec::new() kms_keys|Vec::new()
Environment overrides¶
Each configuration override listed below overlays the file; an unset variable
changes nothing. Other GDSGATE_* variables can be command inputs or switches
instead. Use the supported overrides for secrets and per-host values.
| Variable | Overrides |
|---|---|
GDSGATE_PROFILE |
profile |
GDSGATE_STORE_URL |
store_url |
GDSGATE_STORE_PASSWORD_FILE |
store_password_file |
GDSGATE_STORE_AUTO_MIGRATE |
store_auto_migrate |
GDSGATE_AUTH_ADDR |
endpoints.authority |
GDSGATE_AUTH_ENROLL_ADDR |
endpoints.authority_enroll |
GDSGATE_PROXY_PUBLIC_ADDR |
endpoints.proxy_public |
GDSGATE_PROXY_INTERNAL_ADDR |
endpoints.proxy_internal |
GDSGATE_PROXY_WS_ADDR |
endpoints.proxy_ws |
GDSGATE_PROXY_JOIN_ADDR |
endpoints.proxy_join |
GDSGATE_ENROLL_ENDPOINT |
enroll.endpoint |
GDSGATE_ENROLL_TOKEN |
enroll.token |
GDSGATE_ENROLL_STATE_DIR |
enroll.state_dir |
GDSGATE_ENROLL_RENEW_ENDPOINT |
enroll.renew_endpoint |
GDSGATE_ENROLL_NODE_NAME |
enroll.node_name |
GDSGATE_CLIENT_TRANSPORT_CA |
client.transport_ca |
GDSGATE_CLIENT_TRANSPORT_SNI |
client.transport_sni |
GDSGATE_CLIENT_ALLOW_INSECURE_HTTP |
client.allow_insecure_http |
GDSGATE_PROXY_SINGLE_PORT |
proxy.single_port |
GDSGATE_POLICY_PATH |
policy.path |
GDSGATE_OIDC_ISSUER |
oidc.issuer |
GDSGATE_OIDC_CLIENT_ID |
oidc.client_id |
GDSGATE_OIDC_AUDIENCE |
oidc.audience |
GDSGATE_OIDC_ALLOW_INSECURE_HTTP |
oidc.allow_insecure_http |
GDSGATE_OIDC_JWKS_REFRESH_SECS |
oidc.jwks_refresh_secs |
GDSGATE_OIDC_REQUEST_TIMEOUT_SECS |
oidc.request_timeout_secs |
GDSGATE_IDENTITY_ALLOW_SYSTEM_GROUPS |
identity.allow_system_groups |
GDSGATE_IDENTITY_MAX_LENGTH |
identity.max_length |
GDSGATE_IDENTITY_MAX_GROUPS |
identity.max_groups |
GDSGATE_CONNECTOR_ID |
connector.id |
GDSGATE_CONNECTOR_AUTH_TRANSPORT |
connector.authority_transport |
GDSGATE_CA_ROTATION_ENABLED |
ca_rotation.enabled |
GDSGATE_CA_ROTATION_INTERVAL_SECS |
ca_rotation.interval_secs |
GDSGATE_CA_ROTATION_PROACTIVE_SECS |
ca_rotation.proactive_secs |
GDSGATE_CA_ROTATION_PROPAGATION_SECS |
ca_rotation.propagation_secs |
GDSGATE_CA_ROTATION_RETIRE_SECS |
ca_rotation.retire_secs |
GDSGATE_CA_ROTATION_CHECK_SECS |
ca_rotation.check_secs |
GDSGATE_HA_ENABLED |
ha.enabled |
GDSGATE_HA_OWNER |
ha.owner |
GDSGATE_HA_LEASE_TTL_SECS |
ha.lease_ttl_secs |
GDSGATE_HA_RENEW_SECS |
ha.renew_secs |
GDSGATE_AUDIT_ANCHOR_KEY_PATH |
audit.anchor_key_path |
GDSGATE_AUDIT_APPROVAL_KEY_PATH |
audit.approval_key_path |
GDSGATE_AUDIT_REVOCATION_KEY_PATH |
audit.revocation_key_path |
GDSGATE_AUDIT_DELEGATION_KEY_PATH |
audit.delegation_key_path |
GDSGATE_AUDIT_INVENTORY_KEY_PATH |
audit.inventory_key_path |
GDSGATE_AUDIT_EXPORT_PATH |
audit.export_path |
GDSGATE_TELEMETRY_METRICS_LISTEN |
telemetry.metrics_listen |
GDSGATE_TELEMETRY_OTEL_ENDPOINT |
telemetry.otel_endpoint |
GDSGATE_ADMIN_ENDPOINT GDSGATE_ADMIN_IDENTITY_DIR GDSGATE_ADMIN_TRANSPORT GDSGATE_AUDIT_ANCHOR_KEY_PATH GDSGATE_AUDIT_APPROVAL_KEY_PATH GDSGATE_AUDIT_DELEGATION_KEY_PATH GDSGATE_AUDIT_EXPORT_PATH GDSGATE_AUDIT_INVENTORY_KEY_PATH GDSGATE_AUDIT_REVOCATION_KEY_PATH GDSGATE_AUTH_ADDR GDSGATE_AUTH_ENROLL_ADDR GDSGATE_CA_ROTATION_CHECK_SECS GDSGATE_CA_ROTATION_ENABLED GDSGATE_CA_ROTATION_INTERVAL_SECS GDSGATE_CA_ROTATION_PROACTIVE_SECS GDSGATE_CA_ROTATION_PROPAGATION_SECS GDSGATE_CA_ROTATION_RETIRE_SECS GDSGATE_CLIENT_ALLOW_INSECURE_HTTP GDSGATE_CLIENT_TRANSPORT_CA GDSGATE_CLIENT_TRANSPORT_SNI GDSGATE_CONNECTOR_AUTH_TRANSPORT GDSGATE_CONNECTOR_ID GDSGATE_ENROLL_ENDPOINT GDSGATE_ENROLL_NODE_NAME GDSGATE_ENROLL_RENEW_ENDPOINT GDSGATE_ENROLL_STATE_DIR GDSGATE_ENROLL_TOKEN GDSGATE_HA_ENABLED GDSGATE_HA_LEASE_TTL_SECS GDSGATE_HA_OWNER GDSGATE_HA_RENEW_SECS GDSGATE_IDENTITY_ALLOW_SYSTEM_GROUPS GDSGATE_IDENTITY_MAX_GROUPS GDSGATE_IDENTITY_MAX_LENGTH GDSGATE_OIDC_ALLOW_INSECURE_HTTP GDSGATE_OIDC_AUDIENCE GDSGATE_OIDC_CLIENT_ID GDSGATE_OIDC_ISSUER GDSGATE_OIDC_JWKS_REFRESH_SECS GDSGATE_OIDC_REQUEST_TIMEOUT_SECS GDSGATE_POLICY_PATH GDSGATE_PROFILE GDSGATE_PROXY_INTERNAL_ADDR GDSGATE_PROXY_JOIN_ADDR GDSGATE_PROXY_PUBLIC_ADDR GDSGATE_PROXY_SINGLE_PORT GDSGATE_PROXY_WS_ADDR GDSGATE_STORE_AUTO_MIGRATE GDSGATE_STORE_PASSWORD_FILE GDSGATE_STORE_URL GDSGATE_TELEMETRY_METRICS_LISTEN GDSGATE_TELEMETRY_OTEL_ENDPOINT
| GDSGATE_ADMIN_ENDPOINT | admin.endpoint |
| GDSGATE_ADMIN_IDENTITY_DIR | admin.identity_dir |
| GDSGATE_ADMIN_TRANSPORT | admin.transport |
A few client-only variables are not config overrides but switches:
| Variable | Purpose |
|---|---|
GDSGATE_ID_TOKEN |
Identity token a client command should present (headless / CI). |
GDSGATE_USER |
Local-dev principal name when no [oidc] is configured. |
RUST_LOG |
Log filter. Default warn,gdsgate=info: gdsgate* at INFO, everything else at WARN. A set value replaces the default. |
The [[connector.backends]] list is structured data and has no environment
override; it is file-only.