dumpnet-argo/terraform/repertory-frontend.tf

148 lines
4.3 KiB
Terraform
Raw Normal View History

2026-09-14 13:37:00 -04:00
# Static site hosting for the repertory frontend (tunes.dumpnet.chat)
# S3 static website hosting behind CloudFront (for HTTPS) + ACM cert.
# NOTE: bucket name currently matches the live hostname (repertory.dumpnet.chat)
# because it's also used as an S3-website CNAME target internally. When this
# moves to tunes.dumpnet.chat, rename the bucket + update the Route53 record
# + alt name below to match.
resource "aws_s3_bucket" "repertory_frontend" {
bucket = "repertory.dumpnet.chat"
force_destroy = true
}
resource "aws_s3_bucket_website_configuration" "repertory_frontend" {
bucket = aws_s3_bucket.repertory_frontend.id
index_document {
suffix = "index.html"
}
}
resource "aws_s3_bucket_public_access_block" "repertory_frontend" {
bucket = aws_s3_bucket.repertory_frontend.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_policy" "repertory_frontend" {
bucket = aws_s3_bucket.repertory_frontend.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Sid = "PublicReadGetObject"
Effect = "Allow"
Principal = "*"
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.repertory_frontend.arn}/*"
}
]
})
depends_on = [aws_s3_bucket_public_access_block.repertory_frontend]
}
# --- ACM cert for CloudFront (must be in us-east-1, which this provider already is) ---
resource "aws_acm_certificate" "repertory_frontend" {
domain_name = "repertory.${var.domain}"
validation_method = "DNS"
lifecycle {
create_before_destroy = true
}
}
resource "aws_route53_record" "repertory_frontend_cert_validation" {
for_each = {
for dvo in aws_acm_certificate.repertory_frontend.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
zone_id = data.aws_route53_zone.dumpnet.zone_id
name = each.value.name
type = each.value.type
records = [each.value.record]
ttl = 300
}
resource "aws_acm_certificate_validation" "repertory_frontend" {
certificate_arn = aws_acm_certificate.repertory_frontend.arn
validation_record_fqdns = [for r in aws_route53_record.repertory_frontend_cert_validation : r.fqdn]
}
# --- CloudFront distribution in front of the S3 website endpoint ---
resource "aws_cloudfront_distribution" "repertory_frontend" {
enabled = true
default_root_object = "index.html"
aliases = ["repertory.${var.domain}"]
origin {
domain_name = aws_s3_bucket_website_configuration.repertory_frontend.website_endpoint
origin_id = "repertory-frontend-s3-website"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only" # S3 website endpoints are HTTP-only
origin_ssl_protocols = ["TLSv1.2"]
}
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "repertory-frontend-s3-website"
viewer_protocol_policy = "redirect-to-https"
forwarded_values {
query_string = false
cookies {
forward = "none"
}
}
}
restrictions {
geo_restriction {
restriction_type = "none"
}
}
viewer_certificate {
acm_certificate_arn = aws_acm_certificate_validation.repertory_frontend.certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
}
resource "aws_route53_record" "repertory_frontend" {
zone_id = data.aws_route53_zone.dumpnet.zone_id
name = "repertory.${var.domain}"
type = "A"
alias {
name = aws_cloudfront_distribution.repertory_frontend.domain_name
zone_id = aws_cloudfront_distribution.repertory_frontend.hosted_zone_id
evaluate_target_health = false
}
}
output "repertory_frontend_bucket" {
value = aws_s3_bucket.repertory_frontend.id
}
output "repertory_frontend_website_endpoint" {
value = aws_s3_bucket_website_configuration.repertory_frontend.website_endpoint
}
output "repertory_frontend_cloudfront_domain" {
value = aws_cloudfront_distribution.repertory_frontend.domain_name
}