Skip to main content
  1. Docs
  2. Secrets & Configuration
  3. Get Started

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

    1. Create a Pulumi account at app.pulumi.com
    2. 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:

    1. Log in to Pulumi Cloud:

      pulumi login
      

      You’ll be prompted to log in via your browser or with an access token. Follow the instructions to authenticate.

    2. Open Pulumi Cloud and log in

    3. Select Environments in the left navigation

    4. Select + Create Environment

    5. Choose New Environment

    6. For Project name, enter: my-project

    7. For Environment name, enter: dev

    8. Select Create Environment

    9. 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-123
      

      This defines two values: region (a plaintext value) and apiKey (a secret value, denoted with fn::secret).

    10. Select Save

      ESC automatically encrypts the secret value. If you reopen the environment definition, the plaintext demo-secret-123 has been replaced with ciphertext, while region remains 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

    1. Open Pulumi Cloud and select Environments in the left navigation
    2. Select your my-project/dev environment to open it
    3. 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.

    ESC requires the Pulumi Cloud backend. Importing an ESC environment into a stack works only for Pulumi stacks that use Pulumi Cloud as their state backend. Stacks stored in self-managed backends (such as S3, Azure Blob Storage, or the local filesystem) can’t reference ESC environments.

    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