Pulumi’s managed state and secrets are designed to simplify infrastructure management, but they often leave users confused about how their state is actually stored and protected.
Let’s see this in action. When you run pulumi up, Pulumi needs to know the current state of your infrastructure – what resources exist, their properties, and how they’re related. It also needs to store sensitive information like passwords or API keys securely. Pulumi’s managed backend handles both.
Imagine you’re deploying a simple S3 bucket:
# Pulumi.yaml
name: my-s3-project
runtime: yaml
description: A simple S3 bucket
resources:
myBucket:
type: aws:s3:Bucket
properties:
bucketName: my-unique-pulumi-bucket-12345
acl: private
When you run pulumi up for the first time, Pulumi communicates with the Pulumi Service (its managed backend). It sends the desired state defined in your Pulumi.yaml. The Pulumi Service then attempts to create this bucket in AWS.
If successful, the Pulumi Service stores the actual state of the myBucket resource – its ID, ARN, creation date, and any other relevant properties – in its backend. This state is versioned, so you can always see the history of your infrastructure. Crucially, any secrets defined in your Pulumi program (e.g., a password for a database) are encrypted before being sent to the Pulumi Service, using a unique encryption key per stack. The Pulumi Service only stores the encrypted blob.
The core problem Pulumi’s managed state solves is providing a centralized, secure, and versioned source of truth for your infrastructure, accessible from anywhere. Without it, you’d be responsible for managing terraform.tfstate files yourself, which is error-prone and insecure.
Here’s how it works internally:
-
State Storage: The Pulumi Service acts as a remote backend. When you run
pulumi login, you’re authenticating with the Service. Your stack’s state is stored in a dedicated database associated with your Pulumi account and organization. Each stack gets its own state file, which is essentially a JSON document representing your infrastructure’s current configuration. -
Secret Encryption: Pulumi uses AES-256-GCM for secret encryption. When you define a secret (e.g.,
secret: truefor aaws:rds:Instancepassword), Pulumi encrypts the value locally using a unique key generated for that specific stack. This encrypted ciphertext is then stored in the state file. The Pulumi Service never sees the unencrypted secret value. The decryption key is managed by Pulumi and is only accessible when you, or an authenticated CI/CD system, runpulumi uporpulumi previewwith the correct stack context. -
Version Control: Every
pulumi upoperation results in a new version of the state file. This allows you topulumi rollbackto a previous state if something goes wrong. The Pulumi Service keeps a history of these state versions, accessible through the Pulumi Console. -
Resource Tracking: Pulumi uses the state file to determine what needs to be created, updated, or deleted. During a
pulumi previeworpulumi up, Pulumi compares your desired configuration with the current state. If a resource exists in the state but not in your configuration, Pulumi flags it for deletion. If a resource exists in your configuration but not in the state, it’s flagged for creation. If properties differ, it’s flagged for update.
Consider a scenario where you have a database password stored as a Pulumi secret:
# Pulumi.yaml
name: my-db-project
runtime: yaml
description: A simple database
resources:
myDB:
type: aws:rds:Instance
properties:
# ... other RDS properties ...
username: admin
password:
secret: "mySuperSecretPassword123!" # This will be encrypted
When you run pulumi up, Pulumi encrypts "mySuperSecretPassword123!" locally. The state file stored in the Pulumi Service will contain a representation like {"secret": "..."} where ... is the encrypted ciphertext. The Pulumi Service itself cannot decrypt this. Only when you run pulumi up again, and your local Pulumi CLI has access to the decryption key (derived from your Pulumi login session), can the password be decrypted for operations like creating or updating the RDS instance.
The one thing that often trips people up is how Pulumi’s managed secrets interact with the Pulumi Service. It’s not that the Pulumi Service stores your secrets; it stores encrypted versions of your secrets. The actual encryption and decryption happen on your local machine or within your CI/CD environment. The Pulumi Service is merely a secure conduit for these encrypted blobs, ensuring that only authorized users with access to the correct stack can retrieve and decrypt them. This is why pulumi login and PULUMI_ACCESS_TOKEN are critical for security.
The next step in managing your infrastructure with Pulumi is understanding how to integrate this managed state and secrets into your CI/CD pipelines.