Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: more iac #46

Merged
merged 9 commits into from
Jun 5, 2024
Merged
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"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we (maybe later?) want to scope this to only the immich-app repo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've mostly been pretty lax with anything but the master keys, but we can scope this if you want to reasonably easily

}
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
}
Loading