Skip to content

Commit

Permalink
chore: Migrate to Terraform/OpenTofu remote state
Browse files Browse the repository at this point in the history
Terraform state should not live in Git repos, and should instead be
securely stored on a remote backend. This is that change.
  • Loading branch information
evancharlton committed Dec 7, 2024
1 parent 1843269 commit 20dc7a7
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 96 deletions.
72 changes: 49 additions & 23 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,46 +1,72 @@
name: Build and Deploy
on: [push]
on:
push:
branches:
- main
jobs:
build-and-deploy:
build:
permissions:
id-token: write
contents: read

runs-on: ubuntu-latest
steps:
- uses: opentofu/setup-opentofu@v1
- name: Checkout 🛎️
uses: actions/checkout@v4
with:
submodules: "true"
persist-credentials: false
submodules: "true"
token: ${{ secrets.ORDLIST_TOKEN }}

- name: Install
env:
PUBLIC_URL: /
run: |
npm ci
- id: "auth"
name: "Authenticate to Google Cloud"
uses: "google-github-actions/auth@v2"
with:
create_credentials_file: true
workload_identity_provider: "projects/594849475420/locations/global/workloadIdentityPools/github-pool/providers/github-provider"

- uses: opentofu/setup-opentofu@v1

- name: "Set environment variables"
run: |
echo "VITE_RELEASE=${GITHUB_SHA:0:8}" >> $GITHUB_ENV
- name: Build
- name: Install and Build 🔧
env:
PUBLIC_URL: /
run: |
./build.sh
- run: tofu init
- id: plan
run: tofu plan -no-color
- name: Terraform
run: |
tofu init
tofu plan -no-color
tofu state rm cloudflare_zone_settings_override.ssl_settings || true
tofu apply -auto-approve
env:
TF_VAR_cloudflare_api_token: ${{ secrets.TF_VAR_cloudflare_api_token }}
TF_VAR_github_token: ${{ secrets.TF_VAR_github_token }}
TF_LOG: ${{ vars.TF_LOG }}

- name: Deploy 🚀
uses: JamesIves/github-pages-deploy-action@v4
- name: Upload static files as artifact
id: deployment
uses: actions/upload-pages-artifact@v3
with:
branch: gh-pages # The branch the action should deploy to.
folder: dist # The folder the action should deploy.
clean: true # Automatically remove deleted files from the deploy branch
path: dist/

- run: |
tofu state rm cloudflare_zone_settings_override.ssl_settings
tofu apply -auto-approve
env:
TF_VAR_cloudflare_api_token: ${{ secrets.TF_VAR_cloudflare_api_token }}
deploy:
needs: build

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
6 changes: 6 additions & 0 deletions backend.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
terraform {
backend "gcs" {
prefix = "ordle/terraform"
bucket = "terraform-remote-backend-2180c2249d350f10"
}
}
214 changes: 142 additions & 72 deletions ordle.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,107 +4,177 @@ terraform {
source = "cloudflare/cloudflare"
version = "~> 4"
}
github = {
source = "integrations/github"
version = "6.4.0"
}
google = {
source = "hashicorp/google"
version = "6.12.0"
}
}
}

locals {
# Zone IDs from Cloudflare
zones = {
"ordle-app.no" = "639b49d65fe403a6d1bdc89b416f7619"
}

project = "ordle"

main_domain = "ordle-app.no"
redirects = [
]

github_owner = "evancharlton"
github_challenge = "085db663e91db52924a0d7719dbf11"
}

resource "github_repository" "github_repo" {
name = "ordle"
description = "Wordle, på norsk!"
homepage_url = "https://${local.main_domain}"

visibility = "public"
has_discussions = false
has_downloads = false
has_issues = true
allow_auto_merge = true
allow_merge_commit = false
allow_rebase_merge = false
allow_squash_merge = true
squash_merge_commit_title = "PR_TITLE"
squash_merge_commit_message = "PR_BODY"
delete_branch_on_merge = true

license_template = "mit"

pages {
build_type = "workflow"
cname = local.main_domain
}
}

variable "cloudflare_api_token" {
default = ""
}

