Published: Wed 10 June 2020
By Rilindo Foster
In Blog .
tags: terraform automation saas cloud
I run my practice labs on a number of tier 1 and tier 2 cloud providers. While Terraform can store my state on any S3 compatible bucket, some providers makes it difficult to setup, if not impossible. This is how I get around it by storing my state on Terraform Cloud.
First, I sign up for the account here , which, as of this time of writing is free for personal use. Next, I create my workspace:

After I created my workspace (in this case, scaleway-cka):

I click on NO VCS button:

Then on the right, I click on settings and then general :

Finally, I have the choice between remote or local . It is just me working with my terraform code, so I picked local :

Now I am done, so the next step is to perform the actual migration. First, I created a branch off my terraform code (I am not a barbarian, after all):
git checkout -b move_scaleway_local_to_terraform_cloud
Next, I created a backend.tf file in the main terraform module directory:
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "monzell"
workspaces {
name = "scaleway-cka"
}
}
}
Then, I login into my Terraform cloud account:
It prompted me to configure my terraform cloud credentials:
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 / rilindo / .terraform .d / credentials .tfrc .json
Do you want to proceed ? ( y / n ) y
I say y for yes and terraform follows up with the prompt to enter the token:
Terraform must now open a web browser to the tokens page for app .terraform .io .
If a browser does not open this automatically , open the following URL to proceed :
https :// app .terraform .io / app / settings / tokens ?source = terraform - login
---------------------------------------------------------------------------------
Generate a token using your browser , and copy - paste it into this prompt .
Terraform will store the token in plain text in the following file
for use by subsequent commands :
/ Users / rilindo / .terraform .d / credentials .tfrc .json
Token for app .terraform .io :
And at the same time, bring up the following screen in my browser:

I generated my token and pasted it back into terminal token prompt, which allowed me to successfully configure my credentials on my machine.
Retrieved token for user rilindo
---------------------------------------------------------------------------------
Success! Terraform has obtained and saved an API token .
The new API token will be used for any future Terraform command that must make
authenticated requests to app . terraform . io .
Now I am ready to build. First, I re-initialize my terraform configuration with terraform init .
terraform init
Initializing modules ...
Initializing the backend ...
Successfully configured the backend "remote" ! Terraform will automatically
use this backend unless the backend configuration changes .
Initializing provider plugins ...
The following providers do not have any version constraints in configuration ,
so the latest version was installed .
To prevent automatic upgrades to new major versions that may contain breaking
changes , it is recommended to add version = "..." constraints to the
corresponding provider blocks in configuration , with the constraint strings
suggested below .
* provider . template : version = "~> 2.1"
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 .
Then I created my terraform plan:
terraform plan - out = terraform . tfplan \
> - var "domain_name=${DOMAIN_NAME}" \
> - var "public_key=${PUBLIC_KEY}" \
> - var "sw_ns1=${SW_NS1}" \
> - var "sw_org_id=${SW_ORG_ID}" \
> - var "src_ip=${SRC_IP}" \
> - var "sw_access_key=${SW_ACCESS_KEY}" \
> - var "sw_secret_key=${SW_SECRET_KEY}"
After reviewing my output:
Refreshing Terraform state in - memory prior to plan ...
The refreshed state will be used to calculate this plan , but will not be
persisted to local or remote state storage .
module . cp01 . data . scaleway_instance_image . image : Refreshing state ...
------------------------------------------------------------------------
An execution plan has been generated and is shown below .
Resource actions are indicated with the following symbols :
+ create
<= read ( data resources )
Terraform will perform the following actions :
# module.cp01.data.template_file.custom_user_data will be read during apply
# (config refers to values not yet known)
<= data "template_file" "custom_user_data" {
+ id = ( known after apply )
+ rendered = ( known after apply )
+ template = <<~ EOT
#!/bin/bash
yum check - update
yum install - y NetworkManager git epel - release
hostnamectl set - hostname "${node_name}.${domain_name}"
EOT
+ vars = {
.
.
.
.
# module.zone.ns1_zone.domain_name will be created
+ resource "ns1_zone" "domain_name" {
+ autogenerate_ns_record = true
+ dns_servers = ( known after apply )
+ dnssec = ( known after apply )
+ expiry = ( known after apply )
+ hostmaster = ( known after apply )
+ id = ( known after apply )
+ networks = ( known after apply )
+ nx_ttl = ( known after apply )
+ refresh = ( known after apply )
+ retry = ( known after apply )
+ ttl = 600
+ zone = "reverseblade.org"
}
Plan : 6 to add , 0 to change , 0 to destroy .
------------------------------------------------------------------------
This plan was saved to : terraform . tfplan
To perform exactly these actions , run the following command to apply :
terraform apply "terraform.tfplan"
Finally, I went ahead and apply my configuration:
terraform apply "terraform.tfplan"
Back in my Terraform cloud screen, I could see that my workspace is locked:

And when it is done in my terminal:
module .cp01 .data .scaleway_instance_image .image: Refreshing state ...
module .zone .ns1_zone .domain_name: Creating ...
module .cp01_scaleway_instance_ip .scaleway_instance_ip .ip: Creating ...
module .ssh_key .scaleway_account_ssh_key .public: Creating ...
module .scaleway_security_group .scaleway_instance_security_group .external: Creating ...
module .zone .ns1_zone .domain_name: Creation complete after 2 s [id =5 ee1824015dbdd0091efa8b2 ]
module .cp01 .data .template_file .custom_user_data: Refreshing state ...
module .ssh_key .scaleway_account_ssh_key .public: Creation complete after 1 s [id =f8f89569-6e52-4a25-986c-57104006a74b ]
module .cp01_scaleway_instance_ip .scaleway_instance_ip .ip: Creation complete after 1 s [id =fr-par-1 / 4 a5870f2-9989-4e11-a4fc-1fcebbe7c9b1 ]
module .cp01_record .ns1_record .www: Creating ...
module .cp01_record .ns1_record .www: Creation complete after 2 s [id =5 ee182436711b3008b1e6d80 ]
module .scaleway_security_group .scaleway_instance_security_group .external: Creation complete after 5 s [id =fr-par-1 / 284 ebb7b-7101-47cd-a781-8894ccddad6e ]
module .cp01 .scaleway_instance_server .instance: Creating ...
module .cp01 .scaleway_instance_server .instance: Still creating ... [10 s elapsed ]
module .cp01 .scaleway_instance_server .instance: Still creating ... [20 s elapsed ]
module .cp01 .scaleway_instance_server .instance: Still creating ... [30 s elapsed ]
module .cp01 .scaleway_instance_server .instance: Creation complete after 33 s [id =fr-par-1 / a23efeab-13e8-4609-a2a2-c8f0ecfaafcd ]
Apply complete ! Resources: 6 added , 0 changed , 0 destroyed .
I can see a new state entry under states , indicating that I either created or updated my state:

And that is about it.
So far, I liked the Terraform Cloud. I could already see the benefits of using it visually tracking my activity and managing the state through an easy to use UI. If I were part of a larger team using Terraform, I would recommend moving to Terraform cloud, as it removes the need to manage the state manually. I give it a thumbs up.
(in other news, I really need to not rely on the <center> tag for my images)