diff --git a/.github/workflows/env-config-drift.yml b/.github/workflows/env-config-drift.yml new file mode 100644 index 0000000000..b5f7779ca9 --- /dev/null +++ b/.github/workflows/env-config-drift.yml @@ -0,0 +1,44 @@ +name: 'Environment config drift' + +# The environment variable table in the client environment configuration +# reference is hand-written, but the variables it documents live in six other +# repositories. This job reports when the table and those sources disagree. +# +# It runs on a schedule rather than per PR because it fetches sources over the +# network: a GitHub outage should not block unrelated documentation PRs. It also +# runs on demand, and on PRs that touch the reference page or the checker itself. +on: + schedule: + # Mondays at 15:00 UTC. + - cron: '0 15 * * 1' + workflow_dispatch: + pull_request: + paths: + - 'docs/references/client-environment-configuration.mdx' + - 'bin/check-env-config-table.js' + - '.github/workflows/env-config-drift.yml' + +permissions: + contents: read + +jobs: + check: + name: 'Compare the reference table against every implementation' + runs-on: ubuntu-latest + defaults: + run: + shell: bash + + steps: + - name: Checkout + uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 + with: + persist-credentials: false + + - name: Setup Node + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version: 24 + + - name: Check for drift + run: node bin/check-env-config-table.js diff --git a/bin/check-env-config-table.js b/bin/check-env-config-table.js new file mode 100644 index 0000000000..86972f4fc4 --- /dev/null +++ b/bin/check-env-config-table.js @@ -0,0 +1,323 @@ +#!/usr/bin/env node +/** + * Checks the environment variable table in the client environment configuration + * reference against the implementations that actually read those variables. + * + * Each SDK implements environment variable loading independently, as does the + * CLI, and nothing publishes a machine-readable list. So this script extracts the + * variable names from each implementation's source and compares them against the + * docs table. + * + * The implementations are the authority here. temporalio/proposals has a design + * document (all-sdk/external-client-configuration.md) that describes an intended + * naming rule, but it is a proposal: it does not always match what shipped, and + * it should not be used to justify documented behavior. + * + * It reports drift; it does not rewrite the page. Descriptions and wording stay + * hand-maintained. + * + * Usage: + * node bin/check-env-config-table.js # fetch sources from GitHub + * node bin/check-env-config-table.js --json # machine-readable output + * + * Exit codes: 0 no drift, 1 drift found, 2 could not run (network, parse). + */ + +const fs = require("fs"); +const path = require("path"); + +const DOCS_PAGE = path.join( + __dirname, + "..", + "docs", + "references", + "client-environment-configuration.mdx" +); + +// Every client the Supported by column can name. "All" expands to this set. +const ALL_CLIENTS = ["Go", "Java", "Python", "TypeScript", ".NET", "Ruby", "CLI"]; + +// The table says "Temporal CLI" for readability; sources label it "CLI". +const CLIENT_ALIASES = { "Temporal CLI": "CLI" }; + +// Implementations that read environment variables directly. `label` is the token +// expected in the docs "Supported by" column. +// +// Python, .NET, and Ruby do not implement env var loading themselves. They call +// into Rust core through their bridges, so they inherit core's set: +// sdk-python temporalio/envconfig.py -> temporalio.bridge...envconfig +// sdk-dotnet ClientEnvConfig.cs -> Bridge.EnvConfig +// sdk-ruby lib/temporalio/env_config.rb -> Internal::Bridge::EnvConfig +// Go, Java, TypeScript, and the CLI each read variables directly, so they are +// listed as their own sources instead. TypeScript in particular reads process.env +// in packages/envconfig/src/envconfig-toml.ts rather than going through core, so +// it must not inherit core's set. +const SOURCES = [ + { + label: "Go", + repo: "temporalio/sdk-go", + ref: "main", + files: ["contrib/envconfig/client_config_load.go"], + }, + { + label: "Core", + repo: "temporalio/sdk-rust", + ref: "main", + files: ["crates/common/src/envconfig.rs"], + }, + { + label: "TypeScript", + repo: "temporalio/sdk-typescript", + ref: "main", + files: ["packages/envconfig/src/envconfig-toml.ts"], + }, + { + label: "Java", + repo: "temporalio/sdk-java", + ref: "main", + files: [ + "temporal-envconfig/src/main/java/io/temporal/envconfig/ClientConfigProfile.java", + "temporal-envconfig/src/main/java/io/temporal/envconfig/ClientConfig.java", + "temporal-envconfig/src/main/java/io/temporal/envconfig/LoadClientConfigProfileOptions.java", + ], + }, + { + label: "CLI", + repo: "temporalio/cli", + ref: "main", + // option-sets.yaml carries implied-env mappings; client.go reads the legacy + // TLS variables that have no flag of their own. + files: ["cliext/option-sets.yaml", "cliext/client.go"], + }, +]; + +const DELEGATES_TO_CORE = ["Python", ".NET", "Ruby"]; + +// Variables that appear in source as a prefix scan rather than a fixed name. +// TEMPORAL_GRPC_META_ is matched by prefix, so extraction sees the stem. +const PREFIX_VARS = { TEMPORAL_GRPC_META_: "TEMPORAL_GRPC_META_*" }; + +// Test fixtures and doc comments mention variables that are not read. Extraction +// is deliberately broad, so drop names that are only ever examples. +const NOT_A_REAL_VARIABLE = /^TEMPORAL_GRPC_META_SOME/; + +function extractVariables(text) { + const found = new Set(); + for (const match of text.matchAll(/TEMPORAL_[A-Z0-9_]+/g)) { + let name = match[0]; + if (NOT_A_REAL_VARIABLE.test(name)) continue; + if (PREFIX_VARS[name]) name = PREFIX_VARS[name]; + found.add(name); + } + return found; +} + +async function fetchSource({ repo, ref, files }) { + const texts = []; + for (const file of files) { + const url = `https://raw.githubusercontent.com/${repo}/${ref}/${file}`; + const res = await fetch(url); + if (!res.ok) { + throw new Error(`${url} returned ${res.status}`); + } + texts.push(await res.text()); + } + return texts.join("\n"); +} + +/** + * Reads the variable rows out of the docs table. Expects a Markdown table whose + * first column is a backticked variable name and which has a "Supported by" + * column. Returns a Map of variable name to the set of support tokens. + */ +function parseDocsTable(mdx) { + const lines = mdx.split("\n"); + const rows = new Map(); + let tablesFound = 0; + + // The page has several tables (client settings, plus CLI-only groups). Every + // table with these columns contributes rows. + for (let i = 0; i < lines.length; i++) { + if (!(lines[i].includes("| Variable") && /supported by/i.test(lines[i]))) continue; + tablesFound++; + + const columns = lines[i].split("|").map((c) => c.trim().toLowerCase()); + const varCol = columns.findIndex((c) => c === "variable"); + const supportCol = columns.findIndex((c) => c === "supported by"); + + for (let j = i + 2; j < lines.length; j++) { + if (!lines[j].trim().startsWith("|")) break; + const cells = lines[j].split("|").map((c) => c.trim()); + const name = (cells[varCol] || "").replace(/`/g, "").trim(); + if (!name.startsWith("TEMPORAL_")) continue; + rows.set(name, parseSupportCell(cells[supportCol] || "")); + i = j; + } + } + + if (tablesFound === 0) { + return { rows: null, reason: 'no table with "Variable" and "Supported by" columns' }; + } + return { rows }; +} + +/** + * Reads a "Supported by" cell into a set of client names. Accepts an explicit + * list ("Go, Java"), "All", or "All except Go, Java". + */ +function parseSupportCell(cell) { + const text = cell.replace(/`/g, "").trim(); + if (!text) return new Set(); + + const canonical = (s) => { + const trimmed = s.trim(); + return CLIENT_ALIASES[trimmed] || trimmed; + }; + + const except = text.match(/^All\s+except\s+(.+)$/i); + if (except) { + const excluded = new Set(except[1].split(",").map(canonical)); + return new Set(ALL_CLIENTS.filter((c) => !excluded.has(c))); + } + if (/^All$/i.test(text)) return new Set(ALL_CLIENTS); + + return new Set(text.split(",").map(canonical).filter(Boolean)); +} + +/** Expands source labels into the SDK tokens the docs table uses. */ +function expandSupport(labels) { + const expanded = new Set(); + for (const label of labels) { + if (label === "Core") { + for (const sdk of DELEGATES_TO_CORE) expanded.add(sdk); + } else { + expanded.add(label); + } + } + return expanded; +} + +function setDiff(a, b) { + return [...a].filter((x) => !b.has(x)).sort(); +} + +async function main() { + const asJson = process.argv.includes("--json"); + + if (!fs.existsSync(DOCS_PAGE)) { + console.error(`[env-config-check] docs page not found: ${DOCS_PAGE}`); + process.exit(2); + } + + // variable name -> Set of source labels that read it + const supportBySource = new Map(); + for (const source of SOURCES) { + let text; + try { + text = await fetchSource(source); + } catch (err) { + console.error( + `[env-config-check] could not read ${source.repo}: ${err.message}` + ); + process.exit(2); + } + for (const name of extractVariables(text)) { + if (!supportBySource.has(name)) supportBySource.set(name, new Set()); + supportBySource.get(name).add(source.label); + } + } + + // --dump prints what the sources say, for building or auditing the table by hand. + if (process.argv.includes("--dump")) { + for (const name of [...supportBySource.keys()].sort()) { + const where = [...expandSupport(supportBySource.get(name))].sort().join(", "); + console.log(`${name}\t${where}`); + } + process.exit(0); + } + + const mdx = fs.readFileSync(DOCS_PAGE, "utf-8"); + const { rows, reason } = parseDocsTable(mdx); + if (!rows) { + console.error(`[env-config-check] could not parse the docs table: ${reason}`); + process.exit(2); + } + + const sourceVars = new Set(supportBySource.keys()); + const docsVars = new Set(rows.keys()); + + const missingFromDocs = setDiff(sourceVars, docsVars); + const missingFromSources = setDiff(docsVars, sourceVars); + + const supportMismatches = []; + for (const [name, documented] of rows) { + if (!supportBySource.has(name)) continue; + const expected = expandSupport(supportBySource.get(name)); + // An empty or prose-only cell is treated as unverified rather than wrong. + if (documented.size === 0) continue; + const unexpected = setDiff(documented, expected); + const unlisted = setDiff(expected, documented); + if (unexpected.length || unlisted.length) { + supportMismatches.push({ variable: name, unlisted, unexpected }); + } + } + + const result = { + missingFromDocs, + missingFromSources, + supportMismatches, + checked: { + variablesInSources: sourceVars.size, + variablesInDocs: docsVars.size, + sources: SOURCES.map((s) => `${s.repo}@${s.ref}`), + }, + }; + + if (asJson) { + console.log(JSON.stringify(result, null, 2)); + } else { + report(result, supportBySource); + } + + const drifted = + missingFromDocs.length || missingFromSources.length || supportMismatches.length; + process.exit(drifted ? 1 : 0); +} + +function report({ missingFromDocs, missingFromSources, supportMismatches, checked }, supportBySource) { + console.log( + `[env-config-check] ${checked.variablesInSources} variables across ${checked.sources.length} sources, ${checked.variablesInDocs} in the docs table\n` + ); + + if (missingFromDocs.length) { + console.log("Read by an implementation but absent from the docs table:"); + for (const name of missingFromDocs) { + const where = [...expandSupport(supportBySource.get(name))].sort().join(", "); + console.log(` ${name} (${where})`); + } + console.log(""); + } + + if (missingFromSources.length) { + console.log("In the docs table but read by no implementation:"); + for (const name of missingFromSources) console.log(` ${name}`); + console.log(""); + } + + if (supportMismatches.length) { + console.log('"Supported by" disagrees with the sources:'); + for (const { variable, unlisted, unexpected } of supportMismatches) { + const parts = []; + if (unlisted.length) parts.push(`missing ${unlisted.join(", ")}`); + if (unexpected.length) parts.push(`claims ${unexpected.join(", ")} but no source reads it`); + console.log(` ${variable}: ${parts.join("; ")}`); + } + console.log(""); + } + + if (!missingFromDocs.length && !missingFromSources.length && !supportMismatches.length) { + console.log("[env-config-check] OK: docs table matches every implementation."); + } +} + +main(); diff --git a/docs/cli/setup-cli.mdx b/docs/cli/setup-cli.mdx index d8ab988967..9ab736460a 100644 --- a/docs/cli/setup-cli.mdx +++ b/docs/cli/setup-cli.mdx @@ -171,25 +171,12 @@ This setting makes created Search Attributes immediately available. ### Environment variables -The following table describes the environment variables you can set for the Temporal CLI. - -{/* This is an automatically generated file and the TEMPORAL_API_KEY correction will disappear on the next push. */} - -| Variable | Definition | Client Option | -| ---------------------------------------- | ------------------------------------------------------------------------- | ------------------------------- | -| `TEMPORAL_ADDRESS` | Host and port (formatted as host:port) for the Temporal Frontend Service. | --address | -| `TEMPORAL_CODEC_AUTH` | Authorization header for requests to Codec Server. | --codec-auth | -| `TEMPORAL_CODEC_ENDPOINT` | Endpoint for remote Codec Server. | --codec-endpoint | -| `TEMPORAL_NAMESPACE` | Namespace in Temporal Workflow. Default: "default". | --namespace | -| `TEMPORAL_TLS_CA` | Path to server CA certificate. | --tls-ca-path | -| `TEMPORAL_TLS_CERT` | Path to x509 certificate. | --tls-cert-path | -| `TEMPORAL_TLS_DISABLE_HOST_VERIFICATION` | Turns off TLS host name verification. Default: false. | --tls-disable-host-verification | -| `TEMPORAL_TLS_KEY` | Path to private certificate key. | --tls-key-path | -| `TEMPORAL_TLS_SERVER_NAME` | Override for target TLS server name. | --tls-server-name | -| `TEMPORAL_API_KEY` | API key used for authentication. | --api-key | - -{/* This is an automatically generated file and this caution will disappear on the next push. */} -{/* issue: https://github.com/temporalio/cli/issues/776 */} +You can configure the CLI with environment variables instead of passing flags on every command. Setting an environment +variable is not the same as storing a preset with [`temporal env`](/cli/command-reference/env): an environment variable +configures the CLI process, while `temporal env` writes named key-value presets to a file. + +For every variable the CLI reads, its equivalent flag, and its TOML configuration key, refer to +[Environment configuration](/references/client-environment-configuration). ### Create and modify configuration files diff --git a/docs/references/client-environment-configuration.mdx b/docs/references/client-environment-configuration.mdx new file mode 100644 index 0000000000..35599918a2 --- /dev/null +++ b/docs/references/client-environment-configuration.mdx @@ -0,0 +1,79 @@ +--- +id: client-environment-configuration +title: Environment configuration +sidebar_label: Environment configuration +description: Reference for the environment variables that configure Temporal Clients, including the Temporal CLI. +tags: + - Temporal Client + - Configuration + - Environment Variables + - TOML +--- + +This page lists every environment variable that configures a Temporal Client, along with its TOML configuration key, +the equivalent Temporal CLI flag, and which clients read it. The Temporal CLI is a Temporal Client, so its variables +are included here. + +For how to use these variables and configuration files together, refer to +[Environment configuration](/develop/environment-configuration). + +Environment variables always take precedence over values in a TOML configuration file. An explicitly passed CLI flag +takes precedence over the matching environment variable. + +The Supported by column records which clients read a variable. Where a client reads a variable but applies it with +caveats, the description says so. + +## Client settings + +| Variable | TOML key | CLI flag | Supported by | Description | +| :------- | :------- | :------- | :----------- | :---------- | +| `TEMPORAL_CONFIG_FILE` | NA | `--config-file` | All | Path to the TOML configuration file. Defaults to `temporal.toml` in a platform-specific directory. | +| `TEMPORAL_PROFILE` | NA | `--profile` | All | Name of the configuration profile to load. Defaults to `default`. | +| `TEMPORAL_ADDRESS` | `profile..address` | `--address` | All | Host and port of the Temporal Frontend Service, such as `localhost:7233`. | +| `TEMPORAL_NAMESPACE` | `profile..namespace` | `--namespace` | All | Temporal Namespace to connect to. | +| `TEMPORAL_API_KEY` | `profile..api_key` | `--api-key` | All | API key for authentication. When set, TLS is enabled by default. | +| `TEMPORAL_TLS` | `profile..tls.disabled` | `--tls` | All | Set to `true` to enable TLS, `false` to disable it. The TOML key is inverted: `disabled = true` turns TLS off. | +| `TEMPORAL_TLS_CLIENT_CERT_PATH` | `profile..tls.client_cert_path` | `--tls-cert-path` | All | Filesystem path to the client's public TLS certificate. Cannot be combined with `TEMPORAL_TLS_CLIENT_CERT_DATA`. | +| `TEMPORAL_TLS_CLIENT_CERT_DATA` | `profile..tls.client_cert_data` | `--tls-cert-data` | All | Raw PEM data for the client's public TLS certificate. Cannot be combined with `TEMPORAL_TLS_CLIENT_CERT_PATH`. | +| `TEMPORAL_TLS_CLIENT_KEY_PATH` | `profile..tls.client_key_path` | `--tls-key-path` | All | Filesystem path to the client's private TLS key. Cannot be combined with `TEMPORAL_TLS_CLIENT_KEY_DATA`. | +| `TEMPORAL_TLS_CLIENT_KEY_DATA` | `profile..tls.client_key_data` | `--tls-key-data` | All | Raw PEM data for the client's private TLS key. Cannot be combined with `TEMPORAL_TLS_CLIENT_KEY_PATH`. | +| `TEMPORAL_TLS_SERVER_CA_CERT_PATH` | `profile..tls.server_ca_cert_path` | `--tls-ca-path` | All | Filesystem path to the Certificate Authority certificate used to verify the server. Cannot be combined with `TEMPORAL_TLS_SERVER_CA_CERT_DATA`. | +| `TEMPORAL_TLS_SERVER_CA_CERT_DATA` | `profile..tls.server_ca_cert_data` | `--tls-ca-data` | All | Raw PEM data for the Certificate Authority certificate used to verify the server. Cannot be combined with `TEMPORAL_TLS_SERVER_CA_CERT_PATH`. | +| `TEMPORAL_TLS_SERVER_NAME` | `profile..tls.server_name` | `--tls-server-name` | All | Overrides the server name used for Server Name Indication (SNI) in the TLS handshake. | +| `TEMPORAL_TLS_DISABLE_HOST_VERIFICATION` | `profile..tls.disable_host_verification` | `--tls-disable-host-verification` | All | Disables server hostname verification. Use with caution. Not every SDK applies this setting. | +| `TEMPORAL_GRPC_META_*` | `profile..grpc_meta` | `--grpc-meta` | All | Sets gRPC headers. The part after `_META_` becomes the header key, so `TEMPORAL_GRPC_META_SOME_KEY` sets `some-key`. | +| `TEMPORAL_CODEC_ENDPOINT` | `profile..codec.endpoint` | `--codec-endpoint` | All except Java | Endpoint for a remote Codec Server. SDKs that support this setting do not apply it by default. Intended mostly for CLI use. | +| `TEMPORAL_CODEC_AUTH` | `profile..codec.auth` | `--codec-auth` | All except Java | Authorization header value for the remote Codec Server. | +| `TEMPORAL_CLIENT_AUTHORITY` | `profile..authority` | NA | Go | Overrides the `:authority` gRPC header. Currently a Go SDK extension with no equivalent in other clients. | + +## Temporal CLI settings + +The Temporal CLI reads the variables below in addition to the client settings above. No other client reads them. + +### `temporal env` preset variables + +The CLI supports a second configuration mechanism alongside TOML configuration files. `temporal env` stores named +key-value presets in `temporal.yaml`, and the variables below select which preset the CLI reads. No SDK reads them. + +Both mechanisms work. The `temporal config` command that manages TOML configuration files is currently experimental, +while `temporal env` is not. + +| Variable | TOML key | CLI flag | Supported by | Description | +| :------- | :------- | :------- | :----------- | :---------- | +| `TEMPORAL_ENV` | NA | `--env` | Temporal CLI | Name of the active `temporal env` preset. Defaults to `default`. | +| `TEMPORAL_ENV_FILE` | NA | `--env-file` | Temporal CLI | Path to the preset file. Defaults to `temporal.yaml` in the CLI configuration directory. | + +### Legacy TLS variables + +The CLI reads an older set of TLS variable names for compatibility. When any of them is set, it overrides the +corresponding value from the configuration file and from the preferred variable. These names have no CLI flag of their +own, and no SDK reads them. + +| Variable | TOML key | CLI flag | Supported by | Description | +| :------- | :------- | :------- | :----------- | :---------- | +| `TEMPORAL_TLS_CERT` | NA | NA | Temporal CLI | Superseded by `TEMPORAL_TLS_CLIENT_CERT_PATH`. | +| `TEMPORAL_TLS_CERT_DATA` | NA | NA | Temporal CLI | Superseded by `TEMPORAL_TLS_CLIENT_CERT_DATA`. | +| `TEMPORAL_TLS_KEY` | NA | NA | Temporal CLI | Superseded by `TEMPORAL_TLS_CLIENT_KEY_PATH`. | +| `TEMPORAL_TLS_KEY_DATA` | NA | NA | Temporal CLI | Superseded by `TEMPORAL_TLS_CLIENT_KEY_DATA`. | +| `TEMPORAL_TLS_CA` | NA | NA | Temporal CLI | Superseded by `TEMPORAL_TLS_SERVER_CA_CERT_PATH`. | +| `TEMPORAL_TLS_CA_DATA` | NA | NA | Temporal CLI | Superseded by `TEMPORAL_TLS_SERVER_CA_CERT_DATA`. | diff --git a/docs/references/client-envrionment-configuration.mdx b/docs/references/client-envrionment-configuration.mdx deleted file mode 100644 index 9f2c16949a..0000000000 --- a/docs/references/client-envrionment-configuration.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -id: client-environment-configuration -title: Environment configuration -sidebar_label: Environment configuration -description: Reference for configuring Temporal Clients using environment variables and TOML configuration files. -tags: - - Temporal Client - - Configuration - - Environment Variables - - TOML ---- - -The following table details all available settings, their corresponding environment variables, and their TOML file -paths. For more information on using environment variables and configuration files to set up your Temporal Client, refer -to the [Environment Configuration](/develop/environment-configuration). - -| Setting | Environment Variable | TOML Path | Description | -| :------------------------ | :--------------------------------------- | :--------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Configuration File Path | `TEMPORAL_CONFIG_FILE` | **NA** | Path to the TOML configuration file | -| Server Address | `TEMPORAL_ADDRESS` | `profile..address` | The host and port of the Temporal Frontend service (e.g., "localhost:7233"). | -| Namespace | `TEMPORAL_NAMESPACE` | `profile..namespace` | The Temporal Namespace to connect to. | -| API Key | `TEMPORAL_API_KEY` | `profile..api_key` | An API key for authentication. If present, TLS is enabled by default. | -| Enable/Disable TLS | `TEMPORAL_TLS` | `profile..tls.disabled` | Set to "true" to enable TLS, "false" to disable. In TOML, disabled = true turns TLS off. | -| Client Certificate | `TEMPORAL_TLS_CLIENT_CERT_DATA` | `profile..tls.client_cert_data` | The raw PEM data containing the client's public TLS certificate. Alternatively, you can use `TEMPORAL_TLS_CLIENT_CERT_PATH` to provide a path to the certificate or the TOML `profile..tls.client_cert_path`. | -| Client Certificate Path | `TEMPORAL_TLS_CLIENT_CERT_PATH` | `profile..tls.client_cert_path` | A filesystem path to the client's public TLS certificate. Alternatively, you can provide the raw PEM data using `TEMPORAL_TLS_CLIENT_CERT_DATA` or the TOML `profile..tls.client_cert_data`. | -| Client Key | `TEMPORAL_TLS_CLIENT_KEY_DATA` | `profile..tls.client_key_data` | The raw PEM data containing the client's private TLS key. Alternatively, you can use `TEMPORAL_TLS_CLIENT_KEY_PATH` to provide a path to the key or the TOML `profile..tls.client_key_path`. | -| Client Key Path | `TEMPORAL_TLS_CLIENT_KEY_PATH` | `profile..tls.client_key_path` | A filesystem path to the client's private TLS key. Alternatively, you can provide the raw PEM data using `TEMPORAL_TLS_CLIENT_KEY_DATA` or the TOML `profile..tls.client_key_data`. | -| Server CA Cert | `TEMPORAL_TLS_SERVER_CA_CERT_DATA` | `profile..tls.server_ca_cert_data` | The raw PEM data for the Certificate Authority certificate used to verify the server. Alternatively, you can use `TEMPORAL_TLS_SERVER_CA_CERT_PATH` to provide a path or the TOML `profile..tls.server_ca_cert_path`. | -| Server CA Cert Path | `TEMPORAL_TLS_SERVER_CA_CERT_PATH` | `profile..tls.server_ca_cert_path` | A filesystem path to the Certificate Authority certificate. Alternatively, you can provide the raw PEM data using `TEMPORAL_TLS_SERVER_CA_CERT_DATA` or the TOML `profile..tls.server_ca_cert_data`. | -| TLS Server Name | `TEMPORAL_TLS_SERVER_NAME` | `profile..tls.server_name` | Overrides the server name used for Server Name Indication (SNI) in the TLS handshake. | -| Disable Host Verification | `TEMPORAL_TLS_DISABLE_HOST_VERIFICATION` | `profile..tls.disable_host_verification` | A boolean to disable server hostname verification. Use with caution. Not supported by all SDKs. | -| Codec Endpoint | `TEMPORAL_CODEC_ENDPOINT` | `profile..codec.endpoint` | The endpoint for a remote Data Converter. This is not supported by all SDKs. SDKs that support this configuration don't apply it by default. Intended mostly for CLI use. | -| Codec Auth | `TEMPORAL_CODEC_AUTH` | `profile..codec.auth` | The authorization header value for the remote data converter. | -| gRPC Metadata | `TEMPORAL_GRPC_META_*` | `profile..grpc_meta` | Sets gRPC headers. The part after `_META_` becomes the header key (e.g., `_SOME_KEY` -> `some-key`). |