locals {
zones = {
"ordle-app.no" = "639b49d65fe403a6d1bdc89b416f7619"
}
variable "github_token" {
default = ""
}

variable "google_token" {
default = ""
}

provider "cloudflare" {
api_token = var.cloudflare_api_token
}

resource "cloudflare_record" "a_records" {
for_each = {
for val in setproduct(
toset(["ordle-app.no"]),
[
"185.199.111.153",
"185.199.110.153",
"185.199.109.153",
"185.199.108.153"
]
) : "${val[0]}-${val[1]}" => {
domain = val[0]
ip = val[1]
provider "github" {
token = var.github_token
}

provider "google" {
project = "ordspill"
region = "europe-west10"
}

resource "local_file" "default" {
file_permission = "0644"
filename = "${path.module}/backend.tf"

# You can store the template in a file and use the templatefile function for
# more modularity, if you prefer, instead of storing the template inline as
# we do here.

# TODO: Can we source the bucket name from somewhere?
content = <<-EOT
terraform {
backend "gcs" {
prefix = "${local.project}/terraform"
bucket = "terraform-remote-backend-2180c2249d350f10"
}
}
zone_id = local.zones[each.value.domain]
content = each.value.ip
name = each.value.domain
EOT
}

resource "cloudflare_record" "a_records" {
for_each = toset([
"185.199.111.153",
"185.199.110.153",
"185.199.109.153",
"185.199.108.153"
])
zone_id = local.zones[local.main_domain]
content = each.value
name = local.main_domain
proxied = true
ttl = 1
type = "A"
}

resource "cloudflare_record" "aaaa_records" {
for_each = {
for val in setproduct(
toset(["ordle-app.no"]),
[
"2606:50c0:8003::153",
"2606:50c0:8002::153",
"2606:50c0:8001::153",
"2606:50c0:8000::153"
]
) : "${val[0]}-${val[1]}" => {
domain = val[0]
ip = val[1]
}
}
zone_id = local.zones[each.value.domain]
content = each.value.ip
name = each.value.domain
for_each = toset([
"2606:50c0:8003::153",
"2606:50c0:8002::153",
"2606:50c0:8001::153",
"2606:50c0:8000::153"
])
zone_id = local.zones[local.main_domain]
content = each.value
name = local.main_domain
proxied = true
ttl = 1
type = "AAAA"
}

resource "cloudflare_record" "txt_records_no" {
for_each = {
# Tell recipients that this domain will never send email
"_dmarc" = "v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s;",
"*._domainkey" = "v=DKIM1; p=",
"ordle-app.no" = "v=spf1 -all",
"_github-pages-challenge-evancharlton" = "085db663e91db52924a0d7719dbf11",
}
zone_id = local.zones["ordle-app.no"]
name = each.key
content = each.value
proxied = false
ttl = 1
type = "TXT"
resource "cloudflare_record" "mail_records_dmarc" {
for_each = setunion([local.main_domain], local.redirects)
zone_id = local.zones[each.value]
name = "_dmarc"
content = "'v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s;'"
proxied = false
ttl = 1
type = "TXT"
}

resource "cloudflare_record" "cname_no" {
for_each = {
"www" = "ordle-app.no"
}
zone_id = local.zones["ordle-app.no"]
name = each.key
content = each.value
proxied = true
ttl = 1
type = "CNAME"
resource "cloudflare_record" "mail_records_domainkey" {
for_each = setunion([local.main_domain], local.redirects)
zone_id = local.zones[each.value]
name = "*._domainkey"
content = "'v=DKIM1; p='"
proxied = false
ttl = 1
type = "TXT"
}

# NOTE: There's a bug in Cloudflare somewhere with this. If you run into
# problems, try this:
# tofu state rm cloudflare_zone_settings_override.ssl_settings
#
# https://github.com/cloudflare/terraform-provider-cloudflare/issues/1297
resource "cloudflare_zone_settings_override" "ssl_settings" {
zone_id = local.zones["ordle-app.no"]
resource "cloudflare_record" "mail_records_spf" {
for_each = setunion([local.main_domain], local.redirects)
zone_id = local.zones[each.value]
name = each.value
content = "'v=spf1 -all'"
proxied = false
ttl = 1
type = "TXT"
}

settings {
automatic_https_rewrites = "on"
ssl = "flexible"
}
resource "cloudflare_record" "github_challenge" {
zone_id = local.zones[local.main_domain]
name = "_github-pages-challenge-${local.github_owner}"
content = "'${local.github_challenge}'"
proxied = false
ttl = 1
type = "TXT"
}

resource "cloudflare_record" "cnames_www" {
for_each = setunion([local.main_domain], local.redirects)
zone_id = local.zones[each.value]
name = "www"
content = each.value
proxied = true
ttl = 1
type = "CNAME"
}
Loading

0 comments on commit 20dc7a7

Please sign in to comment.