Get Started with Pulumi ESC
Pulumi ESC (Environments, Secrets, and Configuration) is a centralized secrets and configuration management service that is part of Pulumi Cloud. In this quick start, you’ll create your first environment, store a secret, retrieve it, and then consume it from a Pulumi IaC stack — the most common ESC workflow.
Prerequisites
- Create a Pulumi account at app.pulumi.com
- Install the Pulumi CLI
brew install pulumi/tap/pulumi
curl -fsSL https://get.pulumi.com | sh
choco install pulumi
See the Pulumi installation docs for more options. The pulumi env commands used in this guide ship with the Pulumi CLI, so you don’t need to install anything else.
Create your first environment
Create an environment, then store both plaintext configuration and an encrypted secret in it:
Log in to Pulumi Cloud:
pulumi loginYou’ll be prompted to log in via your browser or with an access token. Follow the instructions to authenticate.
Open Pulumi Cloud and log in
Select Environments in the left navigation
Select + Create Environment
Choose New Environment
For Project name, enter:
my-projectFor Environment name, enter:
devSelect Create Environment
In the Environment definition editor, erase the contents and replace them with the following YAML:
values: region: us-west-2 apiKey: fn::secret: demo-secret-123This defines two values:
region(a plaintext value) andapiKey(a secret value, denoted withfn::secret).Select Save
ESC automatically encrypts the secret value. If you reopen the environment definition, the plaintext
demo-secret-123has been replaced with ciphertext, whileregionremains in plaintext:values: region: us-west-2 apiKey: fn::secret: ciphertext: ZXNjeAAAAAEAAAEAFatkojHgMRjHuWIwKbPqplpSUoKCrtLUCwtU0rhJuhtOa6
Retrieve your configuration and secrets
You can retrieve all values, including decrypted secrets, from either the Pulumi Cloud console or the CLI.
Using the Pulumi Cloud console
- Open Pulumi Cloud and select Environments in the left navigation
- Select your
my-project/devenvironment to open it - The resolved values, including the decrypted
apiKey, appear in the preview pane next to the environment definition
Using the CLI
Open your environment to retrieve all values, including decrypted secrets:
pulumi env open my-project/dev
You should see output like:
{
"apiKey": "demo-secret-123",
"region": "us-west-2"
}
You’ve created an environment, stored configuration and secrets, and retrieved them. Notice that the secret is automatically decrypted when you open the environment.
Add ESC to your Pulumi stack
The most common way to use an ESC environment is to consume it from a Pulumi IaC stack, which centralizes configuration and secrets across all your stacks.
Step 1: Reference your ESC environment
In your stack configuration file (Pulumi.<stack-name>.yaml), add an environment block that references your ESC environment:
environment:
- <your-project-name>/<your-environment-name>
For example, if your ESC environment is my-project/dev:
environment:
- my-project/dev
You can also reference multiple environments, which will be merged in order (later values override earlier ones):
environment:
- my-project/common
- my-project/dev
Pin imports to a specific version. By default, Pulumi uses the @latest tag of each environment (always the most recent revision). To ensure your stack uses a known, fixed version, append a version tag or revision number with @:
environment:
- my-project/common@production
- my-project/dev@3
This prevents unexpected changes when someone updates the source environment. Learn more in Environment versioning.
Step 2: Define configuration in your ESC environment
ESC environments are YAML documents that you can edit using the CLI or Pulumi Cloud console. Use the CLI to edit your environment:
pulumi env edit my-project/dev
You can also edit environments in the Pulumi Cloud console if you prefer a visual editor.
In your ESC environment, use the pulumiConfig block to expose values to Pulumi IaC. Wrap the values you created earlier in a pulumiConfig block:
values:
pulumiConfig:
region: us-west-2
apiKey:
fn::secret: demo-secret-123
Values in pulumiConfig can be strings, numbers, booleans, or secrets (using fn::secret).
The pulumiConfig block is the bridge between ESC and Pulumi IaC. Any values you define under pulumiConfig become available in your Pulumi program through the standard Configuration API.
This allows you to centralize all your configuration and secrets in ESC while accessing them through familiar Pulumi config patterns like config.get() or config.require().
Step 3: Access configuration in your code
Use Pulumi’s standard Configuration API to access these values in your infrastructure code:
import * as pulumi from "@pulumi/pulumi";
// Create a new Pulumi Config
const config = new pulumi.Config();
// Retrieve the values of "region" and "apiKey"
const region = config.get("region");
const apiKey = config.getSecret("apiKey");
// Export values as stack output
export const Region = region;
export const ApiKey = apiKey;
import pulumi
# Import the configuration values
config = pulumi.Config()
# Retrieve the values of "region" and "apiKey"
region = config.get("region")
api_key = config.get_secret("apiKey")
# Export the values as an output
pulumi.export('Region', region)
pulumi.export("ApiKey", api_key)package main
import (
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi/config"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Create a Pulumi Config
config := config.New(ctx, "")
// Retrieve the value of "region" and "apiKey"
region := config.Get("region")
apiKey := config.GetSecret("apiKey")
// Export values as outputs
ctx.Export("Region", pulumi.String(region))
ctx.Export("ApiKey", pulumi.StringOutput(apiKey))
return nil
})
}
using Pulumi;
using System.Threading.Tasks;
using System.Collections.Generic;
class Program
{
static async Task<int> Main(string[] args)
{
return await Deployment.RunAsync(() =>
{
// Import the configuration values
var config = new Config();
// Retrieve the value of "region" and "apiKey"
var region = config.Get("region");
var apiKey = config.GetSecret("apiKey");
// Return a dictionary of outputs
return new Dictionary<string, object?>
{
["Region"] = region,
["ApiKey"] = apiKey
};
});
}
}
package myproject;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
public class App {
public static void main(String[] args) {
Pulumi.run(ctx -> {
// Create a Pulumi Config
var config = ctx.config();
// Retrieve the values of "region" and "apiKey"
var region = config.get("region");
var apiKey = config.getSecret("apiKey");
// Export the values as a stack outputs
ctx.export("Region", Output.of(region));
ctx.export("ApiKey", Output.of(apiKey));
});
}
}Your Pulumi program now retrieves configuration and secrets from ESC. Run pulumi preview or pulumi up to see it in action.
Next steps
Now that you’ve created your first environment and connected it to a stack, here’s where to go next:
- Concepts - Understand how ESC works and the full set of capabilities it offers
- Providers - Pull secrets and generate dynamic credentials from external sources like AWS, Azure, GCP, Vault, and 1Password
- Rotators - Automatically rotate credentials like API keys and database passwords on a schedule or on demand
- Integrations - Consume ESC environments from Kubernetes, the External Secrets Operator, the Secrets Store CSI Driver, and more
- Configure OpenID Connect - Set up OIDC trust so ESC can issue short-lived cloud credentials
- Integrate with Pulumi IaC - Dynamic cloud credentials, external secret stores, and environment composition in your stacks
Thank you for your feedback!
If you have a question about how to use Pulumi, reach out in Community Slack.
Open an issue on GitHub to report a problem or suggest an improvement.