Using Octopus Deploy with Pulumi
Octopus Deploy is a deployment automation server that orchestrates releases across environments. Octopus is organized around projects, versioned releases, and environments that a release advances through. You run Pulumi as a step in an Octopus deployment process, so an infrastructure change is deployed and promoted with the same release mechanics Octopus already uses for application code.
This guide assumes Pulumi Cloud as your backend. Pulumi Cloud isn't required to run Pulumi in CI/CD — Pulumi also supports self-managed backends — but the access token, OIDC, and ESC features described here are specific to Pulumi Cloud.
How Pulumi works with Octopus Deploy
Octopus Deploy is a continuous delivery server, not a continuous integration server: it does not track your version control system, and it does not watch for pull requests or branch pushes. Octopus is typically paired with an upstream CI system — such as GitHub Actions, Jenkins, or TeamCity — that builds and tests your code, runs pull request previews, and produces the versioned package Octopus releases.
To apply infrastructure changes, Pulumi runs your program with the Pulumi CLI. In an Octopus deployment process, a Run a Script step provides that environment. Octopus execution containers let that step run inside a container image you choose: point it at the official pulumi/pulumi image and the step has the Pulumi CLI and every language runtime preinstalled. The same deployment process then works with a Pulumi program written in any supported language and targeting any cloud provider Pulumi supports.
Prerequisites
Before you begin, make sure you have:
- A Pulumi Cloud account and organization.
- An Octopus Deploy instance — Octopus Cloud or a self-hosted server — with a project and one or more environments configured.
- A Pulumi program in a Git repository. If you don’t have one yet, follow a Get started guide.
- An upstream CI system that builds your program and publishes it as a package for Octopus to release.
Authenticate with Pulumi Cloud
Give your deployment process a Pulumi Cloud identity in one of two ways. Choose one — you don’t need both:
- A stored access token. Save a long-lived Pulumi access token as a sensitive Octopus variable. Simple to set up and works on every Octopus version.
- OpenID Connect (OIDC), recommended where supported. Exchange a short-lived token issued by Octopus for a temporary Pulumi access token, so no long-lived credential is stored anywhere.
Use a stored access token
Pulumi reads its access token from the PULUMI_ACCESS_TOKEN environment variable and authenticates without an interactive login. Store the token as a sensitive Octopus project variable — or, to reuse it across projects, in a library variable set — named PULUMI_ACCESS_TOKEN. Prefer an organization or team token over a personal token so the deployment’s identity isn’t tied to an individual.
Marking the variable sensitive keeps its value out of logs and the Octopus UI. Scope it to the environments that should use it.
Use OIDC
Octopus Deploy 2025.1 and later can issue a short-lived OIDC token for a deployment run through a Generic OpenID Connect account. Pulumi Cloud can register Octopus Server as a trusted OIDC issuer, which removes the need to store a static PULUMI_ACCESS_TOKEN.
The flow is generic:
- Register your Octopus Server as an OIDC issuer in Pulumi Cloud, and configure a Generic OIDC account in Octopus whose audience matches what Pulumi Cloud expects.
- During the deployment, the Run a Script step reads the issued token from the account’s
OpenIdConnect.Jwtvariable. - The step exchanges that token for a temporary Pulumi access token with
pulumi login --oidc-token <token> --oidc-org <your-org>.
Provide cloud credentials
When Pulumi runs, your program also needs credentials for the cloud provider it manages. You can supply them in one of two ways:
- Pulumi ESC (recommended). Configure a Pulumi ESC (Environments, Secrets, and Configuration) environment to broker short-lived cloud credentials through OIDC. Your program receives temporary credentials scoped to exactly what it needs, and the deployment stores nothing but its Pulumi access token. Because ESC delivers those values the same way whether the consumer is an Octopus deployment or a developer’s machine, a single environment definition works in both places.
- Octopus accounts and variables. Add the provider’s credentials as an Octopus account — for example an AWS or Azure account — or as sensitive variables for other clouds, and expose them to the Run a Script step.
Run Pulumi in a deployment process
Add a Run a Script step to your project’s deployment process and run the Pulumi CLI against a stack. The following inline Bash script assumes the Pulumi program lives in an infra/ directory of the deployed package:
cd infra
# Install the program's language dependencies and required plugins.
pulumi install
# Select the stack for the environment being deployed.
pulumi stack select acme/website/staging
# Apply the infrastructure changes.
pulumi up --yes
Bind PULUMI_ACCESS_TOKEN to the step from the sensitive variable you created, or run the OIDC pulumi login exchange before the other commands. Set the step’s execution container image to pulumi/pulumi so the CLI and every language runtime are already present — no installation step required.
pulumi install installs the program’s language dependencies and required plugins, so the same step works for a program written in any supported language.
Build a trunk-based CI/CD workflow
The most common way to run Pulumi in CI/CD follows a trunk-based development model: work merges into a single main branch, and deployments flow outward from there. Because Octopus is a delivery server, the work is split: your upstream CI system handles the pull request and packaging stages, and Octopus deploys each release and promotes it through its environments.
Preview infrastructure changes
A pulumi preview reports the proposed changes without modifying any resources. Run it on every pull request in your upstream CI system so reviewers see the infrastructure changes alongside the code diff.
Within Octopus, you can also preview before applying: run pulumi preview as an early step in the deployment process, then add a manual intervention and approval step that pauses the deployment until someone signs off on the preview. The pulumi up step runs only after approval.
To let reviewers exercise a change in a live environment before it merges, use a Review Stack, which provisions an ephemeral stack for the pull request and destroys it when the pull request closes.
Deploy to staging on merge
When a pull request merges, your upstream CI system publishes a new package and creates an Octopus release. Octopus deploys that release to an environment that receives continuous delivery — such as a shared development or staging environment — by running pulumi up against the stack for that environment.
Promote to production
Octopus lifecycles make the production deployment a deliberate, traceable step. Rather than rebuilding, you promote the same release that was validated in staging to the Production environment, where the deployment process runs pulumi up against the production stack. Trigger the promotion from a release marker in your upstream CI — for example, a moving production Git tag that you advance to a commit already verified in staging. Production never deploys an untested build.
Speed up builds with caching
A fresh Octopus worker starts with an empty plugin cache, so Pulumi re-downloads its provider plugins on every deployment. Octopus has no native cross-deployment cache for these runs. To avoid the repeated downloads, bake the provider plugins into a custom image:
- Derive an image from
pulumi/pulumi. - Run
pulumi plugin installfor each provider your program uses. - Use that image as the execution container for the Run a Script step.
This makes each deployment deterministic and removes plugin-download time from every run. See the plugins documentation for details.
Report results on pull requests
Octopus Deploy is not aware of pull requests, but Pulumi Cloud’s version control integrations work independently of whichever system runs Pulumi. A version control integration lets Pulumi Cloud post infrastructure-change summaries as pull request comments and status checks, and link each stack update back to the commit and pull request that produced it. Pulumi maintains integrations for popular version control systems — see Version Control for the current list.
Additional resources
- Continuous delivery — overview of running Pulumi in CI/CD.
- CI/CD troubleshooting guide — diagnose common failures when running Pulumi in a pipeline.
- Pulumi ESC — deliver credentials, secrets, and configuration to deployments and developers consistently.
- OIDC Issuers — eliminate static tokens with short-lived, exchanged credentials.
- Review Stacks — ephemeral environments for pull requests.
- Version Control — connect Pulumi Cloud to your version control system.
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.