Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Usage of ACM certificate instead of CloudFront #134

Merged
merged 6 commits into from
Aug 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions examples/with-custom-domain/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Custom Domain Example

This example shows how to configure a custom domain for the [Terraform Next.js Image Optimization module for AWS](https://github.com/milliHQ/terraform-aws-next-js-image-optimization).

> **Note:** The full example code is available on [GitHub](https://github.com/milliHQ/terraform-aws-next-js-image-optimization/tree/main/examples/with-custom-domain)

## Setup the Terraform module

1. Create a new file called `main.tf` and paste the code from the following source: [main.tf on GitHub](https://github.com/milliHQ/terraform-aws-next-js-image-optimization/blob/main/examples/with-custom-domain/main.tf):

2. Then configure the domain you want to use:

```tf
# main.tf

...
###########
# Variables
###########

variable "custom_domain" {
description = "Your custom domain"
type = string
default = "example.com"
}

variable "custom_domain_zone_name" {
description = "The Route53 zone name of the custom domain"
type = string
default = "example.com."
}

...
```

3. Run Terraform to deploy the image optimizer to your AWS account:

```sh
terraform init # Only needed on the first time running Terraform

terraform plan # (Optional) See what resources Terraform will create
terraform apply # Deploy the image optimizer module to your AWS account
```

After Terraform has successfully created all resources in your AWS account, you should see the following output on the terminal:

```sh
> Apply complete!
>
> Outputs:
>
> custom_domain = "example.com"
> cloudfront_domain = "<distribution-id>.cloudfront.net"
```

4. Integrate with Next.js by editing `next.config.js`:

```diff
// next.config.js

module.exports = {
+ images: {
+ path: 'https://example.com/_next/image'
+ },
}
```
98 changes: 98 additions & 0 deletions examples/with-custom-domain/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}

# AWS region where the image optimizer should be deployed to.
# While the optimized images are cached globally (via CloudFront CDN) this
# determines the location where the optimization (Lambda) should happen, when
# the cache is missed.
provider "aws" {
region = "us-east-1"
}

###########
# Variables
###########

variable "custom_domain" {
description = "Your custom domain"
type = string
default = "example.com"
}

# Assuming that the hosted ZONE of your domain is already registered in your
# AWS account (Route 53)
# https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/AboutHZWorkingWith.html
variable "custom_domain_zone_name" {
description = "The Route53 zone name of the custom domain"
type = string
default = "example.com."
}

# Get the hosted zone for the custom domain
data "aws_route53_zone" "custom_domain_zone" {
name = var.custom_domain_zone_name
}

# Create a new record in Route 53 for the domain
resource "aws_route53_record" "cloudfront_alias_domain" {
zone_id = data.aws_route53_zone.custom_domain_zone.zone_id
name = each.key
type = "A"

alias {
name = module.next_image_optimizer.cloudfront_domain_name
zone_id = module.next_image_optimizer.cloudfront_hosted_zone_id
evaluate_target_health = false
}
}

##########
# SSL Cert
##########

# Creates a free SSL certificate for CloudFront distribution
# For more options (e.g. multiple domains) see:
# https://registry.terraform.io/modules/terraform-aws-modules/acm/aws/
module "cloudfront_cert" {
source = "terraform-aws-modules/acm/aws"
version = "~> 3.0"

domain_name = var.custom_domain
zone_id = data.aws_route53_zone.custom_domain_zone.zone_id
subject_alternative_names = slice(local.aliases, 1, length(local.aliases))

tags = {
Name = "CloudFront ${var.custom_domain}"
}

# CloudFront works only with certs stored in us-east-1
providers = {
aws = aws.global_region
}
}

#######################
# Route53 Domain record
#######################

module "next_image_optimizer" {
source = "milliHQ/next-js-image-optimization/aws"

cloudfront_aliases = [var.custom_domain]
cloudfront_acm_certificate_arn = module.cloudfront_cert.acm_certificate_arn
next_image_domains = ["assets.vercel.com"]
}

output "custom_domain" {
value = var.custom_domain
}

output "cloudfront_domain" {
value = module.next_image_optimizer.cloudfront_domain_name
}
11 changes: 7 additions & 4 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,13 @@ resource "aws_cloudfront_cache_policy" "this" {
module "cloudfront" {
source = "./modules/cloudfront-cache"

cloudfront_create_distribution = var.cloudfront_create_distribution
cloudfront_price_class = var.cloudfront_price_class
cloudfront_origin = local.cloudfront_origin
cloudfront_default_behavior = local.cloudfront_cache_behavior
cloudfront_create_distribution = var.cloudfront_create_distribution
cloudfront_price_class = var.cloudfront_price_class
cloudfront_origin = local.cloudfront_origin
cloudfront_default_behavior = local.cloudfront_cache_behavior
cloudfront_minimum_protocol_version = var.cloudfront_minimum_protocol_version
cloudfront_acm_certificate_arn = var.cloudfront_acm_certificate_arn
cloudfront_aliases = var.cloudfront_aliases

deployment_name = var.deployment_name
tags = var.tags
Expand Down
6 changes: 5 additions & 1 deletion modules/cloudfront-cache/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ resource "aws_cloudfront_distribution" "distribution" {
is_ipv6_enabled = true
comment = var.deployment_name
price_class = var.cloudfront_price_class
aliases = var.cloudfront_aliases

dynamic "default_cache_behavior" {
for_each = [var.cloudfront_default_behavior]
Expand Down Expand Up @@ -68,7 +69,10 @@ resource "aws_cloudfront_distribution" "distribution" {
}

viewer_certificate {
cloudfront_default_certificate = true
acm_certificate_arn = var.cloudfront_acm_certificate_arn
cloudfront_default_certificate = var.cloudfront_acm_certificate_arn == null
minimum_protocol_version = var.cloudfront_minimum_protocol_version
ssl_support_method = var.cloudfront_acm_certificate_arn != null ? "sni-only" : null
}

restrictions {
Expand Down
14 changes: 14 additions & 0 deletions modules/cloudfront-cache/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,17 @@ variable "deployment_name" {
variable "tags" {
type = map(string)
}

variable "cloudfront_minimum_protocol_version" {
type = string
}

variable "cloudfront_acm_certificate_arn" {
type = string
default = null
}

variable "cloudfront_aliases" {
type = list(string)
default = []
}
20 changes: 19 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ variable "cloudfront_enable_origin_shield" {
}

variable "cloudfront_origin_shield_region" {
description = "Override the region choosen for the CloudFront origin shield. Use `auto` to automatically determine the optimal region."
description = "Override the region chosen for the CloudFront origin shield. Use `auto` to automatically determine the optimal region."
type = string
default = "auto"
}
Expand All @@ -129,6 +129,24 @@ variable "cloudfront_origin_id" {
default = "tf-next-image-optimizer"
}

variable "cloudfront_minimum_protocol_version" {
description = "The minimum version of the SSL protocol that you want CloudFront to use for HTTPS connections. One of SSLv3, TLSv1, TLSv1_2016, TLSv1.1_2016, TLSv1.2_2018 TLSv1.2_2019 or TLSv1.2_2021."
type = string
default = "TLSv1"
}

variable "cloudfront_acm_certificate_arn" {
description = "CloudFront ACM certificate to use."
type = string
default = null
}

variable "cloudfront_aliases" {
description = "Custom domain(s) for CloudFront."
type = list(string)
default = []
}

##########
# Labeling
##########
Expand Down