1. Tutorials
  2. Managing Configuration and Secrets

Managing Configuration and Secrets

In Pulumi, each stack within your project has a settings file, and this file contains a collection of values intended to capture the configuration details needed to work with a particular environment. These can be plain-text values like server names, environment types (ex: dev, test, prod), region names and so on. They can also be sensitive values such as database passwords or service tokens.

In this tutorial, we’ll demonstrate how to create and utilize configuration and secret values in Pulumi.

In this tutorial, you'll learn:

  • How to create a plain-text configuration value
  • How to create an encrypted secret configuration value
  • How to view configuration details in the CLI
  • How to access configuration values from within Pulumi program code

Prerequisites:

Create a new project

To start, login to the Pulumi CLI. Next, create a new project by running the pulumi new <language> command, making sure to replace <language> with the supported language of your choice:

# example using python
$ pulumi new python
This command will walk you through creating a new Pulumi project.

Enter a value or leave blank to accept the (default), and press <ENTER>.
Press ^C at any time to quit.

project name (pulumi-dev):  
project description (A minimal Python Pulumi program):  
Created project 'pulumi-dev'

Please enter your desired stack name.
To create a stack in an organization, use the format <org-name>/<stack-name> (e.g. `acmecorp/dev`).
stack name (dev): pulumi/dev
Created stack 'dev'

Installing dependencies...

Creating virtual environment...
Finished creating virtual environment
Updating pip, setuptools, and wheel in virtual environment...
...
...
Finished installing dependencies

Your new project is ready to go!

To perform an initial deployment, run `pulumi up`

This will create simple Pulumi program without any resources or configuration details.

Create configuration values

In a Pulumi project, you can locally store and retrieve configuration values using the pulumi config set <key> [value] command. To demonstrate, run the following command to create a configuration value with a key of myEnvironment and a value of development:

$ pulumi config set myEnvironment development

This value will be stored in your project’s stack settings file Pulumi.<your-stack-name>.yaml as shown below:

# Contents of Pulumi.<your-stack-name>.yaml file
config:
  pulumi-dev:myEnvironment: development

You can also list the configuration values for your stack in the command line. To do so, run the pulumi config command:

$ pulumi config

KEY            VALUE
myEnvironment  development
pulumi:tags    {"pulumi:template":"python"}

To retrieve a specific configuration value, run the pulumi config get <key> command as shown below:

$ pulumi config get myEnvironment
development

Create secret values

Pulumi supports encrypting specific values as “secrets” for extra protection. Pulumi Cloud transmits and stores state files over a secure connection, but once received the files are viewable in plain-text. By encrypting secrets, Pulumi ensures that these values never appear as plain-text in your state file. By default, the encryption method uses automatic, per-stack encryption keys provided by Pulumi Cloud, but you can also use a provider of your own choosing instead.

To encrypt a configuration value before runtime, you will need to run the pulumi config set <key> [value] --secret command. To demonstrate how this works, you’ll create a configuration value named myPassword. Run the CLI command pulumi config set myPassword <value-of-password>, making sure to pass the --secret flag, and also making sure to replace <value-of-password> with an actual value as shown below:

pulumi config set myPassword demo-password-123 --secret

Now run the pulumi config command again, and you will see that, unlike the value for myEnvironment, the value for myPassword is hidden:

$ pulumi config get myEnvironment

KEY            VALUE
myEnvironment  development
myPassword     [secret]
pulumi:tags    {"pulumi:template":"python"}

If you open your project’s stack settings file (e.g. Pulumi.<your-stack-name>.yaml), you will notice that the password value is also encrypted there:

config:
  generic-python:myEnvironment: development
  generic-python:myPassword:
    secure: AAABADd5YzRaVuzxM08i5z2CJ3LGkQau5e5Lhk+1Gtj37qv6zKkFr8KxmN6X+w/XMg==

Reference values in code

Within your Pulumi program code, configuration values can be retrieved for a given stack using the following:

  • Config.get or Config.require for raw configuration values
  • Config.getSecret or Config.requireSecret for secret values
You can learn more about the difference between the get and require functions by referring to the Pulumi Configuration concept documentation.

To demonstrate, update your Pulumi program code with the following:

"use strict";
const pulumi = require("@pulumi/pulumi");

// Create a new Pulumi Config
const config = new pulumi.Config();

// Retrieve the values of "myEnvironment" and "myPassword"
const environment = config.get("myEnvironment");
const password = config.getSecret("myPassword");

// Export values as stack outputs
module.exports = {
    Environment: environment,
    Password: password,
};
import * as pulumi from "@pulumi/pulumi";

// Create a new Pulumi Config
const config = new pulumi.Config();

// Retrieve the values of "myEnvironment" and "myPassword"
const environment = config.get("myEnvironment");
const password = config.getSecret("myPassword");

// Export values as stack output
export const Environment = environment;
export const Password = password;
import pulumi

# Import the configuration values
config = pulumi.Config()

# Retrieve the values of "myEnvironment" and "myPassword"
environment = config.get("myEnvironment")
password = config.get_secret("myPassword")

# Export the values as an output
pulumi.export('Environment', environment)
pulumi.export("Password", password)
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 "myEnvironment" and "myPassword"
		environment := config.Get("myEnvironment")
		password := config.GetSecret("myPassword")

		// Export values as outputs
		ctx.Export("Environment", pulumi.String(environment))
		ctx.Export("Password", pulumi.StringOutput(password))
		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 "myEnvironment" and "myPassword"
            var environment = config.Get("myEnvironment");
            var password = config.GetSecret("myPassword");

            // Return a dictionary of outputs
            return new Dictionary<string, object?>
            {
                ["Environment"] = environment,
                ["Password"] = password
            };
        });
    }
}
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 "myEnvironment" and "myPassword"
            var environment = config.get("myEnvironment");
            var password = config.getSecret("myPassword");

            // Export the values as a stack outputs
            ctx.export("Environment", Output.of(environment));
            ctx.export("Password", Output.of(password));
        });
    }
}

Save your file and then run the pulumi up command.

$ pulumi up -y

     Type                 Name                Status
 +   pulumi:pulumi:Stack  python-dev  created (0.54s)

Outputs:
    myEnvironment: "development"
    Password   : [secret]

Resources:
    + 1 created

Duration: 2s

You can see that the configuration values were successfully imported into the program and exported as outputs, and you can see that the value of Password, which comes from the secret configuration value myPassword, is still not visible.

Clean Up

Before moving on, tear down the resources that are part of your stack to avoid incurring any charges.

  1. Run pulumi destroy to tear down all resources. You'll be prompted to make sure you really want to delete these resources. A destroy operation may take some time, since Pulumi waits for the resources to finish shutting down before it considers the destroy operation to be complete.
  2. To delete the stack itself, run pulumi stack rm. Note that this command deletes all deployment history from the Pulumi Service.

Next Steps

In this tutorial, you created raw and secret configuration values in your project’s stack. You also accessed these values via your Pulumi program code.

To learn more about managing and utilizing configuration and secrets in Pulumi, take a look at the following resources:

  • Learn more about more about how to centralize your configuration and secrets in the Pulumi ESC documentation.
  • Learn more about stack outputs and references in the Stack Outputs and References tutorial.