Moves to DigitalOcean from AWS (#4)

* Moves to DigitalOcean from AWS

* README

* Removes deployment workflow

---------

Co-authored-by: Joe Carstairs <65492573+Sycamost@users.noreply.github.com>
This commit is contained in:
Joe Carstairs
2024-05-10 21:57:35 +01:00
committed by GitHub
parent efb931b1b8
commit 88c6e8a658
12 changed files with 94 additions and 315 deletions

View File

@@ -1,25 +1,26 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "4.67.0"
constraints = "~> 4.16"
provider "registry.terraform.io/digitalocean/digitalocean" {
version = "2.38.0"
constraints = "~> 2.0"
hashes = [
"h1:LfOuBkdYCzQhtiRvVIxdP/KGJODa3cRsKjn8xKCTbVY=",
"zh:0843017ecc24385f2b45f2c5fce79dc25b258e50d516877b3affee3bef34f060",
"zh:19876066cfa60de91834ec569a6448dab8c2518b8a71b5ca870b2444febddac6",
"zh:24995686b2ad88c1ffaa242e36eee791fc6070e6144f418048c4ce24d0ba5183",
"zh:4a002990b9f4d6d225d82cb2fb8805789ffef791999ee5d9cb1fef579aeff8f1",
"zh:559a2b5ace06b878c6de3ecf19b94fbae3512562f7a51e930674b16c2f606e29",
"zh:6a07da13b86b9753b95d4d8218f6dae874cf34699bca1470d6effbb4dee7f4b7",
"zh:768b3bfd126c3b77dc975c7c0e5db3207e4f9997cf41aa3385c63206242ba043",
"zh:7be5177e698d4b547083cc738b977742d70ed68487ce6f49ecd0c94dbf9d1362",
"zh:8b562a818915fb0d85959257095251a05c76f3467caa3ba95c583ba5fe043f9b",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:9c385d03a958b54e2afd5279cd8c7cbdd2d6ca5c7d6a333e61092331f38af7cf",
"zh:b3ca45f2821a89af417787df8289cb4314b273d29555ad3b2a5ab98bb4816b3b",
"zh:da3c317f1db2469615ab40aa6baba63b5643bae7110ff855277a1fb9d8eb4f2c",
"zh:dc6430622a8dc5cdab359a8704aec81d3825ea1d305bbb3bbd032b1c6adfae0c",
"zh:fac0d2ddeadf9ec53da87922f666e1e73a603a611c57bcbc4b86ac2821619b1d",
"h1:ElG5GAiHN6paMNUG0JnQ4uCv1Y37ZUbCXQSAQwb/j8U=",
"zh:04d1ca6ac6d7e69635657aeac8aadb75f84018305514381f9d7bed48065df61b",
"zh:081258f8526b3597eeb7154d5b453c2fe36194ca1a95e0de655d7a1080224be0",
"zh:15e77088b8a73012d87ad29ad3cf10392642a6781a35c0923a45386fe61cda61",
"zh:1a0c741f9be0f22c18fec93b4200c1968c1c6e4ac02292d494ace78b16f13fea",
"zh:2a3a778cd982e5e09a2414f0a16c54101c56d7ab6f824ea3e55709a608f7f3ea",
"zh:6832b594a7e408e085bf148c5a1e2eaf94ed8f47796b917acf56078ee9362ca1",
"zh:78b8acad99e7035344677f70c08c3daf457cfa3f8b467e73352d14353889b8cf",
"zh:8a1c446f1b3b5dee097fc000cf4d341b00602ace60246af4a09e5a49666a0638",
"zh:8c23094d06f5b4c780dbdde21c56b9b03b275c1cc8728669ef8f3f45e0d9fb24",
"zh:8c5a9871c2a2e094f58723624bb3fd2dbedafc8d9cab609df79d01011de79b8a",
"zh:a32adff1d0fc405f1596b6dc679b3029c87177e717eb991c418fff13ec559427",
"zh:a3f89176401db06ccc97b89a23bb004c8ab1562ce04178d6a08125bd4b8c073e",
"zh:d739de876cdd6176570c610e0edca0d2133b8e21787f22caa9a72d9806055c07",
"zh:d8a874a0e442c10deae3217bb88375209d45f79d52cb7d2b19756863d6ab6414",
"zh:eac47cd0b28953404622d11d8d4049ce2a4da3bc0a0ecaf386e5f55117386bbd",
"zh:ec3686163d1177d41f13588bb24db9a2b3afd199ac410d8c9899f053f271515c",
]
}

View File

@@ -1,4 +0,0 @@
data "aws_acm_certificate" "joeac_ssl_certificate" {
domain = local.domain
statuses = ["ISSUED"]
}

53
infrastructure/app.tf Normal file
View File

@@ -0,0 +1,53 @@
resource "digitalocean_app" "joeac_net" {
project_id = "c106269c-1115-4682-8757-867368e057a4"
spec {
name = "joeac-net"
region = local.region
domain {
name = local.domain
}
features = [
"buildpack-stack=ubuntu-22"
]
alert {
disabled = false
rule = "DEPLOYMENT_FAILED"
}
alert {
disabled = false
rule = "DOMAIN_FAILED"
}
ingress {
rule {
component {
name = "personal-website"
preserve_path_prefix = false
}
match {
path {
prefix = "/"
}
}
}
}
static_site {
build_command = "npm run build"
environment_slug = "node-js"
name = "personal-website"
output_dir = "website/dist"
source_dir = "/"
github {
branch = "main"
deploy_on_push = true
repo = "joeacarstairs/personal-website"
}
}
}
}

View File

@@ -1,59 +0,0 @@
resource "aws_cloudfront_distribution" "joeac" {
enabled = true
is_ipv6_enabled = true
default_root_object = "index.html"
price_class = "PriceClass_100"
aliases = ["joeac.net"]
origin {
domain_name = aws_s3_bucket_website_configuration.website.website_endpoint
origin_id = local.website_origin_id
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", "OPTIONS"]
target_origin_id = local.website_origin_id
cache_policy_id = data.aws_cloudfront_cache_policy.caching_optimized.id
viewer_protocol_policy = "redirect-to-https"
}
restrictions {
geo_restriction {
restriction_type = "none"
locations = []
}
}
viewer_certificate {
acm_certificate_arn = data.aws_acm_certificate.joeac_ssl_certificate.arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}
depends_on = [aws_cloudfront_origin_access_control.website]
}
resource "aws_cloudfront_origin_access_control" "website" {
name = "website"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
data "aws_cloudfront_cache_policy" "caching_optimized" {
name = "Managed-CachingOptimized"
}
locals {
website_origin_id = "website"
}

View File

@@ -1,5 +1,5 @@
locals {
aws_region = "us-east-1"
domain = "joeac.net"
domain = "joeac.net"
region = "lon"
}

View File

@@ -1,11 +1,9 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.16"
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0"
}
}
required_version = ">= 1.2.0"
}

