AWS S3 Bucket Website Redirect through Terraform
- published
- reading time
- 3 minutes
If you ever needed to create a quick website redirect without using any servers you can do so very easily using this Terraform script I’ve created. It will create a SSL key via ACM, S3 Bucket with the redirect setup, A Cloudfront instance and a Route 53 record. You can also endlessy customise it and remove modules as needed. I’ve added helpful comments which show where the next module starts.
First you’ll need to run the following:
apt update
apt install terraform
mkdir s3-redirect
cd s3-redirect
Then paste the following into a file named main.tf (make sure you edit your domains, access and secret keys):
provider "aws" {
access_key = "YOUR_ACCESS_KEY"
secret_key = "YOUR_SECRET_KEY"
region = "us-east-1"
}
variable "root_domain_name" {
default = "example.com"
}
variable "www_domain_name" {
default = "www.example.com"
}
variable "redirect_domain_name" {
default = "redirect-example.com"
}
locals {
origin_id = "${aws_s3_bucket.www.bucket}"
cloudfront-authentication-user-agent = "somethingRandomEen8Ohta"
}
#
# S3 bucket for redirections
#
resource "aws_s3_bucket" "www" {
bucket = "${var.root_domain_name}"
acl = "public-read"
policy = <<POLICY
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::${var.root_domain_name}/*"]
}
]
}
POLICY
website {
redirect_all_requests_to = "https://${var.redirect_domain_name}"
}
}
#
# ACM cert and Route 53 validation
#
resource "aws_acm_certificate" "cert" {
domain_name = "${var.root_domain_name}"
validation_method = "DNS"
subject_alternative_names = ["www.${var.root_domain_name}"]
}
data "aws_route53_zone" "zone" {
name = "${var.root_domain_name}."
private_zone = false
}
resource "aws_route53_record" "cert_validation" {
name = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_name}"
type = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_type}"
zone_id = "${data.aws_route53_zone.zone.id}"
records = ["${aws_acm_certificate.cert.domain_validation_options.0.resource_record_value}"]
ttl = 60
}
resource "aws_route53_record" "cert_validation_www" {
name = "${aws_acm_certificate.cert.domain_validation_options.1.resource_record_name}"
type = "${aws_acm_certificate.cert.domain_validation_options.1.resource_record_type}"
zone_id = "${data.aws_route53_zone.zone.id}"
records = ["${aws_acm_certificate.cert.domain_validation_options.1.resource_record_value}"]
ttl = 60
}
resource "aws_acm_certificate_validation" "cert" {
certificate_arn = "${aws_acm_certificate.cert.arn}"
validation_record_fqdns = ["${aws_route53_record.cert_validation.fqdn}", "${aws_route53_record.cert_validation_www.fqdn}"]
}
#
# Cloudfront Distribution for S3
#
resource "aws_cloudfront_distribution" "distribution" {
origin {
domain_name = "${aws_s3_bucket.www.website_endpoint}"
origin_id = "${local.origin_id}"
custom_origin_config {
http_port = "80"
https_port = "443"
origin_protocol_policy = "http-only"
origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
}
custom_header {
name = "User-Agent"
value = "${local.cloudfront-authentication-user-agent}"
}
}
enabled = true
default_cache_behavior {
allowed_methods = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
cached_methods = ["HEAD", "GET", "OPTIONS"]
target_origin_id = "${local.origin_id}"
forwarded_values {
query_string = false
cookies {
forward = "all"
}
}
viewer_protocol_policy = "redirect-to-https"
min_ttl = 0
default_ttl = 3600
max_ttl = 86400
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = "${aws_acm_certificate.cert.arn}"
ssl_support_method = "sni-only"
}
aliases = ["${var.root_domain_name}", "${var.www_domain_name}"]
depends_on = ["aws_s3_bucket.www", "aws_acm_certificate_validation.cert"]
}
#
# Route 53 DNS Record for Cloudfront
#
resource "aws_route53_record" "root" {
zone_id = "${data.aws_route53_zone.zone.id}"
name = "${var.root_domain_name}"
type = "A"
alias = {
name = "${aws_cloudfront_distribution.distribution.domain_name}"
zone_id = "${aws_cloudfront_distribution.distribution.hosted_zone_id}"
evaluate_target_health = false
}
depends_on = ["aws_s3_bucket.www", "aws_acm_certificate_validation.cert", "aws_cloudfront_distribution.distribution"]
}
resource "aws_route53_record" "www" {
zone_id = "${data.aws_route53_zone.zone.id}"
name = "${var.www_domain_name}"
type = "A"
alias = {
name = "${aws_cloudfront_distribution.distribution.domain_name}"
zone_id = "${aws_cloudfront_distribution.distribution.hosted_zone_id}"
evaluate_target_health = false
}
depends_on = ["aws_s3_bucket.www", "aws_acm_certificate_validation.cert", "aws_cloudfront_distribution.distribution"]
}
To run it you will first need to initialise Terraform on that specific project using:
terraform init
Then run the apply function to run the script:
terraform apply
If you encounter any errors you can re-run the script as Terraform saves the current state automatically.