Skip to content
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
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,30 @@
# terraform-aws-publii-hosting

Terraform module to host a static site generated by Publii

[![Terraform CI](https://github.com/chris-qa-org/terraform-aws-publii-hosting/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/chris-qa-org/terraform-aws-publii-hosting/actions/workflows/main.yml?branch=main)
[![GitHub release](https://img.shields.io/github/release/chris-qa-org/terraform-aws-publii-hosting.svg)](https://github.com/chris-qa-org/terraform-aws-publii-hosting/releases/)

This module launches static hosting resources (eg. S3 bucket, Cloudfront) specifically for sites generated by the Static Site Generator [Publii][1]

It can in most cases be used to host any static site, however this module adds some configurations for the features of [Publii][1]

## Key features:

- Creates an S3 bucket along with an IAM user which has the minimum required permissions to sync from [Publii][1]
- Creates a CloudFront endpoint (And optionally ACM certificates and Route53 records in an existing Hosted Zone)
- Creates a Lambda function to run a Cloudfront Invalidation when `files.publii.json` is created/updated (This file is updated on every sync)
- Optionally have CloudFront do the right thing when 'Pretty URLs' are enabled (This is achieved via a CloudFront function which adds `index.html` to the URI if there is no extention)
- Optionally redirect from the apex domain (eg. example.com) to www (www.example.com). If this is enabled (`var.cloudfront_enable_apex_to_www_redirect`), the 'Website Url' within 'Server' options should be set to www.yourdomain.com - [Publii S3 Server Settings docs (point 26)]
- Optionally enable WAF
- Optionally add custom origins and cache behaviours

## Usage

- [Full launch with existing Route53 Zone](./examples/full-launch-with-existing-route53-zone/README.tf)
- [Use existing certificate and create own Route53 records](./examples/use-existing-certificate-and-create-own-route53-records/README.tf)
- [Adding custom origins and cache behaviours](./examples/adding-custom-origins-and-cache-behaviours/README.tf)

<!-- BEGIN_TF_DOCS -->
## Requirements

Expand Down Expand Up @@ -107,3 +128,7 @@ Terraform module to host a static site generated by Publii
| <a name="output_project_random_id"></a> [project\_random\_id](#output\_project\_random\_id) | The random ID generated to ensure unique resource names |
| <a name="output_s3_bucket_frontend"></a> [s3\_bucket\_frontend](#output\_s3\_bucket\_frontend) | S3 bucket frontend attributes |
<!-- END_TF_DOCS -->

<!-- LINKS -->
[1]: https://getpublii.com/
[2]: https://getpublii.com/docs/setup-static-website-hosting-amazon-s3.html
71 changes: 71 additions & 0 deletions examples/adding-custom-origins-and-cache-behaviours/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Adding custom origins and cache behaviours

- [main.tf](./main.tf)

```
provider "aws" {
region = "us-east-1"
alias = "useast1"
default_tags {
tags = {
Project = "my-project"
}
}
}
resource "aws_route53_zone" "example" {
name = "example.com"
}
module "aws_publii_hosting" {
source = "chris-qa-org/terraform-aws-publii-hosting/aws"
version = "v1.0.0"
providers = {
aws.useast1 = aws.useast1
}
site_url = "example.com"
s3_bucket_acl = "private"
cloudfront_enable_ipv6 = true
cloudfront_enable_waf = true // Note: This will cost at least $5.00/month - https://aws.amazon.com/waf/pricing/ (default: false)
cloudfront_enable_apex_to_www_redirect = true
enable_publii_pretty_urls = true
route53_hosted_zone_options = {
id = aws_route53_zone.example.id
create_certificate_dns_validation_records = true
create_site_url_dns_records = true
}
cloudfront_origins = [
{
domain_name = aws_s3_bucket.example.bucket_regional_domain_name
origin_id = "example-custom-origin"
s3_origin_config = {
origin_access_identity = aws_cloudfront_origin_access_identity.example.cloudfront_access_identity_path
}
}
]
cloudfront_ordered_cache_behaviors = [
{
path_pattern = "/example/*"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "example-custom-origin"
use_forwarded_values = true
query_string = false
headers = ["Origin"]
cookies_forward = "none"
min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
compress = true
viewer_protocol_policy = "redirect-to-https"
}
]
}
```
65 changes: 65 additions & 0 deletions examples/adding-custom-origins-and-cache-behaviours/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
provider "aws" {
region = "us-east-1"
alias = "useast1"
default_tags {
tags = {
Project = "my-project"
}
}
}

resource "aws_route53_zone" "example" {
name = "example.com"
}

module "aws_publii_hosting" {
source = "chris-qa-org/terraform-aws-publii-hosting/aws"
version = "v1.0.0"

providers = {
aws.useast1 = aws.useast1
}

site_url = "example.com"
s3_bucket_acl = "private"
cloudfront_enable_ipv6 = true
cloudfront_enable_waf = true // Note: This will cost at least $5.00/month - https://aws.amazon.com/waf/pricing/ (default: false)
cloudfront_enable_apex_to_www_redirect = true
enable_publii_pretty_urls = true
route53_hosted_zone_options = {
id = aws_route53_zone.example.id
create_certificate_dns_validation_records = true
create_site_url_dns_records = true
}

cloudfront_origins = [
{
domain_name = aws_s3_bucket.example.bucket_regional_domain_name
origin_id = "example-custom-origin"

s3_origin_config = {
origin_access_identity = aws_cloudfront_origin_access_identity.example.cloudfront_access_identity_path
}
}
]

cloudfront_ordered_cache_behaviors = [
{
path_pattern = "/example/*"
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "example-custom-origin"

use_forwarded_values = true
query_string = false
headers = ["Origin"]
cookies_forward = "none"

min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
compress = true
viewer_protocol_policy = "redirect-to-https"
}
]
}
40 changes: 40 additions & 0 deletions examples/full-launch-with-existing-route53-zone/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Full launch with existing Route53 Zone

- [main.tf](./main.tf)

```
provider "aws" {
region = "us-east-1"
alias = "useast1"
default_tags {
tags = {
Project = "my-project"
}
}
}
resource "aws_route53_zone" "example" {
name = "example.com"
}
module "aws_publii_hosting" {
source = "chris-qa-org/terraform-aws-publii-hosting/aws"
version = "v1.0.0"
providers = {
aws.useast1 = aws.useast1
}
site_url = "example.com"
s3_bucket_acl = "private"
cloudfront_enable_ipv6 = true
cloudfront_enable_waf = true // Note: This will cost at least $5.00/month - https://aws.amazon.com/waf/pricing/ (default: false)
cloudfront_enable_apex_to_www_redirect = true
enable_publii_pretty_urls = true
route53_hosted_zone_options = {
id = aws_route53_zone.example.id
create_certificate_dns_validation_records = true
create_site_url_dns_records = true
}
}
```
34 changes: 34 additions & 0 deletions examples/full-launch-with-existing-route53-zone/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
provider "aws" {
region = "us-east-1"
alias = "useast1"
default_tags {
tags = {
Project = "my-project"
}
}
}

resource "aws_route53_zone" "example" {
name = "example.com"
}

module "aws_publii_hosting" {
source = "chris-qa-org/terraform-aws-publii-hosting/aws"
version = "v1.0.0"

providers = {
aws.useast1 = aws.useast1
}

site_url = "example.com"
s3_bucket_acl = "private"
cloudfront_enable_ipv6 = true
cloudfront_enable_waf = true // Note: This will cost at least $5.00/month - https://aws.amazon.com/waf/pricing/ (default: false)
cloudfront_enable_apex_to_www_redirect = true
enable_publii_pretty_urls = true
route53_hosted_zone_options = {
id = aws_route53_zone.example.id
create_certificate_dns_validation_records = true
create_site_url_dns_records = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Use existing certificate and create own Route53 records

- [main.tf](./main.tf)

```
provider "aws" {
region = "us-east-1"
alias = "useast1"
default_tags {
tags = {
Project = "my-project"
}
}
}
module "aws_publii_hosting" {
source = "chris-qa-org/terraform-aws-publii-hosting/aws"
version = "v1.0.0"
providers = {
aws.useast1 = aws.useast1
}
site_url = "example.com"
s3_bucket_acl = "private"
cloudfront_tls_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
cloudfront_enable_ipv6 = true
cloudfront_enable_waf = true // Note: This will cost at least $5.00/month - https://aws.amazon.com/waf/pricing/ (default: false)
cloudfront_enable_apex_to_www_redirect = true
enable_publii_pretty_urls = true
}
resource "aws_route53_zone" "example" {
name = "example.com"
}
resource "aws_route53_record" "frontend" {
zone_id = aws_route53_zone.example.zone_id
name = "www.example.com"
type = "A"
alias {
name = module.aws_publii_hosting.aws_cloudfront_distribution_frontend.domain_name
zone_id = module.aws_publii_hosting.aws_cloudfront_distribution_frontend.hosted_zone_id
evaluate_target_health = true
}
}
resource "aws_route53_record" "apex_redirect" {
zone_id = aws_route53_zone.example.zone_id
name = "example.com"
type = "A"
alias {
name = module.aws_publii_hosting.aws_cloudfront_distribution_frontend_www_redirect.domain_name
zone_id = module.aws_publii_hosting.aws_cloudfront_distribution_frontend_www_redirect.hosted_zone_id
evaluate_target_health = true
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
provider "aws" {
region = "us-east-1"
alias = "useast1"
default_tags {
tags = {
Project = "my-project"
}
}
}

module "aws_publii_hosting" {
source = "chris-qa-org/terraform-aws-publii-hosting/aws"
version = "v1.0.0"

providers = {
aws.useast1 = aws.useast1
}

site_url = "example.com"
s3_bucket_acl = "private"
cloudfront_tls_certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
cloudfront_enable_ipv6 = true
cloudfront_enable_waf = true // Note: This will cost at least $5.00/month - https://aws.amazon.com/waf/pricing/ (default: false)
cloudfront_enable_apex_to_www_redirect = true
enable_publii_pretty_urls = true
}

resource "aws_route53_zone" "example" {
name = "example.com"
}

resource "aws_route53_record" "frontend" {
zone_id = aws_route53_zone.example.zone_id
name = "www.example.com"
type = "A"

alias {
name = module.aws_publii_hosting.aws_cloudfront_distribution_frontend.domain_name
zone_id = module.aws_publii_hosting.aws_cloudfront_distribution_frontend.hosted_zone_id
evaluate_target_health = true
}
}

resource "aws_route53_record" "apex_redirect" {
zone_id = aws_route53_zone.example.zone_id
name = "example.com"
type = "A"

alias {
name = module.aws_publii_hosting.aws_cloudfront_distribution_frontend_www_redirect.domain_name
zone_id = module.aws_publii_hosting.aws_cloudfront_distribution_frontend_www_redirect.hosted_zone_id
evaluate_target_health = true
}
}