View File

@@ -1,12 +1,4 @@
provider "aws" {
region = local.aws_region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
default_tags {
tags = {
project = "joeac-website"
owner = "terraform"
}
}
provider "digitalocean" {
token = var.do_token
}

View File

@@ -1,35 +0,0 @@
# This hosted zone must have NS records which point to the same nameservers as
# those listed with the domain registrar. Right now, this means manually going
# into Route53Domains, finding the nameservers, and manually copying these into
# the NS records for this hosted zone.
resource "aws_route53_zone" "joeac_zone" {
name = "joeac.net"
}
resource "aws_route53_record" "cloudfront" {
# This is the subdomain for the record. Specify the root domain by leaving it blank
name = ""
zone_id = aws_route53_zone.joeac_zone.id
type = "A"
alias {
name = aws_cloudfront_distribution.joeac.domain_name
zone_id = aws_cloudfront_distribution.joeac.hosted_zone_id
evaluate_target_health = false
}
}
resource "aws_route53_record" "cloudfront_aaaa" {
# This is the subdomain for the record. Specify the root domain by leaving it blank
name = ""
zone_id = aws_route53_zone.joeac_zone.id
type = "AAAA"
alias {
name = aws_cloudfront_distribution.joeac.domain_name
zone_id = aws_cloudfront_distribution.joeac.hosted_zone_id
evaluate_target_health = false
}
}

View File

@@ -1,78 +0,0 @@
resource "aws_s3_bucket" "website" {
bucket = local.bucket_name
}
locals {
bucket_name = "${local.domain}-${var.secret_s3_bucket_suffix}"
}
resource "aws_s3_bucket_website_configuration" "website" {
bucket = aws_s3_bucket.website.id
index_document {
suffix = "index.html"
}
error_document {
key = "error/index.html"
}
}
resource "aws_s3_bucket_ownership_controls" "website" {
bucket = aws_s3_bucket.website.id
rule {
object_ownership = "BucketOwnerPreferred"
}
depends_on = [aws_s3_bucket_public_access_block.website]
}
resource "aws_s3_bucket_public_access_block" "website" {
bucket = aws_s3_bucket.website.id
block_public_acls = false
block_public_policy = false
ignore_public_acls = false
restrict_public_buckets = false
}
resource "aws_s3_bucket_acl" "website" {
bucket = aws_s3_bucket.website.id
acl = "public-read"
depends_on = [aws_s3_bucket_ownership_controls.website]
}
resource "aws_s3_bucket_versioning" "website" {
bucket = aws_s3_bucket.website.id
versioning_configuration {
status = "Disabled"
}
}
resource "aws_s3_bucket_policy" "website" {
bucket = aws_s3_bucket.website.id
policy = data.aws_iam_policy_document.website.json
}
# TODO: can we restrict access to just from the CloudFront distro?
data "aws_iam_policy_document" "website" {
statement {
sid = "AllowPublicRead"
effect = "Allow"
resources = [
"arn:aws:s3:::${local.bucket_name}",
"arn:aws:s3:::${local.bucket_name}/*",
]
actions = ["S3:GetObject"]
principals {
type = "*"
identifiers = ["*"]
}
}
depends_on = [aws_s3_bucket_public_access_block.website, aws_s3_bucket.website]
}

View File

@@ -1,28 +1,5 @@
variable "aws_access_key" {
variable "do_token" {
type = string
sensitive = true
description = "An AWS access key with permission to provision all relevant resources"
}
variable "aws_secret_key" {
type = string
sensitive = true
description = "The secret corresponding to the provided AWS access key"
}
variable "secret_s3_bucket_suffix" {
type = string
sensitive = true
description = "This string should be a long string of up to 54 random characters. It will be appended to the S3 bucket name to mitigate the risk of DDoS attacks."
nullable = false
validation {
condition = length(var.secret_s3_bucket_suffix) > 12
error_message = "This string should be at least 12 characters"
}
validation {
condition = length(var.secret_s3_bucket_suffix) <= 54
error_message = "This string should be no more than 54 characters long"
}
description = "A DigitalOcean access token. Can also be provided as an environment variable"
}