Skip to main content

Environment Configuration

Temporal CLI and SDKs support configuring a Temporal Client using environment variables and TOML configuration files, rather than setting connection options programmatically in your code. This decouples connection settings from application logic, making it easier to manage different environments such as development, staging, and production without code changes.

SUPPORT, STABILITY, and DEPENDENCY INFO

This feature is currently in Pre-release in the Go and Python Temporal SDKs, as well as the Temporal CLI.

Configuration methods

You can configure your client using a TOML file, environment variables, or a combination of both. The configuration is loaded with a specific order of precedence:

  1. Environment variables: These have the highest precedence. If an environment variable defines a setting, it will always override any value set in a configuration file. This makes it easy to provide secrets in dynamic environments.
  2. TOML configuration file: A TOML file can be used to define one or more configuration profiles. This file is located by checking the following sources in order:
    1. The path specified by the TEMPORAL_CONFIG_FILE environment variable.
    2. The default configuration path: ~/.config/temporalio/temporal.toml (or the equivalent standard user config directory on your OS).

Configuration profiles

You can use configuration profiles to maintain separate configurations within a single file for different environments. The Temporal client uses the default profile unless you specify another via the TEMPORAL_PROFILE environment variable or in the SDK's load options. If a requested profile doesn't exist, the application will return an error.

Configuration settings

The following table details all available settings, their corresponding environment variables, and their TOML file paths.

SettingEnvironment VariableTOML PathDescription
Configuration File PathTEMPORAL_CONFIG_FILENAPath to the TOML configuration file
Server AddressTEMPORAL_ADDRESSprofile.<name>.addressThe host and port of the Temporal Frontend service (e.g., "localhost:7233").
NamespaceTEMPORAL_NAMESPACEprofile.<name>.namespaceThe Temporal Namespace to connect to.
API KeyTEMPORAL_API_KEYprofile.<name>.api_keyAn API key for authentication. If present, TLS is enabled by default.
Enable/Disable TLSTEMPORAL_TLSprofile.<name>.tls.disabledSet to "true" to enable TLS, "false" to disable. In TOML, disabled = true turns TLS off.
Client CertificateTEMPORAL_TLS_CLIENT_CERT_DATAprofile.<name>.tls.client_cert_dataThe 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.<name>.tls.client_cert_path.
Client Certificate PathTEMPORAL_TLS_CLIENT_CERT_PATHprofile.<name>.tls.client_cert_pathA 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.<name>.tls.client_cert_data.
Client KeyTEMPORAL_TLS_CLIENT_KEY_DATAprofile.<name>.tls.client_key_dataThe 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.<name>.tls.client_key_path.
Client Key PathTEMPORAL_TLS_CLIENT_KEY_PATHprofile.<name>.tls.client_key_pathA 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.<name>.tls.client_key_data.
Server CA CertTEMPORAL_TLS_SERVER_CA_CERT_DATAprofile.<name>.tls.server_ca_cert_dataThe 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.<name>.tls.server_ca_cert_path.
Server CA Cert PathTEMPORAL_TLS_SERVER_CA_CERT_PATHprofile.<name>.tls.server_ca_cert_pathA 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.<name>.tls.server_ca_cert_data.
TLS Server NameTEMPORAL_TLS_SERVER_NAMEprofile.<name>.tls.server_nameOverrides the server name used for Server Name Indication (SNI) in the TLS handshake.
Disable Host VerificationTEMPORAL_TLS_DISABLE_HOST_VERIFICATIONprofile.<name>.tls.disable_host_verificationA boolean to disable server hostname verification. Use with caution. Not supported by all SDKs.
Codec EndpointTEMPORAL_CODEC_ENDPOINTprofile.<name>.codec.endpointThe 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 AuthTEMPORAL_CODEC_AUTHprofile.<name>.codec.authThe authorization header value for the remote data converter.
gRPC MetadataTEMPORAL_GRPC_META_*profile.<name>.grpc_metaSets gRPC headers. The part after _META_ becomes the header key (e.g., _SOME_KEY -> some-key).

TOML Configuration Example

Here is an example temporal.toml file that defines two profiles: default for local development and prod for production.

