Terraform Cloud Project Bootcamp with Andrew Brown — 2.5.0 Deploying to Terratowns
This article is part of my Terraform journey with Terraform Bootcamp by Andrew Brown and Andrew Bayko with Chris Williams and Shala.
My wild career adventure into Cloud Computing continues with Andrews, and I highly, highly recommend you to come join us if you are interested. Check out Andrews’ free youtube learning contents. You can also buy some paid courses here to support their good cause.
Agenda
Video here: 2 5 0 Deploying to Terratowns
Issue #52 Goals
- ✅ 1) Test our custom provider, to work with the production server.
Workflow
- ✅ 1) Deploy to Missingo
- ✅ 2) Serve the content
- ✅ 3) Bucket name and & Security Best practices
1. Deploy to Missingo
In the previous episode, we were testing the environment locally in Gitpod workspace. Now we want to deploy our terratown_homes
to actual TerraTown. The town Missingo
is a test town for campers to test-deploy our homes
. Let’s do this.
The first thing we do is to update the URL endpoint for the terratowns
provider in main.tf
.
provider "terratowns" {
- endpoint = "http://localhost:4567/api"
+ endpoint = "https://terratowns.cloud/api"
user_uuid = "e328f4ab-b99f-421c-84c9-4ccea042c7d1"
token = "9b49b3fb-b8e9-483c-b703-97ba88eef8e0"
}
Then we replace the mock user_uuid
and token
with our own. You can find your own User UUID in the access token on ExamPro.co website.
user_uuid
: click on your profile circle at the top-right corner.token
: from that circle, you have the top-down menu. Click onSettings
. Then you will have theVending Machine
option. There, you can generate your own access token.
# main.tf
provider "terratowns" {
endpoint = "https://terratowns.cloud/api"
user_uuid = "your-own-uuid"
token = "your-own-token-from-vending-machine"
}
Then we are switching to the test town “missingo
”.
resource "terratowns_home" "home" {
name = "Nomadiachi's nomadic life"
description = <<DESCRIPTION
Mariachi works nomadically so popping in and checking out here and there.
Pictures of some memorable moments, quick snapshots of days in and days out.
Come join my nomadinary journey? :D
DESCRIPTION
# domain_name = module.terrahouse_aws.cloudfront_url
domain_name = "3fdq3gz.cloudfront.net"
- town = "the-nomad-pad"
+ town = "missingo"
content_version = 2
}
We rebuild our custom provider then test it out. Now run:
./bin/build_provider
terraform init
terraform apply
Now it’s running.
2. Serve the content
If you click on the terratowns_home
in Missingo, however, the content is not served. We have to do more configuration to get it served up. So we tear down the infrastructure. Run: terraform destroy
(6:19).
First, we want to mask the environmental variables using terraform variables in provider
in main.tf
.
provider "terratowns" {
- endpoint = "http://localhost:4567/api"
- user_uuid = "e328f4ab-b99f-421c-84c9-4ccea042c7d1"
- token = "9b49b3fb-b8e9-483c-b703-97ba88eef8e0"
+ endpoint = var.terratowns_endpoint
+ user_uuid = var.teacherseat_user_uuid
+ token = var.terratowns_access_token
}
Add the following to terraform.tfvars
at root.
terraform_endpoint="https://terratowns.cloud/api"
We take out the mock url and bring back the CloudFront domain_name
in resource
home
.
resource "terratowns_home" "home" {
name = "Nomadiachi's nomadic life"
...
+ domain_name = module.terrahouse_aws.cloudfront_url
- domain_name = "4fdq3gz.cloudfront.net"
town = "missingo"
content_version = 1
}
For security best practices, we want to store the user_uuid
and access_token
as env variables and call them from main.tf
. The way to let terraform know of the locally stored env variables is to name the env variables headed by “TF_VAR
”.
export TF_VAR_terratowns_access_token="access-token-from-vending"
gp env TF_VAR_terratowns_access_token="access-token-from-vending"
export TF_VAR_teacherseat_user_uuid="uuid-from-exampro"
gp env TF_VAR_teacherseat_user_uuid="uuid-from-exampro"
Run terraform apply
.
Obviously, terraform doesn’t know where to find the values. We have to modify the terraform variable names identical to the exported variable names (excluding TF_VAR_
in front).
# variables.tf
- variable "user_uuid" {
+ variable "teacherseat_user_uuid" {
type = string
}
In fact, we have to add all the variables that we are going to secure so add the following three to your variables.tf
at root.
provider "terratowns" {
endpoint = var.terratowns_endpoint
user_uuid = var.teacherseat_user_uuid
token = var.terratowns_access_token
}
# variables.tf
variable "terratowns_endpoint" {
type = string
}
variable "teacherseat_user_uuid" {
description = "Your own user uuid from teacherseat."
type = string
}
variable "terratowns_access_token" {
description = "Your own access token generated by the vending machine from teacherseat."
type = string
}
Andrew wants to see if referencing variables works correctly. We run terraform apply
. If successful, destroy
the infrastructure right after.
Now, bring back the old infrastructure module.terrahouse_aws
.
module "terrahouse_aws" {
source = "./modules/terrahouse_aws"
user_uuid = var.teacherseat_user_uuid
bucket_name = var.bucket_name
index_html_filepath = var.index_html_filepath
error_html_filepath = var.error_html_filepath
content_version = var.content_version
assets_path = var.assets_path
}
Run terraform init
and terraform apply
. It’s not going to work as the value for assets_path
is missing.
Add assets_path
to the module terrahouse_aws
.
module "terrahouse_aws" {
source = "./modules/terrahouse_aws"
user_uuid = var.teacherseat_user_uuid
bucket_name = var.bucket_name
index_html_filepath = var.index_html_filepath
error_html_filepath = var.error_html_filepath
content_version = var.content_version
+ assets_path = var.assets_path
}
3. Bucket name & Security Best practices
There are security concerns regarding the bucket_name
. During our Terraform bootcamp, it happened that someone took Andrew’s bucket name which he had been using throughout the videos. As every AWS S3 bucket name has to be unique throughout the world, this causes problems on Andrew’s end. Now he wants to have the bucket_name
randomly generated so this name conflict doesn’t happen again.
module "terrahouse_aws" {
source = "./modules/terrahouse_aws"
user_uuid = var.teacherseat_user_uuid
- bucket_name = var.bucket_name
index_html_filepath = var.index_html_filepath
error_html_filepath = var.error_html_filepath
content_version = var.content_version
assets_path = var.assets_path
}
Then comment out the entire bucket_name
variable in variables.tf
.
# variable "bucket_name" {
# description = "The name of the S3 bucket"
# type = string
# validation {
# condition = (
# length(var.bucket_name) >= 3 && length(var.bucket_name) <= 63 &&
# can(regex("^[a-z0-9][a-z0-9-.]*[a-z0-9]$", var.bucket_name))
# )
# error_message = "The bucket name must be between 3 and 63 characters, start and end with a lowercase letter or number, and can contain only lowercase letters, numbers, hyphens, and dots."
# }
# }
Now that we removed the bucket_name
variable, we have to change the parts where this variable is referenced.
resource "aws_cloudfront_origin_access_control" "default" {
- name = "OAC ${var.bucket_name}"
- description = "Origin Access Controls for Static Website Hosting ${var.bucket_name}"
+ name = "OAC ${aws_s3_bucket.website_bucket.bucket}"
+ description = "Origin Access Controls for Static Website Hosting ${aws_s3_bucket.website_bucket.bucket}"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
resource "aws_cloudfront_distribution" "s3_distribution" {
...
enabled = true
is_ipv6_enabled = true
- comment = "Static website hosting for: ${var.bucket_name}"
+ comment = "Static website hosting for: ${aws_s3_bucket.website_bucket.bucket}"
default_root_object = "index.html"
Then terraform apply
. My terrahome is up and running on the test town Missingo!
📑 Notes
- Every bucket name in AWS S3 must be globally unique. Otherwise this will lead to a bucket name conflict.
Resources
Bootcamp
- Video: 2 5 0 Deploying to Terratowns
- My feature branch: 52-terratown-test
- My complete Learning Journal