tl;dr Cara provision dan hosting static website dengan cara redirect dari Amazon S3 bucket ke web url lain menggunakan Terraform
Amazon Simple Storage Service (S3) merupakan storage service yang disediakan oleh Amazon Web Services (AWS). Secara garis besar penggunaannya adalah untuk media penyimpanan object atau sering disebut object storage service. Namun selain fungsi penyimpanan object tersebut, S3 juga menyediakan fitur static website hosting.
Pada blogpost kali ini, saya akan mendiskusikan cara hosting static website di S3 dengan metode redirect ke web url lain. Konfigurasi atau provision AWS resource menggunakan Terraform dengan backend remote (Terraform Cloud).
Skenario dan Topologi
Skenario dan topologi yang digunakan pada blog ini sebagai berikut:
- User mengakses nama domain yang didaftarkan di hosted zone Amazon Route 53. Pada contoh kali ini adalah ludesdeveloper.com. DNS record yang didaftarkan adalah A record alias yang diteruskan ke S3 http endpoint
- S3 static website hosting dikonfigurasi dengan metode redirect dengan protocol https dan diteruskan ke nama domain ludesdeveloper.wordpress.com/about/
- Traffic akan diteruskan ke domain tujuan yang telah dikonfigurasi di poin nomor 2
Konfigurasi
Pada artikel ini, struktur file yang digunakan oleh terraform code sebagai berikut:
modules/
├─ s3/
│ ├─ s3-apse1/
│ │ ├─ static-website-hosting/
│ │ │ ├─ s3.tf
│ │ │ ├─ outputs.tf
│ │ │ ├─ variables.tf
s3/
├─ s3-apse1/
│ ├─ main.tf
│ ├─ outputs.tf
│ ├─ s3.tf
│ ├─ variables.tf
route53/
├─ data.tf
├─ main.tf
├─ records.tf
├─ variables.tf
Directory S3 dan Route53 akan menjadi workspace terpisah di Terraform Cloud. Resource S3 dibuat berdasarkan self managed module yang saya buat dimana di dalamnya dikonfigurasi S3 static website hosting dan beberapa parameter lainnya.
Langkah konfigurasi
- Konfigurasi saya mulai dengan membuat self managed module yang ada di directory modules/s3/s3-apse1. File pertama yang saya diskusikan adalah modules/s3/s3-apse1/s3.tf. Pada file ini, saya membuat template untuk s3 bucket, public access permissions dan bucket static website. Value dari terraform argument saya referensikan dari variable-variable yang sudah saya definisikan sebelumnya di file modules/s3/s3-apse1/variables.tf dan akan saya jelaskan di poin berikutnya.
# Create S3 bucket
resource "aws_s3_bucket" "bucket" {
bucket = var.bucket_name
tags = var.bucket_tags
}
# Public access configuration for S3 bucket
resource "aws_s3_bucket_public_access_block" "bucket_access" {
bucket = aws_s3_bucket.bucket.id
block_public_acls = var.block_public_acls
block_public_policy = var.block_public_policy
ignore_public_acls = var.ignore_public_acls
restrict_public_buckets = var.restrict_public_buckets
}
# Configuration for S3 static website hosting
resource "aws_s3_bucket_website_configuration" "bucket_website_configuration" {
bucket = aws_s3_bucket.bucket.bucket
redirect_all_requests_to {
host_name = var.redirect_host_name
protocol = var.redirect_protocol
}
}
- Berikutnya di file modules/s3/s3-apse1/variables.tf saya definisikan variable-variable yang digunakan di poin nomor 1.
variable "bucket_name" {
type = string
description = "S3 bucket name"
}
variable "bucket_tags" {
type = map(string)
description = "Set key value tags for s3 bucket"
default = {}
}
variable "block_public_acls" {
type = bool
description = "Whether block public acl or not"
default = true
}
variable "block_public_policy" {
type = bool
description = "Whether block public policy or not"
default = true
}
variable "ignore_public_acls" {
type = bool
description = "Whether ignore public acls or not"
default = true
}
variable "restrict_public_buckets" {
type = bool
description = "Whether restrict public buckets or not"
default = true
}
variable "redirect_host_name" {
type = string
description = "Destination hostname for redirect request"
default = true
}
variable "redirect_protocol" {
type = string
description = "Protocol use by redirect host"
default = "https"
}
- Setelah itu di file modules/s3/s3-apse1/outputs.tf, saya deklarasikan output yang nantinya dapat dipanggil di root module. Output berupa bucket website endpoint dan bucket hosted zone id.
# Set outputs
output "bucket_website_endpoint" {
value = aws_s3_bucket_website_configuration.bucket_website_configuration.website_endpoint
}
output "bucket_hosted_zone_id" {
value = aws_s3_bucket.bucket.hosted_zone_id
}
- Setelah child module untuk template s3 static website hosting selesai dibuat, selanjutnya adalah konfigurasi s3 root module. Saya mulai dengan menjelaskan file s3/s3-apse1/main.tf. Di file ini saya akan mendeklarasikan konfigurasi terraform yang akan mengacu ke terraform cloud (app.terraform.io) sebagai backend. Dan mereferensikan nama organisasi dan workspace yang digunakan. Kemudian saya juga deklarasikan terraform provider yang digunakan yaitu hashisorp/aws dengan versi terkait. Di akhir saya deklarasikan region aws yang digunakan, mengacu ke variable aws_region yang ada di file s3/s3-apse1/variables.tf yang berikutnya akan saya jelaskan.
# Setup terraform cloud and workspace
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "lanandra"
workspaces {
name = "s3-ap-southeast-1"
}
}
}
# Setup terraform providers
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.14.0"
}
}
required_version = ">= 1.1.9"
}
# Setup AWS provider
provider "aws" {
region = var.aws_region
}
- Selanjutnya adalah mendefinisikan variable yang digunakan oleh s3 root module di file s3/s3-apse1/variables.tf.
# Setup AWS Region
variable "aws_region" {
type = string
description = "AWS Region"
default = "ap-southeast-1"
}
- Berikutnya di file s3/s3-apse1/s3.tf, saya membuat s3 bucket dengan referensi dari child module static website hosting yang sudah saya buat sebelumnya. Di dalam konfigurasi s3 di root module ini, saya deklarasikan nama bucket, redirect host name atau tujuan url dan tag yang digunakan oleh S3 bucket.
# Create s3 bucket from module
module "ludesdeveloper_com" {
source = "../../modules/s3/s3-apse1/static-website-hosting/"
bucket_name = "ludesdeveloper.com"
redirect_host_name = "ludesdeveloper.wordpress.com/about/"
bucket_tags = {
Name = "ludesdeveloper.com"
Environment = "Production"
Owner = "Luthfi"
}
}
- Selanjutnya di file s3/s3-apse1/outputs.tf, saya mencoba untuk meneruskan menampilkan value atau nilai output bucket website endpoint dan bucket hosted zone id yang sudah dideklarasikan di child module. Nilai output ini nantinya akan digunakan sebagai referensi saat pembuatan nama DNS atau DNS record yang ada di workspace route53.
# Set outputs
output "ludesdeveloper_com_bucket_website_endpoint" {
value = module.ludesdeveloper_com.bucket_website_endpoint
}
output "ludesdeveloper_com_bucket_hosted_zone_id" {
value = module.ludesdeveloper_com.bucket_hosted_zone_id
}
- Berikutnya adalah melakukan commit dan push terraform code ke repository. Dan lakukan terraform plan dan terraform apply di Terraform Cloud workspace agar infrastructure dapat dibuat/provisioned. Untuk bagian ini hanya saya tampilkan simulasinya saja. Jika ingin melihat lebih detail bagaimana proses provisioning resource AWS via Terraform Cloud, silahkan lihat blogpost saya berikut ini. Pertama-tama, saya menjalankan terraform plan dan apply di workspace s3.
- Setelah resource S3 berhasil dibuat oleh Terraform, selanjutnya kita akan masuk ke konfigurasi DNS record di Amazon Route 53. Konfigurasi akan berfokus pada file-file yang ada di dalam directory route53. Sama seperti di directory S3, di directory Route53 terdapat file route53/main.tf yang digunakan untuk mendeklarasikan konfigurasi terraform yang akan mengacu ke terraform cloud (app.terraform.io) sebagai backend. Dan mereferensikan nama organisasi dan workspace yang digunakan. Kemudian saya juga deklarasikan terraform provider yang digunakan yaitu hashisorp/aws dengan versi terkait.
# Setup terraform cloud and workspace
terraform {
backend "remote" {
hostname = "app.terraform.io"
organization = "lanandra"
workspaces {
name = "route53"
}
}
}
# Setup terraform providers
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.14.0"
}
}
required_version = ">= 1.1.9"
}
# Setup AWS provider
provider "aws" {
region = var.aws_region
}
- Berikutnya deklarasi variables di file route53/variables.tf. Disini saya mendeklarasikan variable ludesdeveloper_com_zone_id. Setiap hosted zone di Route53 memiliki ID yang unik. Informasi ini dapat diverifikasi via web console ataupun CLI. Silahkan untuk mengganti default value dari variable zone id dengan ID yang digunakan oleh masing-masing hosted zone.
variable "aws_region" {
type = string
description = "AWS Region"
default = "ap-southeast-1"
}
variable "ludesdeveloper_com_zone_id" {
type = string
description = "ludesdeveloper.com hosted zone ID"
default = "MYHOSTEDZONEID"
}
- Seperti sudah disebutkan sebelumnya, resource DNS record di workspace Route53 memerlukan referensi data yang berupa remote state dari workspace S3, maka saya deklarasikan referensi data tersebut pada file route53/data.tf.
# Get terraform state from other workspaces
data "terraform_remote_state" "s3_ap_southeast_1" {
backend = "remote"
config = {
organization = "lanandra"
workspaces = {
name = "s3-ap-southeast-1"
}
}
}
- Selanjutnya di file route53/records.tf, saya buat DNS record dengan nama ludesdeveloper.com dengan tipe record A. DNS record ini merupakan alias dari S3 website endpoint dimana valuenya direferensikan dari data output bucket website endpoint dan bucket hosted zone id dari workspace S3.
# Create A record with alias to S3 website endpoint
resource "aws_route53_record" "ludesdeveloper_com" {
zone_id = var.ludesdeveloper_com_zone_id
name = "ludesdeveloper.com"
type = "A"
alias {
name = data.terraform_remote_state.s3_ap_southeast_1.outputs.ludesdeveloper_com_bucket_website_endpoint
zone_id = data.terraform_remote_state.s3_ap_southeast_1.outputs.ludesdeveloper_com_bucket_hosted_zone_id
evaluate_target_health = true
}
}
-
Langkah berikutnya adalah melakukan push dan commit ke repository. Kemudian melakukan terraform plan dan apply di workspace route53 seperti yang sudah dilakukan di poin nomor 8.
-
Setelah provisioning resource via terraform sudah selesai. Langkah selanjutnya adalah memastikan resource-resource berhasil terbentuk. Kita dapat menggunakan AWS web console untuk memastikannya. Resource pertama yang akan kita verifikasi adalah S3 bucket. Masuk ke halaman service S3, kemudian masuk ke menu Buckets. Pastikan bucket dengan nama seperti yang didefinisikan di terraform code berhasil terbentuk.
- Selanjutnya masuk ke detail konfigurasi S3 bucket tersebut. Pastikan permission public access sudah sesuai dengan yang didefinisikan di terraform code. Kemudian konfigurasi Static website hosting sudah berhasil terbentuk.
- Setelah verifikasi S3 bucket selesai, selanjutnya kita dapat verifikasi DNS record di Route53. Masuk ke halaman service Route53, kemudian masuk ke menu Hosted zones dan pilih nama domain hosted zone tempat DNS record dibuat. Pastikan DNS record yang dideklarasikan di terraform code sudah berhasil terbentuk.
- Selanjutnya verifikasi http redirect. Saya coba akses ludesdeveloper.com di web browser. Jika di-inspect http redirect sudah berhasil mengarahkan traffic ludesdeveloper.com ke https://ludesdeveloper.wordpress.com/about/.
Kesimpulan
Akhirnya kita sampai di penghujung artikel ini. Ada beberapa kesimpulan atau key takeaways yang ingin saya sampaikan:
- S3 menyediakan fitur static website hosting dengan metode http redirect ke url lain
- Route53 memungkinkan kita untuk membuat DNS record yang dapat meneruskan http redirect S3 website endpoint
- Konfigurasi S3 dan Route53 dapat dilakukan dengan pendekatan IaC. Sehingga kita memiliki state file dari infrastruktur yang sudah kita buat
Silahkan kunjungi GitHub repo saya untuk melihat source code konfigurasi yang digunakan dalam artikel ini. Child module untuk template S3 bucket dengan static website hosting dapat dilihat di S3 Static Website Module. Konfigurasi root module untuk S3 dapat dilihat di directory S3. Dan untuk konfigurasi Route53 dapat dilihat di directory Route53.
Sekian artikel kali ini. Jika ada saran, kritik, atau masukan silahkan tinggalkan di kolom komentar.
Tinggalkan Balasan