- what are cloud infrastructure state files
- how to properly store cloud infrastructure state files using different Pulumi backends
- which Pulumi backends to use in different contexts
In order to bring your project into existence, you need to deploy your application code, along with the necessary cloud infrastructure, into a cloud provider of your choice (for example AWS ).
By default, for everything deployment-related, Webiny relies on Pulumi, a modern infrastructure as code (IaC) framework. Essentially, the framework enables us to define needed cloud infrastructure via code, and ultimately, deploy it into one or more separate environments.
Read more about Pulumi, environments, and other deployment-related concepts in our Deployment key topics section.
One of the fundamental concepts of any IaC framework are cloud infrastructure state files. Every framework handles them differently, but in all cases, state files represent the state of all deployed cloud infrastructure resources. Things like which resources are currently deployed, which configuration params were used upon deploying them, and more, are just some of the information these state files contain.
It’s important to know that state files must not be lost or deleted, because otherwise, the connection between our IaC framework and the actual cloud infrastructure resources would also be lost. Meaning, we would lose the ability to update existing cloud infrastructure resources or even delete them (using the IaC framework).
If it happens that we’ve lost our state files and we wanted to delete all of the deployed cloud infrastructure resources, we would have to do it manually, via the cloud provider’s user interface or using a CLI.
Because of the fact that our cloud infrastructure state files must be preserved, we are often talking about cloud infrastructure state management, or, in context of IaC frameworks and cloud infrastructure deployments, just state management.
Fortunately, out of the box, Pulumi already offers a solution that solves the state management overhead for us. Using different backends, we are able to store our state files in different places, in a secure and reliable way.
The following are three backends that are commonly used with Webiny projects.
This is the default backend, with which, all of the state files are stored within your Webiny project, inside of a single
.pulumi folder, located in your project root. Note that this folder contains cloud infrastructure state files for all project applications you might have in your Webiny project.
Learn more about project applications and project organization in general, in the Project Applications and Packages key topic.
The following directory tree shows the
.pulumi folder which is being utilized by all three default project applications (
. ├── api │ ├── .pulumi │ │ ├── backups │ │ ├── history │ │ └── stacks ├── apps │ ├── admin │ │ ├── .pulumi │ │ │ ├── backups │ │ │ ├── history │ │ │ └── stacks │ └── website │ ├── .pulumi │ │ ├── backups │ │ ├── history │ │ └── stacks │ └── (...)
This backend can be a solid choice for local development purposes, where you typically don’t need to share the state files with other team members and are only relevant to you. Because of this, in every new Webiny project, by default, the
.pulumi folder isn’t checked into your version control.
With this backend option, we can store our cloud infrastructure state files in a remote Amazon S3 bucket.
This is useful when deploying our project into long-lived shared environments, like
staging or even
prod (production). Environments like these can certainly be considered as sensitive, so, it is critical that we have a single source of truth of our cloud infrastructure state and also, that the state files are stored in a reliable and secure way. We definitely want to avoid having multiple versions of our production cloud infrastructure state, or have our state files publicly exposed.
You can certainly use the Amazon S3 for storing cloud infrastructure state files, but if you need more, you can also explore the Pulumi Service .
It is a service that not only gives you the ability to store your cloud infrastructure state files in an easy, secure, and reliable way, but also offers a couple of other interesting features, like:
- concurrent state locking to prevent corrupting your infrastructure state in a team environment
- full deployment history for auditing and rollback purposes
- encrypted state in transit and at rest
- and more
Of course, it does come with a price, so make sure to check their official pricing page before making a decision on which backend you’re about to use.
As mentioned, Webiny will instruct the Pulumi framework to use the local file system as the default backend. But, you can easily instruct it to use a different one, using the
WEBINY_PULUMI_BACKEND environment variable, which needs to be assigned upon running the
webiny deploy command.
Environment variables can be assigned in a couple of different ways. In local development, we recommend you assign them via the
.env file, located in your project root. In CI/CD environments, you should use mechanisms recommended by your CI/CD provider.
Check out the Environment Variables how-to guide to learn more.
If we wanted to use Amazon S3 as our backend of choice, we could assign the following environment variable:
On the other hand, if we wanted to use the Pulumi Service, we could assign the following environment variables:
Note that, when using the Pulumi Service, it’s recommended we remove the
PULUMI_CONFIG_PASSPHRASE environment variables. Essentially, these variable instruct Pulumi CLI which secrets provider we want to use, and since Pulumi Service has its own built-in one, we don’t need these anymore.
For development purposes, we recommend using the default local file system as your backend of choice. This is simply because the cloud infrastructure you deploy will most probably only be used by you, and the state files the deployment process produces don’t need to be shared with other developers or processes.
That being said, there might still be cases in which you’ll want to share the cloud infrastructure state files, for example with your team members or maybe you just want to continue developing on a different machine.
And while both can be achieved, note that sharing cloud infrastructure state files implies the same cloud (AWS) account is used on every machine on which the files end up. Which means that sharing them with multiple team members requires every member to use the same cloud account and this is something we usually wouldn’t recommend. Ideally, developers should have their own cloud account for development purposes.
For easier AWS account management, we recommend you checkout the AWS Organizations service which makes it easier to manage multiple AWS accounts within your organization.
In case of the latter, where developers just wants to continue working from one of their other machines (using the same cloud account), sharing the cloud infrastructure state files can be achieved in a relatively straightforward way.
Simply copy and paste your
.pulumi folder to the other machine. Once you’ve done that, also note that all of the extra configuration arguments, that were passed to Pulumi via environment variables, should also be copied. Usually, here we’re referring to values that were specified in your root
.env file, where by default, the
PULUMI_CONFIG_PASSPHRASE values are set.
Keep in mind that if you switched to another machine and later plan to return back to the initial one, you’ll need to repeat the explained steps.
Note that in case of the former, since we recommend a separate cloud (AWS) account to be used with every long-lived environment, you will end up with a separate Amazon S3 bucket for each environment.
If you’re using a separate cloud (AWS) account for every long-lived environment, then the answer is yes and this is the approach we recommend you adapt.
For storing cloud infrastructure state of my long-lived environments in Amazon S3 buckets, must I create these on my own, or does this happen automatically in some way?
If you decide to use Amazon S3 as a way to store your cloud infrastructure state files for your long-lived environments, then be aware that the actual buckets will need to be created manually. At the moment, this is not something Webiny does automatically for you (but we are thinking about it).
The most straightforward way to do it would be to open the AWS Management Console for every separate AWS account you might have, and simply create the bucket from there.
Remember - we recommend having a separate cloud account for every long-lived environment you might have. Usually this means having three accounts: one for
dev, one for
staging, and one for
prod (production) environment. In case you missed it, check out the Environments guide to learn more about these.
We don’t recommend doing it for of a couple reasons, mainly because this can quickly get messy, especially if multiple developers are working on the project.
Still, if you have a strong opinion on this, let us know , we’d like to hear your thoughts!
No matter which Pulumi backend you end up choosing, if two or more Pulumi deployments are triggered simultaneously, only the first one will be performed. The rest will be rejected, with an appropriate error being returned in your terminal. The error should look similar to the following:
error: the current deployment has 1 resource(s) with pending operations: * urn:pulumi:dev::website::aws:cloudfront/distribution:Distribution::delivery, interrupted while updating
Different CI/CD providers offer different options when it comes to setting environment variables. For example, GitHub Actions enable this via repository secrets . On the other hand, if using AWS CodeBuild , you can use the AWS CodePipeline service.
Make sure to read the relevant documentation for best practices around how to properly set environment variables in your CI/CD provider.
Is it possible to move my locally stored state files into an Amazon S3 bucket and continue using it as my backend?
Yes, it can be done by taking the following steps.
First, create a new Amazon S3 bucket. Do note that it has to be created in the same region where your Webiny project is deployed.
Once the bucket has been created, assign its URI to the
WEBINY_PULUMI_BACKEND environment variable, in your
.env file. For example:
Finally, copy all of the folders and files located in your project root
.pulumi folder into the newly created bucket. Once copied, you should end up with paths similar to the following:
my-project-state-files/api/.pulumi/... my-project-state-files/apps/admin/.pulumi/... my-project-state-files/apps/website/.pulumi/...
In order to confirm everything works as expected, from your project root, simply run the
webiny info command. If everything was done correctly, it should display the correct information (GraphQL API URL, Headless CMS GraphQL API URLs, …).
If you’re passing secrets or passwords to cloud infrastructure resources in your cloud infrastructure (Pulumi) code, for example an API token from an external service, then it’s recommended that you mark them as secret.
The easiest way to do this would be to use the pulumi.secret method, for example:
With this approach, values will still end up in your state files, but they will be encoded, which means nobody will be able to actually read them.