# Default profile for local development
[profile.default]
address = "localhost:7233"
namespace = "default"

# Optional: Add custom gRPC headers
[profile.default.grpc_meta]
my-custom-header = "development-value"
trace-id = "dev-trace-123"

# Production profile for Temporal Cloud
[profile.prod]
address = "your-namespace.a1b2c.tmprl.cloud:7233"
namespace = "your-namespace"
api_key = "your-api-key-here"

# TLS configuration for production
[profile.prod.tls]
# TLS is auto-enabled when this TLS config or API key is present, but you can configure it explicitly
# disabled = false
# Use certificate files for mTLS
client_cert_path = "/etc/temporal/certs/client.pem"
client_key_path = "/etc/temporal/certs/client.key"

# Custom headers for production
[profile.prod.grpc_meta]
environment = "production"
service-version = "v1.2.3"

# Staging profile with inline certificate data
[profile.staging]
address = "staging.temporal.example.com:7233"
namespace = "staging"

[profile.staging.tls]
# Example of providing certificate data directly (base64 or PEM format)
client_cert_data = """-----BEGIN CERTIFICATE-----
MIICertificateDataHere...
-----END CERTIFICATE-----"""
client_key_data = """-----BEGIN PRIVATE KEY-----
MIIPrivateKeyDataHere...
-----END PRIVATE KEY-----"""

CLI Integration

The Temporal CLI tool includes temporal config commands that allow you to read and write to the TOML configuration file. This provides a convenient way to manage your connection profiles without manually editing the file.

  • temporal config get <property>: Reads a specific value from the current profile.
  • temporal config set <property> <value>: Sets a property in the current profile.
  • temporal config delete <property>: Deletes a property from the current profile.
  • temporal config list: Lists all available profiles in the config file.

These CLI commands directly manipulate the temporal.toml file. This differs from the SDKs, which only read from the file and environment at runtime to establish a client connection. The CLI is a tool for managing the configuration source, while the SDKs are consumers of that configuration. You can select a profile for the CLI to use with the --profile flag (for example, temporal --profile prod ...).

CLI Usage Example

# Set a specific property for the current profile
temporal config set --prop address --value "prod.temporal.io:7233"

# Delete a property for the current profile
temporal config delete --prop tls.client_cert_path

# Get a specific property for the current profile
temporal config get --prop address

# Get all settings for the current profile
temporal config get

# Use a specific profile
temporal --profile prod config get --prop address

# List all profiles
temporal config list

# Connect to a client with the default profile, list its workflows
temporal workflow list

# Connect to a client with the 'prod' profile, list its workflows
temporal --profile prod workflow list

# Start a workflow using the 'prod' profile
temporal --profile prod workflow start \
--type YourWorkflow \
--task-queue your-task-queue \
--input '"your-workflow-input"'

Load the default profile and environment variables

If you don't specify a profile, the SDKs load the default profile and the environment variables.

No matter what profile you choose to load, environment variables are always loaded when you use the APIs in the envconfig package to load Temporal Client connection options. They always take precedence over TOML file settings in the profile.

package main

import (
"fmt"
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)

func main() {
// Loads the "default" profile from the standard location and environment variables.
c, err := client.Dial(envconfig.MustLoadDefaultClientOptions())
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer c.Close()

fmt.Printf("✅ Connected to Temporal namespace %q on %s\n", c.Options().Namespace, c.Options().HostPort)
}

Load configuration from a custom filepath

To load configuration from a non-standard file location without relying on the TEMPORAL_CONFIG_FILE environment variable, you can use a function from the temporalio.envconfig package. The specific method you need to call depends on the SDK you are using.

This is useful if you store application-specific configurations separately. Loading connection options using this method will still respect environment variables, which take precedence over the file settings.

package main

import (
"fmt"
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)

func main() {
// Load a specific profile from the TOML config file.
// This requires a [profile.prod] section in your config.
opts, err := envconfig.LoadClientOptions(envconfig.LoadClientOptionsRequest{
ConfigFileProfile: "prod",
})
if err != nil {
log.Fatalf("Failed to load 'prod' profile: %v", err)
}

c, err := client.Dial(opts)
if err != nil {
log.Fatalf("Failed to connect using 'prod' profile: %v", err)
}
defer c.Close()

fmt.Printf("✅ Connected to Temporal namespace %q on %s using 'prod' profile\n", c.Options().Namespace, c.Options().HostPort)
}

