1. The Pulumi Registry#
The Pulumi Registry is the central repository for all Pulumi Providers. A Provider is simply a plugin that knows how to translate Pulumi’s internal JSON intent into the specific REST API calls required by a third-party service.
Because we are using TypeScript, Pulumi Providers are distributed as standard NPM packages.
To see what is available, search the Registry. You will find providers for:
- Cloud Providers: AWS, Azure, Google Cloud, DigitalOcean.
- Infrastructure Services: Cloudflare, Auth0, Datadog, PagerDuty.
- Developer Tools: GitHub, GitLab, Docker, Kubernetes.
Installing a Provider#
Let’s assume our team needs to provision an AWS EC2 instance, but we also need to create a GitHub repository for the application code.
First, we must install the GitHub Provider via NPM.
Run this in your terminal:
npm install @pulumi/githubThat’s it. You do not need to edit a complex required_providers block like you do in Terraform. You just use standard package management.
2. Multi-Cloud Orchestration#
Now that we have both @pulumi/aws and @pulumi/github installed, let’s write a multi-cloud orchestration script.
Open index.ts:
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as github from "@pulumi/github";
// 1. Create the AWS Infrastructure
const webServer = new aws.ec2.Instance("web-server", {
ami: "ami-0fc5d935ebf8bc3bc",
instanceType: "t3.micro",
});
// 2. Create the GitHub Repository
const appRepo = new github.Repository("app-source-code", {
description: "The source code for the Web Server application",
visibility: "private",
hasIssues: true,
});
// 3. Orchestrate across clouds!
// We can pass the AWS Public IP as a GitHub Repository Secret!
const dbSecret = new github.ActionsSecret("api-url-secret", {
repository: appRepo.name,
secretName: "SERVER_PUBLIC_IP",
// Passing cross-provider data!
plaintextValue: webServer.publicIp,
});The Magic of Cross-Provider Dependencies#
Look closely at Step 3. We are creating a GitHub Action Secret. The plaintextValue is set to webServer.publicIp.
The Pulumi Engine is incredibly smart. It builds a unified Dependency Graph across all providers.
- It knows it must create the AWS EC2 instance first to get the Public IP.
- It knows it must create the GitHub Repository first to get the Repository Name.
- It will execute both creations in parallel.
- Once both are complete, it will create the GitHub Secret.
You just orchestrated a complex multi-cloud deployment with zero race conditions.
3. Configuring Provider Credentials#
How does Pulumi authenticate with GitHub? We never hardcoded a Personal Access Token (PAT).
Every Provider has a specific configuration block in the Pulumi.<stack>.yaml file.
When Pulumi initializes the GitHub Provider, it looks for the github:token configuration variable.
You set this exactly like you set standard config, but you use the provider namespace:
# Set the GitHub token as an encrypted secret
pulumi config set github:token ghp_12345ABCDE --secretIf you look at your Pulumi.dev.yaml:
config:
aws:region: us-east-1
github:token:
secure: v1:9876xyz:fedcba0987654321Pulumi automatically decrypts the token at runtime and passes it to the GitHub Provider plugin.
4. Explicit Provider Instantiation#
By default, when you import @pulumi/aws, Pulumi uses the “default” provider configuration (e.g., us-east-1 from your stack config).
But what if you need to deploy resources to us-east-1 AND eu-central-1 in the exact same TypeScript file? You must explicitly instantiate multiple Provider objects.
import * as aws from "@pulumi/aws";
// 1. Create an explicit Provider pointing to Europe
const euProvider = new aws.Provider("eu-provider", {
region: "eu-central-1",
});
// 2. Create a resource using the default provider (us-east-1)
const usBucket = new aws.s3.Bucket("us-bucket");
// 3. Create a resource using the explicit EU provider
const euBucket = new aws.s3.Bucket("eu-bucket", {
// Pass the explicit provider in the ResourceOptions!
}, { provider: euProvider });
This pattern is also essential if you need to assume different IAM Roles for different resources. You would create a new aws.Provider and pass the assumeRole arguments into it.
Troubleshooting & Common Errors#
error: Missing required configuration variable 'github:token'- Root Cause: You imported the GitHub SDK and instantiated a resource, but the Pulumi Engine cannot authenticate with the GitHub API because you forgot to set the configuration value.
- Solution: Read the documentation for the specific Provider on the Pulumi Registry. It will always list the required configuration variables. Run
pulumi config set <namespace>:<key> <value>.
Module '"@pulumi/datadog"' has no exported member- Root Cause: A TypeScript error indicating your IDE doesn’t recognize the package.
- Solution: Ensure you actually ran
npm install @pulumi/datadog.
Conclusion & Next Steps#
The Pulumi Registry transforms IaC from a simple cloud-provisioning tool into a universal Automation Engine. By integrating providers like GitHub, Kubernetes, and AWS, you can automate your entire organization’s lifecycle.
However, the @pulumi/aws package we have been using is technically a “Bridged” provider. It is actually built on top of the Terraform AWS Provider! This means it inherits some of Terraform’s quirks.
Recently, Pulumi released something revolutionary: a 100% native integration with the AWS Cloud Control API.
In Episode 10: Using Native Providers, we will explore @pulumi/aws-native, learn why it is significantly faster than the classic provider, and discuss when you should use it.

