Skip to content

Commit

Permalink
feat: more iac (#46)
Browse files Browse the repository at this point in the history
* chore: remove unused immich.app dns records

* refactor: add mich ip as a local

* refactor: give all the cloudflare api keys proper names

* chore: add example.env for running locally

* feat: add r2 bucket and mich r2 cloudflare token

* feat: add github org iac for secrets initially

* chore: add and tell IDE's to add newlines to end of files

* feat: deploy github org iac through github actions

* docs: add manual setup steps required for IAC in github actions
  • Loading branch information
zackpollard authored Jun 5, 2024
1 parent 4464fe5 commit 5d80b91
Show file tree
Hide file tree
Showing 25 changed files with 186 additions and 47 deletions.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.{md,mdx}]
max_line_length = off
trim_trailing_whitespace = false

[*.{yml,yaml}]
quote_type = single
12 changes: 9 additions & 3 deletions .github/workflows/terragrunt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
env:
tofu_version: '1.7.1'
tg_version: '0.58.12'
working_dir: 'deployment/modules/cloudflare'
working_dir: 'deployment'

jobs:
check:
Expand Down Expand Up @@ -50,6 +50,10 @@ jobs:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
GITHUB_APP_INSTALLATION_ID: ${{ secrets.TF_APP_INSTALLATION_ID }}
GITHUB_APP_ID: ${{ secrets.TF_APP_ID }}
GITHUB_APP_PEM_FILE: ${{ secrets.TF_APP_PEM_FILE }}
GITHUB_OWNER: ${{ secrets.TF_APP_GITHUB_OWNER }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tofu_version: ${{ env.tofu_version }}
Expand All @@ -71,10 +75,12 @@ jobs:
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
TF_STATE_POSTGRES_CONN_STR: ${{ secrets.TF_STATE_POSTGRES_CONN_STR }}
GITHUB_APP_INSTALLATION_ID: ${{ secrets.TF_APP_INSTALLATION_ID }}
GITHUB_APP_ID: ${{ secrets.TF_APP_ID }}
GITHUB_APP_PEM_FILE: ${{ secrets.TF_APP_PEM_FILE }}
GITHUB_OWNER: ${{ secrets.TF_APP_GITHUB_OWNER }}
with:
tofu_version: ${{ env.tofu_version }}
tg_version: ${{ env.tg_version }}
tg_dir: ${{ env.working_dir }}
tg_command: 'run-all apply'


3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
### Project gitignore
.env

### VisualStudioCode template
.vscode/*
!.vscode/settings.json
Expand Down
2 changes: 1 addition & 1 deletion deployment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ To deploy the OpenTofu modules, follow these steps:
1. Install Terragrunt with `tenv terragrunt install ${version}` then run `tenv terragrunt use ${version}`
1. Set `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` and `TF_STATE_POSTGRES_CONN_STR` in your environment
1. Switch to the `deployment/modules` folder
1. Run `terragrunt run-all plan` to see what changes will be applied for your changes
1. Run `terragrunt run-all plan` to see what changes will be applied for your changes
7 changes: 7 additions & 0 deletions deployment/example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export CLOUDFLARE_ACCOUNT_ID=
export CLOUDFLARE_API_TOKEN=
export TF_STATE_POSTGRES_CONN_STR=
export GITHUB_APP_INSTALLATION_ID=
export GITHUB_APP_ID=
export GITHUB_APP_PEM_FILE=
export GITHUB_OWNER=
15 changes: 15 additions & 0 deletions deployment/manual-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Manual Setup Steps

This lists all the steps required to manually setup the IAC deployments in Github Actions.

### Github Secrets

| Secret | Secret Type | Description |
|-----------------------------|-----------------|-----------------------------------------------------------------------------|
| TF_APP_INSTALLATION_ID | Organisation | The installation ID of the Immich Github App |
| TF_APP_ID | Organisation | The ID of the Immich Github App |
| TF_APP_PEM_FILE | Repo (devtools) | The contents of the PEM file for the Github App |
| TF_APP_GITHUB_OWNER | Organisation | The Github owner of the repository (immich-app) |
| CLOUDFLARE_API_TOKEN | Repo (devtools) | The Cloudflare API token scoped to create new API keys |
| CLOUDFLARE_ACCOUNT_ID | Organisation | The Cloudflare account ID |
| TF_STATE_POSTGRES_CONN_STR | Organisation | The connection string for the Postgres database for Terraform state storage |
27 changes: 0 additions & 27 deletions deployment/modules/cloudflare/account/dns-immich-app.tf
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,6 @@ resource "cloudflare_record" "immich_app_a_demo" {
zone_id = cloudflare_zone.immich_app.id
}

resource "cloudflare_record" "immich_app_a_star_dot_preview" {
name = "*.preview"
proxied = false
ttl = 1
type = "A"
value = "141.144.207.87"
zone_id = cloudflare_zone.immich_app.id
}

resource "cloudflare_record" "immich_app_a_preview" {
name = "preview"
proxied = false
ttl = 1
type = "A"
value = "141.144.207.87"
zone_id = cloudflare_zone.immich_app.id
}

resource "cloudflare_record" "immich_app_a_testing" {
name = "testing"
proxied = true
ttl = 1
type = "A"
value = "143.198.72.84"
zone_id = cloudflare_zone.immich_app.id
}

resource "cloudflare_record" "immich_app_aaaa_docs" {
name = "docs"
proxied = true
Expand Down
2 changes: 1 addition & 1 deletion deployment/modules/cloudflare/account/dns-immich-cloud.tf
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ resource "cloudflare_record" "immich_cloud_a_mich" {
proxied = false
ttl = 1
type = "A"
value = "162.55.86.82"
value = local.mich_ip
zone_id = cloudflare_zone.immich_cloud.id
}
3 changes: 3 additions & 0 deletions deployment/modules/cloudflare/account/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
mich_ip = "162.55.86.82"
}
2 changes: 1 addition & 1 deletion deployment/modules/cloudflare/account/pages-project.tf
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ output "immich_app_preview_pages_project_name" {

output "immich_app_preview_pages_project_subdomain" {
value = cloudflare_pages_project.immich_app_preview.subdomain
}
}
5 changes: 5 additions & 0 deletions deployment/modules/cloudflare/account/r2.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "cloudflare_r2_bucket" "tf_state_database_backups" {
account_id = var.cloudflare_account_id
name = "tf-state-database-backups"
location = "weur"
}
8 changes: 6 additions & 2 deletions deployment/modules/cloudflare/account/terragrunt.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ terraform {
}
}

include {
path = find_in_parent_folders("state.hcl")
include "cloudflare" {
path = find_in_parent_folders("cloudflare.hcl")
}

include "root" {
path = find_in_parent_folders("root.hcl")
}

dependencies {
Expand Down
35 changes: 31 additions & 4 deletions deployment/modules/cloudflare/api-keys/api-keys.tf
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
data "cloudflare_api_token_permission_groups" "all" {}

resource "cloudflare_api_token" "terraform_cloudflare_account" {
name = "terraform"
name = "terraform_cloudflare_account"
policy {
permission_groups = [
data.cloudflare_api_token_permission_groups.all.account["Pages Write"],
data.cloudflare_api_token_permission_groups.all.zone["DNS Write"],
data.cloudflare_api_token_permission_groups.all.zone["Zone Write"],
data.cloudflare_api_token_permission_groups.all.zone["Zone Settings Write"],
data.cloudflare_api_token_permission_groups.all.zone["Dynamic URL Redirects Write"],
data.cloudflare_api_token_permission_groups.all.account["Workers R2 Storage Write"]
]
resources = {
"com.cloudflare.api.account.*" = "*"
Expand All @@ -22,7 +23,7 @@ output "terraform_key_cloudflare_account" {
}

resource "cloudflare_api_token" "terraform_cloudflare_docs" {
name = "terraform"
name = "terraform_cloudflare_docs"
policy {
permission_groups = [
data.cloudflare_api_token_permission_groups.all.account["Pages Write"],
Expand All @@ -39,9 +40,8 @@ output "terraform_key_cloudflare_docs" {
sensitive = true
}


resource "cloudflare_api_token" "terraform_cloudflare_pages_upload" {
name = "terraform"
name = "terraform_cloudflare_pages_upload"
policy {
permission_groups = [
data.cloudflare_api_token_permission_groups.all.account["Pages Write"],
Expand All @@ -56,3 +56,30 @@ output "terraform_key_cloudflare_pages_upload" {
value = cloudflare_api_token.terraform_cloudflare_account.value
sensitive = true
}

resource "cloudflare_api_token" "mich_cloudflare_r2_token" {
name = "mich_r2_token"
policy {
permission_groups = [
data.cloudflare_api_token_permission_groups.all.r2["Workers R2 Storage Bucket Item Write"]
]
resources = {
"com.cloudflare.edge.r2.bucket.*" = "*"
}
}
condition {
request_ip {
in = local.mich_cidrs
}
}
}

output "mich_cloudflare_r2_token_id" {
value = cloudflare_api_token.mich_cloudflare_r2_token.id
sensitive = true
}

output "mich_cloudflare_r2_token_value" {
value = cloudflare_api_token.mich_cloudflare_r2_token.value
sensitive = true
}
2 changes: 1 addition & 1 deletion deployment/modules/cloudflare/api-keys/config.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ terraform {
version = "4.34.0"
}
}
}
}
3 changes: 3 additions & 0 deletions deployment/modules/cloudflare/api-keys/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
mich_cidrs = ["162.55.86.82/32"]
}
8 changes: 6 additions & 2 deletions deployment/modules/cloudflare/api-keys/terragrunt.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ terraform {
}
}

include {
path = find_in_parent_folders("state.hcl")
include "cloudflare" {
path = find_in_parent_folders("cloudflare.hcl")
}

include "root" {
path = find_in_parent_folders("root.hcl")
}
9 changes: 9 additions & 0 deletions deployment/modules/cloudflare/cloudflare.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
locals {
cloudflare_account_id = get_env("CLOUDFLARE_ACCOUNT_ID")
cloudflare_api_token = get_env("CLOUDFLARE_API_TOKEN")
}

inputs = {
cloudflare_account_id = local.cloudflare_account_id
cloudflare_api_token = local.cloudflare_api_token
}
24 changes: 24 additions & 0 deletions deployment/modules/github/org/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions deployment/modules/github/org/config.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
terraform {
backend "pg" {
schema_name = "prod_github_org"
}
required_version = "~> 1.7"

required_providers {
github = {
source = "integrations/github"
version = "~> 6.0"
}
}
}
3 changes: 3 additions & 0 deletions deployment/modules/github/org/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider "github" {
app_auth {}
}
8 changes: 8 additions & 0 deletions deployment/modules/github/org/remote-state.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
data "terraform_remote_state" "api_keys_state" {
backend = "pg"

config = {
conn_str = var.tf_state_postgres_conn_str
schema_name = "prod_cloudflare_api_keys"
}
}
5 changes: 5 additions & 0 deletions deployment/modules/github/org/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "github_actions_organization_secret" "cloudflare_api_token_pages_upload" {
secret_name = "CLOUDFLARE_API_TOKEN_PAGES_UPLOAD"
plaintext_value = data.terraform_remote_state.api_keys_state.outputs.terraform_key_cloudflare_pages_upload
visibility = "all"
}
15 changes: 15 additions & 0 deletions deployment/modules/github/org/terragrunt.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
terraform {
source = "."

extra_arguments custom_vars {
commands = get_terraform_commands_that_need_vars()
}
}

include "root" {
path = find_in_parent_folders("root.hcl")
}

dependencies {
paths = ["../../cloudflare/api-keys"]
}
1 change: 1 addition & 0 deletions deployment/modules/github/org/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
variable "tf_state_postgres_conn_str" {}
5 changes: 0 additions & 5 deletions deployment/state.hcl → deployment/root.hcl
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
locals {
cloudflare_account_id = get_env("CLOUDFLARE_ACCOUNT_ID")
cloudflare_api_token = get_env("CLOUDFLARE_API_TOKEN")

tf_state_postgres_conn_str = get_env("TF_STATE_POSTGRES_CONN_STR")
}

Expand All @@ -14,7 +11,5 @@ remote_state {
}

inputs = {
cloudflare_account_id = local.cloudflare_account_id
cloudflare_api_token = local.cloudflare_api_token
tf_state_postgres_conn_str = local.tf_state_postgres_conn_str
}

0 comments on commit 5d80b91

Please sign in to comment.