Skip to content

Instantly share code, notes, and snippets.

@brett-richardson
Last active March 26, 2024 12:38
Show Gist options
  • Save brett-richardson/edc5a4b9d2d929ce1ada1506e0fb3431 to your computer and use it in GitHub Desktop.
Save brett-richardson/edc5a4b9d2d929ce1ada1506e0fb3431 to your computer and use it in GitHub Desktop.
Deploying a static website with Terraform, S3, CloudFront and CircleCI
version: 2
jobs:
build:
docker: [{ image: "felicianotech/docker-hugo:0.44" }]
working_directory: "~/project"
steps:
- checkout
- run:
name: "Run Hugo"
command: "HUGO_ENV=production hugo -v"
- run:
name: "Test Website"
command: |
htmlproofer src/public \
--allow-hash-href --check-html --empty-alt-ignore --disable-external
- persist_to_workspace: { root: "~/project", paths: ["public"] }
deployment:
docker: [{ image: "circleci/python:latest" }]
working_directory: "~/project"
steps:
- attach_workspace: { at: "~/artifacts" }
- run:
name: "Push to S3"
command: |
pip install --user awscli
export PATH="~/.local/bin:$PATH"
aws s3 sync --acl public-read ~/artifacts/public s3://devbrett.com
workflows:
version: 2
build-test-deploy:
jobs:
- build
- deployment:
requires: ["build"]
filters: { branches: { only: "master" } }
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["s3:*"],
"Effect": "Allow",
"Resource": "${s3_bucket_arn}"
}
]
}
terraform {
backend "s3" {
skip_credentials_validation = true
bucket = "devbrett-terraform-backend"
key = "portfolio-2018.tfstate"
region = "eu-west-2"
}
}
provider "aws" {
version = "~> 1.27"
region = "eu-west-2"
}
provider "aws" {
alias = "global"
version = "~> 1.27"
region = "us-east-1"
}
provider "local" {
version = "~> 1.1"
}
provider "template" {
version = "~> 1.0"
}
resource "aws_iam_user" "circleci" {
name = "circleci"
path = "/system/"
}
resource "aws_iam_access_key" "circleci" {
user = "${aws_iam_user.circleci.name}"
}
data "template_file" "circleci_policy" {
template = "${file("${path.module}/policies/circleci_s3_access.tpl.json")}"
vars { s3_bucket_arn = "${aws_s3_bucket.portfolio.arn}" }
}
resource "local_file" "circle_credentials" {
filename = "tmp/circleci_credentials"
content = "${aws_iam_access_key.circleci.id}\n${aws_iam_access_key.circleci.secret}"
}
resource "aws_iam_user_policy" "circleci" {
name = "AllowCircleCI"
user = "${aws_iam_user.circleci.name}"
policy = "${data.template_file.circleci_policy.rendered}"
}
resource "aws_route53_zone" "primary" {
name = "devbrett.com"
}
resource "aws_route53_record" "www" {
zone_id = "${aws_route53_zone.primary.zone_id}"
name = "www.devbrett.com"
type = "A"
alias {
evaluate_target_health = false
name = "${aws_cloudfront_distribution.portfolio.domain_name}"
zone_id = "${aws_cloudfront_distribution.portfolio.hosted_zone_id}"
}
}
resource "aws_route53_record" "root" {
zone_id = "${aws_route53_zone.primary.zone_id}"
name = "devbrett.com"
type = "A"
alias {
evaluate_target_health = false
name = "${aws_cloudfront_distribution.portfolio.domain_name}"
zone_id = "${aws_cloudfront_distribution.portfolio.hosted_zone_id}"
}
}
locals { s3_origin_id = "portfolio" }
resource "aws_s3_bucket" "portfolio" {
tags { Name = "Portfolio Website Bucket" }
bucket = "devbrett.com"
acl = "public-read"
website {
index_document = "index.html"
error_document = "error.html"
}
}
data "aws_acm_certificate" "devbrett" {
provider = "aws.global"
domain = "devbrett.com"
statuses = ["ISSUED"]
most_recent = true
}
resource "aws_cloudfront_distribution" "portfolio" {
provider = "aws.global"
count = 1
aliases = ["devbrett.com", "www.devbrett.com"]
price_class = "PriceClass_100"
tags { Name = "Portfolio CDN" }
enabled = true
is_ipv6_enabled = true
viewer_certificate {
ssl_support_method = "sni-only"
acm_certificate_arn = "${data.aws_acm_certificate.devbrett.arn}"
}
restrictions {
geo_restriction { restriction_type = "none" }
}
origin {
origin_id = "${local.s3_origin_id}"
domain_name = "${aws_s3_bucket.portfolio.website_endpoint}"
custom_origin_config {
http_port = 80
https_port = 443
origin_protocol_policy = "http-only"
origin_ssl_protocols = ["TLSv1", "TLSv1.1", "TLSv1.2"]
}
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD", "OPTIONS"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "${local.s3_origin_id}"
viewer_protocol_policy = "redirect-to-https"
compress = true
min_ttl = 60
default_ttl = 600
max_ttl = 600
forwarded_values {
query_string = false
cookies { forward = "none" }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment