Now you have built, changed, and destroyed infrastructure from your local machine. This is great for testing and development, but in production environments you should keep your state secure and encrypted, where your teammates can access it to collaborate on infrastructure. The best way to do this is by running Terraform in a remote environment with shared access to state.
Terraform remote backends allow Terraform to use a shared storage space for state data. The Terraform Cloud remote backend also allows teams to easily version, audit, and collaborate on infrastructure changes. It can also store access credentials off of developer machines, and provides a safe, stable environment for long-running Terraform processes.
In this tutorial you will migrate your state to Terraform Cloud.
»Prerequisites
This tutorials assumes you have completed the previous tutorials. If not, create a directory named learn-terraform-azure-instance
and paste this code into
a file named example.tf
.
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.26"
}
}
}
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "rg" {
name = "myTFResourceGroup"
location = "westus2"
}
»Set up the remote backend
First, we'll use Terraform Cloud as our backend. Terraform Cloud offers free remote state management. Terraform Cloud is the recommended best practice for remote state storage.
If you don't have an account, please sign up here for this tutorial. For more information on Terraform Cloud, view our getting started tutorial.
When you sign up for Terraform Cloud, you'll create an organization. Make a note of the organization's name.
Next, configure the backend in your configuration with the organization name, and a new workspace name of your choice:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.26"
}
}
+ backend "remote" {
+ organization = "<ORG_NAME>"
+ workspaces {
+ name = "Example-Workspace"
+ }
+ }
}
provider "azurerm" {
features {}
}
»Authenticate with Terraform Cloud
Now that you have defined your backend, you must authenticate with Terraform Cloud in order to proceed with initialization. In order to authenticate with Terraform Cloud, run the terraform login
subcommand, and follow the prompts to log in.
Note: If you are using a version of Terraform prior to 0.12.21, the terraform login
command is not available. Instead, set up a CLI configuration file to authenticate.
$ terraform login
Terraform will request an API token for app.terraform.io using your browser.
If login is successful, Terraform will store the token in plain text in
the following file for use by subsequent commands:
/Users/username/.terraform.d/credentials.tfrc.json
Do you want to proceed? (y/n)
For more detailed instructions on logging in, see the login tutorial.
»Migrate the state file
Once you have authenticated the remote
backend, you're ready to migrate your local state file to Terraform Cloud. To begin the migration, reinitialize. This causes Terraform to recognize your changed backend configuration.
$ terraform init
Initializing the backend...
Acquiring state lock. This may take a few moments...
Do you want to copy existing state to the new backend?
Pre-existing state was found while migrating the previous "local" backend to the
newly configured "remote" backend. No existing state was found in the newly
configured "remote" backend. Do you want to copy this state to the new "remote"
backend? Enter "yes" to copy and "no" to start with an empty state.
Enter a value:
During reinitialization, Terraform presents a prompt saying that it will copy the state file to the new backend. Enter "yes" and Terraform will migrate the state from your local machine to Terraform Cloud.
Enter a value: yes
Successfully configured the backend "remote"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Using previously-installed hashicorp/azurerm v2.38.0
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Now that Terraform has migrated the state file to Terraform Cloud, delete the local state file.
$ rm terraform.tfstate
»Set remote variables
Terraform Cloud runs the terraform
binary on an ephemeral virtual machine, which makes long runs safer and more stable. Because Terraform is running remotely, you must also define your variables so that Terraform Cloud can access them.
Rename terraform.tfvars
to terraform.auto.tfvars
. Terraform Cloud can automatically load any number of *.auto.tfvars
files.
Create a file called secrets.auto.tfvars
and define your user name and password by pasting them into the file. Be sure to keep this file secure since it contains sensitive information.
admin_username = "plankton"
admin_password = "Password1234!"
»Configure a Service Principal
If you are not already logged in to Azure, use the Azure CLI to log in to your account.
$ az login
Your browser window will open and you will be prompted to enter your Azure login credentials. After successful authentication, your terminal will display your subscription information. You do not need to save this output as it is saved in your system for Terraform to use.
A Service Principal is an application within Azure Active Directory whose authentication tokens can be used as environment variables in Terraform Cloud. For more information, visit the Azure documentation.
First, list the Subscriptions associated with your Azure account.
$ az account list
Your output will display one or more Subscriptions.
[
{
"cloudName": "AzureCloud",
"id": "00000000-0000-0000-0000-000000000000",
"isDefault": true,
"name": "PAYG Subscription",
"state": "Enabled",
"tenantId": "00000000-0000-0000-0000-000000000000",
"user": {
"name": "user@example.com",
"type": "user"
}
}
]
Copy the id
field value. This is the Subscription ID related to your account. Paste this value into the command below with your own Subscription ID and save the value. You will use it later to give Terraform Cloud access to your Azure account.
$ az account set --subscription="SUBSCRIPTION_ID"
Create the Service Principal with the same Subscription ID.
$ az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/SUBSCRIPTION_ID"
Creating a role assignment under the scope of "/subscriptions/SUBSCRIPTION_ID"
{
"appId": "00000000-0000-0000-0000-000000000000",
"displayName": "azure-cli-2017-06-05-10-41-15",
"name": "http://azure-cli-2017-06-05-10-41-15",
"password": "0000-0000-0000-0000-000000000000",
"tenant": "00000000-0000-0000-0000-000000000000"
}
Copy this output somewhere safe.
»Update the Terraform Cloud environment variables
Now that you have the authentication information for your account, navigate to the Example-Workspace
workspace in the Terraform Cloud UI.
Find the Variables tab and create the below environment variables using the values you put into and got back from the last command. Set the ARM_CLIENT_SECRET
as a sensitive value.
Environment Variable | AZ CLI |
---|---|
ARM_SUBSCRIPTION_ID | SUBSCRIPTION_ID from the last command's input. |
ARM_CLIENT_ID | appID from the last command's output. |
ARM_CLIENT_SECRET | password from the last command's output. (Sensitive) |
ARM_TENANT_ID | tenant from the last command's output. |
Update and save these four environment variables. Set the ARM_CLIENT_SECRET
as a sensitive value. Review your environment variables to ensure they match the example below.
»Apply the configuration
Now, apply your configuration including the required variables. Terraform will tell you that there are no changes.
$ terraform apply
# ...
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, Terraform
doesn't need to do anything.
Terraform is now storing your state remotely in Terraform Cloud. Remote state storage makes collaboration easier and keeps state and secret information off your local disk. Remote state is loaded only in memory when it is used.
If you want to move back to local state, you can remove the backend
configuration block from your configuration and run terraform init
again.
Terraform will once again ask if you want to migrate your state back to local.
»Destroy the infrastructure
Destroy your infrastructure, and remember to confirm with a yes
.
$ terraform destroy
»Learn more about Terraform Cloud
Terraform Cloud offers commercial solutions which combines a predictable and reliable shared run environment with tools to help you work together on Terraform configurations and modules.
Although Terraform Cloud can act as a standard remote backend to support Terraform runs on local machines, it works even better as a remote run environment. It supports two main workflows for performing Terraform runs:
- A VCS-driven workflow, in which it automatically queues plans whenever changes are committed to your configuration's VCS repo.
- An API-driven workflow, in which a CI pipeline or other automated tool can upload configurations directly.
For a hands-on introduction to Terraform Cloud, follow the Terraform Cloud getting started tutorials.
»Next Steps
That concludes the getting started tutorial for Terraform. Hopefully you're now able to not only see what Terraform is useful for, but you're also able to put this knowledge to use to improve building your own infrastructure.
We've covered the basics for all of these features in this tutorial.
Make sure to run terraform destroy
to cleanup the resources
you've created in these tutorials.
For more information on Terraform, review the following resources:
Documentation - The documentation is an in-depth reference guide to all the features of Terraform, including technical details about the internals of how Terraform operates.
Modules Track - Learn how to organize and re-use Terraform configuration with modules.
Import - The import section of the documentation covers importing existing infrastructure into Terraform.