Managing Secrets in Pulumi ESC
This guide shows you how to store and retrieve secrets in Pulumi ESC environments. Secrets are encrypted values that ESC stores securely and hides from view by default.
New to ESC? Start with Get Started for a five-minute walkthrough, then return here for the full secret-management workflow.
Understanding ESC values
ESC environments store configuration as key-value pairs in YAML under a top-level values key. Any value wrapped in fn::secret is encrypted at rest and masked in output:
values:
region: us-west-2 # plaintext configuration
apiKey:
fn::secret: my-secret-value # encrypted secret
For the full breakdown of static, secret, and dynamic value types, see Environments.
Storing secrets
To store a secret, add an fn::secret value to your environment — using the CLI (pulumi env set --secret), the Pulumi Cloud console, or by editing the environment YAML directly. See fn::secret for the full reference and examples, including multi-line secrets such as PEM-formatted keys and certificates.
Retrieving secrets
Via the CLI
Open your environment to retrieve all values, including secrets:
pulumi env open <org>/<project>/<env-name>
This returns all values in JSON format with secrets revealed:
{
"apiKey": "my-secret-value",
"region": "us-west-2"
}
To retrieve a single value:
pulumi env get <org>/<project>/<env-name> apiKey
Via the Pulumi Cloud console
- Select your environment in Pulumi Cloud
- Select Open to evaluate the environment
- Toggle Show secrets to reveal encrypted values
Via Pulumi IaC or language SDKs
You can also consume ESC secrets programmatically — either through Pulumi IaC stacks that import the environment, or directly using the ESC SDK.
Organizing secrets
Nested structure
Group related secrets using nested keys:
values:
database:
host: db.example.com
password:
fn::secret: db-password-123
port: 5432
api:
key:
fn::secret: api-key-456
endpoint: https://api.example.com
Access nested values with dot notation:
pulumi env get my-org/my-project/dev database.password
Multiple environments
Organize secrets by environment (dev, staging, production) using separate ESC environments:
my-org/my-project/dev- Development secretsmy-org/my-project/staging- Staging secretsmy-org/my-project/prod- Production secrets
Each environment can have different RBAC permissions, ensuring production secrets are only accessible to authorized users.
Best practices
Rotate secrets regularly
You can replace a secret manually with pulumi env set ... --secret (ESC versions every change, so you can audit or roll back). For supported secret types, ESC can also rotate credentials automatically on a schedule — the recommended approach. See Rotating secrets for operational guidance and best practices.
Control access with RBAC
Use Role-Based Access Control to limit who can read or write secrets:
- Grant teams read-only access to production secrets
- Allow developers full access to development secrets
- Use service accounts for CI/CD access
Next steps
- Integrate with Pulumi IaC - Use secrets in your infrastructure code
- Dynamic secrets - Pull secrets from AWS, Azure, GCP secret stores
- Running commands with pulumi env run - Inject secrets into any command
- Access control reference - Complete RBAC documentation
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.