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.
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:
- 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.
- 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:
- The path specified by the
TEMPORAL_CONFIG_FILEenvironment variable. - The default configuration path:
~/.config/temporalio/temporal.toml(or the equivalent standard user config directory on your OS).
- The path specified by the
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.
| Setting | Environment Variable | TOML Path | Description |
|---|---|---|---|
| Configuration File Path | TEMPORAL_CONFIG_FILE | NA | Path to the TOML configuration file |
| Server Address | TEMPORAL_ADDRESS | profile.<name>.address | The host and port of the Temporal Frontend service (e.g., "localhost:7233"). |
| Namespace | TEMPORAL_NAMESPACE | profile.<name>.namespace | The Temporal Namespace to connect to. |
| API Key | TEMPORAL_API_KEY | profile.<name>.api_key | An API key for authentication. If present, TLS is enabled by default. |
| Enable/Disable TLS | TEMPORAL_TLS | profile.<name>.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.<name>.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.<name>.tls.client_cert_path. |
| Client Certificate Path | TEMPORAL_TLS_CLIENT_CERT_PATH | profile.<name>.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.<name>.tls.client_cert_data. |
| Client Key | TEMPORAL_TLS_CLIENT_KEY_DATA | profile.<name>.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.<name>.tls.client_key_path. |
| Client Key Path | TEMPORAL_TLS_CLIENT_KEY_PATH | profile.<name>.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.<name>.tls.client_key_data. |
| Server CA Cert | TEMPORAL_TLS_SERVER_CA_CERT_DATA | profile.<name>.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.<name>.tls.server_ca_cert_path. |
| Server CA Cert Path | TEMPORAL_TLS_SERVER_CA_CERT_PATH | profile.<name>.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.<name>.tls.server_ca_cert_data. |
| TLS Server Name | TEMPORAL_TLS_SERVER_NAME | profile.<name>.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.<name>.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.<name>.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.<name>.codec.auth | The authorization header value for the remote data converter. |
| gRPC Metadata | TEMPORAL_GRPC_META_* | profile.<name>.grpc_meta | Sets 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.
- Python
- Go
import asyncio
from temporalio.client import Client
from temporalio.envconfig import ClientConfigProfile
async def main():
# Load the "default" profile from default locations and environment variables.
default_profile = ClientConfigProfile.load()
connect_config = default_profile.to_client_connect_config()
# Connect to the client using the loaded configuration.
client = await Client.connect(**connect_config)
print(f"✅ Client connected to {client.service_client.config.target_host} in namespace '{client.namespace}'")
if __name__ == "__main__":
asyncio.run(main())
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, you can use the ClientConfig.load_client_connect_config()
shorthand. This is useful if you store application-specific configurations separately.
import asyncio
from pathlib import Path
from temporalio.client import Client
from temporalio.envconfig import ClientConfig
async def main():
# This file would need to exist on your filesystem.
config_file = Path.home() / ".config" / "my-app" / "temporal.toml"
# Use ClientConfig.load_client_connect_config as a convenient shorthand for
# loading a profile from a specific file and preparing it for connection.
connect_config = ClientConfig.load_client_connect_config(
config_file=str(config_file),
)
# Connect to the client using the loaded configuration.
client = await Client.connect(**connect_config)
print(f"✅ Client connected to {client.target} in namespace '{client.namespace}'")
if __name__ == "__main__":
asyncio.run(main())
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)
}