Override configuration programmatically

You can also load a base configuration and then override specific settings programmatically in your code. The loaded configuration is a dictionary, so you can modify it before passing it to Client.connect().

import asyncio
from temporalio.client import Client
from temporalio.envconfig import ClientConfig

async def main():
# Load the default profile configuration.
connect_config = ClientConfig.load_client_connect_config()

# Apply custom configuration overrides.
print("Applying custom configuration overrides...")
connect_config["target_host"] = "localhost:7233"
connect_config["namespace"] = "test-namespace"

# Connect to the client using the modified configuration.
client = await Client.connect(**connect_config)
print(f"✅ Client connected to {client.target} in namespace '{client.namespace}'")

if __name__ == "__main__":
asyncio.run(main())

SDK Usage Example (Go)

The following Go examples demonstrate how to use envconfig to load configuration from different sources to connect a client.

Load the default profile

The most common use case is to load the "default" profile from environment variables and the default TOML file location (~/.config/temporalio/temporal.toml). The envconfig.MustLoadDefaultClientOptions() function handles this automatically. Any TEMPORAL_* environment variables will override settings from the TOML file.

package main

import (
"fmt"
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)

func main() {
// Loads the "default" profile from the standard location and environment variables.
c, err := client.Dial(envconfig.MustLoadDefaultClientOptions())
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer c.Close()

fmt.Printf("✅ Connected to Temporal namespace %q on %s\n", c.Options().Namespace, c.Options().HostPort)
}

Load a specific profile by name

If your TOML configuration file contains multiple profiles, you can select one by passing its name in envconfig.LoadClientOptionsRequest.

package main

import (
"fmt"
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)

func main() {
// Load a specific profile from the TOML config file.
// This requires a [profile.prod] section in your config.
opts, err := envconfig.LoadClientOptions(envconfig.LoadClientOptionsRequest{
ConfigFileProfile: "prod",
})
if err != nil {
log.Fatalf("Failed to load 'prod' profile: %v", err)
}

c, err := client.Dial(opts)
if err != nil {
log.Fatalf("Failed to connect using 'prod' profile: %v", err)
}
defer c.Close()

fmt.Printf("✅ Connected to Temporal namespace %q on %s using 'prod' profile\n", c.Options().Namespace, c.Options().HostPort)
}

Load configuration from a custom file path

To load configuration from a non-standard file location, specify the path in envconfig.LoadClientOptionsRequest. This is useful if you store application-specific configurations separately.

package main

import (
"fmt"
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)

func main() {
// Replace with the actual path to your TOML file.
configFilePath := "/Users/yourname/.config/my-app/temporal.toml"

opts, err := envconfig.LoadClientOptions(envconfig.LoadClientOptionsRequest{
ConfigFilePath: configFilePath,
})
if err != nil {
log.Fatalf("Failed to load client config from custom file: %v", err)
}

c, err := client.Dial(opts)
if err != nil {
log.Fatalf("Failed to connect using custom config file: %v", err)
}
defer c.Close()

fmt.Printf("✅ Connected using custom config at: %s\n", configFilePath)
}

Override configuration programmatically

You can also load a base configuration and then override specific settings programmatically in your code. The loaded client.Options struct can be modified before passing it to client.Dial().

package main

import (
"fmt"
"log"

"go.temporal.io/sdk/client"
"go.temporal.io/sdk/contrib/envconfig"
)

func main() {
// Load the base configuration (e.g., from the default profile).
opts := envconfig.MustLoadDefaultClientOptions()

// Apply overrides programmatically.
opts.HostPort = "localhost:7233"
opts.Namespace = "test-namespace"

c, err := client.Dial(opts)
if err != nil {
log.Fatalf("Failed to connect with overridden options: %v", err)
}
defer c.Close()

fmt.Printf("✅ Connected with overridden config to: %s in namespace: %s\n", opts.HostPort, opts.Namespace)
}