From 5d1a4687f184e7c171eb1e653d6afd3cbf8c1bce Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Wed, 29 Oct 2025 00:34:12 +0000 Subject: [PATCH 1/8] feat: allow specifying vaults for generated secrets and move to single scoped input --- .../shared/1password/account/secrets.tf | 9 ++---- tf/shared/modules/secrets/generated/data.tf | 13 ++++----- .../modules/secrets/generated/secrets.tf | 28 ++++++++----------- .../modules/secrets/generated/variables.tf | 19 +++++++++---- 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/tf/deployment/modules/shared/1password/account/secrets.tf b/tf/deployment/modules/shared/1password/account/secrets.tf index 221ce2245..c39e8d2c3 100644 --- a/tf/deployment/modules/shared/1password/account/secrets.tf +++ b/tf/deployment/modules/shared/1password/account/secrets.tf @@ -53,7 +53,7 @@ module "manual-secrets" { "MONITORING_GRAFANA_TF_AUTH_TOKEN", "MONITORING_GRAFANA_URL", "IMMICH_DISCORD_SERVER_ID", - ] + ], prod = [ "IMMICH_DISCORD_BOT_TOKEN", "MONITORING_GRAFANA_TF_AUTH_TOKEN", @@ -83,12 +83,7 @@ module "generated-secrets" { { name = "IMMICH_GITHUB_ACTION_CHECKS_WEBHOOK_SECRET" }, { name = "OUTLINE_ROLE_SYNC_WEBHOOK_SECRET" } ] - dev = [ - { name = "METRICS_READ_TOKEN" }, - { name = "METRICS_WRITE_TOKEN" }, - { name = "METRICS_ADMIN_TOKEN" } - ] - prod = [ + scoped = [ { name = "METRICS_READ_TOKEN" }, { name = "METRICS_WRITE_TOKEN" }, { name = "METRICS_ADMIN_TOKEN" }, diff --git a/tf/shared/modules/secrets/generated/data.tf b/tf/shared/modules/secrets/generated/data.tf index 932a3f9a3..fdd21bef5 100644 --- a/tf/shared/modules/secrets/generated/data.tf +++ b/tf/shared/modules/secrets/generated/data.tf @@ -1,11 +1,8 @@ -data "onepassword_vault" "tf" { - name = "tf" +data "onepassword_vault" "global" { + name = var.global_vault } -data "onepassword_vault" "tf_dev" { - name = "tf_dev" -} - -data "onepassword_vault" "tf_prod" { - name = "tf_prod" +data "onepassword_vault" "scoped" { + for_each = var.scoped_vaults + name = each.value } diff --git a/tf/shared/modules/secrets/generated/secrets.tf b/tf/shared/modules/secrets/generated/secrets.tf index ea9b7d754..f899294c0 100644 --- a/tf/shared/modules/secrets/generated/secrets.tf +++ b/tf/shared/modules/secrets/generated/secrets.tf @@ -2,28 +2,22 @@ locals { secrets = concat( var.secrets.global != null ? [ for secret_obj in var.secrets.global : { - vault = data.onepassword_vault.tf + vault = data.onepassword_vault.global name = secret_obj.name length = secret_obj.length type = secret_obj.type } ] : [], - var.secrets.dev != null ? [ - for secret_obj in var.secrets.dev : { - vault = data.onepassword_vault.tf_dev - name = secret_obj.name - length = secret_obj.length - type = secret_obj.type - } - ] : [], - var.secrets.prod != null ? [ - for secret_obj in var.secrets.prod : { - vault = data.onepassword_vault.tf_prod - name = secret_obj.name - length = secret_obj.length - type = secret_obj.type - } - ] : [] + var.secrets.scoped != null ? flatten([ + for vault_name in var.scoped_vaults : [ + for secret_obj in var.secrets.scoped : { + vault = data.onepassword_vault.scoped[vault_name] + name = secret_obj.name + length = secret_obj.length + type = secret_obj.type + } + ] + ]) : [] ) } diff --git a/tf/shared/modules/secrets/generated/variables.tf b/tf/shared/modules/secrets/generated/variables.tf index ebe69b2df..6d52679d5 100644 --- a/tf/shared/modules/secrets/generated/variables.tf +++ b/tf/shared/modules/secrets/generated/variables.tf @@ -5,12 +5,7 @@ variable "secrets" { length = optional(number) type = optional(string, "alphanumeric") }))) - dev = optional(list(object({ - name = string - length = optional(number) - type = optional(string, "alphanumeric") - }))) - prod = optional(list(object({ + scoped = optional(list(object({ name = string length = optional(number) type = optional(string, "alphanumeric") @@ -18,6 +13,18 @@ variable "secrets" { }) } +variable "global_vault" { + type = string + description = "Name of the vault for storing global secrets" + default = "tf" +} + +variable "scoped_vaults" { + type = set(string) + description = "Names of the vaults for storing scoped secrets" + default = ["tf_prod", "tf_dev"] +} + variable "default_secret_length" { type = number description = "The default length for generated secrets if not specified per secret." From ff126f5cd30fe85214c9e9ef627eea774b9d6e81 Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Wed, 29 Oct 2025 00:57:21 +0000 Subject: [PATCH 2/8] feat: allow specifying vaults for manual secrets and move to single scoped input --- .../shared/1password/account/secrets.tf | 8 +----- tf/shared/modules/secrets/manual/data.tf | 26 +++++++----------- tf/shared/modules/secrets/manual/secrets.tf | 27 ++++++++----------- tf/shared/modules/secrets/manual/variables.tf | 24 +++++++++++++++-- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/tf/deployment/modules/shared/1password/account/secrets.tf b/tf/deployment/modules/shared/1password/account/secrets.tf index c39e8d2c3..b89120def 100644 --- a/tf/deployment/modules/shared/1password/account/secrets.tf +++ b/tf/deployment/modules/shared/1password/account/secrets.tf @@ -48,13 +48,7 @@ module "manual-secrets" { "GITLAB_OAUTH_APP_FUTO_ZITADEL_ISSUER", "GITHUB_APP_FUTO_ORG_SELFHOSTED_RUNNERS_INSTALLATION_ID" ] - dev = [ - "IMMICH_DISCORD_BOT_TOKEN", - "MONITORING_GRAFANA_TF_AUTH_TOKEN", - "MONITORING_GRAFANA_URL", - "IMMICH_DISCORD_SERVER_ID", - ], - prod = [ + scoped = [ "IMMICH_DISCORD_BOT_TOKEN", "MONITORING_GRAFANA_TF_AUTH_TOKEN", "MONITORING_GRAFANA_URL", diff --git a/tf/shared/modules/secrets/manual/data.tf b/tf/shared/modules/secrets/manual/data.tf index 287188776..5e32e343f 100644 --- a/tf/shared/modules/secrets/manual/data.tf +++ b/tf/shared/modules/secrets/manual/data.tf @@ -1,23 +1,17 @@ -data "onepassword_vault" "manual" { - name = "tf_manual" +data "onepassword_vault" "manual_global" { + name = var.global_vault } -data "onepassword_vault" "manual_dev" { - name = "tf_dev_manual" +data "onepassword_vault" "manual_scoped" { + for_each = var.scoped_vaults + name = each.key } -data "onepassword_vault" "manual_prod" { - name = "tf_prod_manual" +data "onepassword_vault" "copy_global" { + name = var.copy_global_vault } -data "onepassword_vault" "tf" { - name = "tf" -} - -data "onepassword_vault" "tf_dev" { - name = "tf_dev" -} - -data "onepassword_vault" "tf_prod" { - name = "tf_prod" +data "onepassword_vault" "copy_scoped" { + for_each = var.scoped_vaults + name = each.value } diff --git a/tf/shared/modules/secrets/manual/secrets.tf b/tf/shared/modules/secrets/manual/secrets.tf index 84cebc251..bce70c5fb 100644 --- a/tf/shared/modules/secrets/manual/secrets.tf +++ b/tf/shared/modules/secrets/manual/secrets.tf @@ -2,25 +2,20 @@ locals { secrets = concat( var.secrets.global != null ? [ for name in var.secrets.global : { - manual_vault = data.onepassword_vault.manual - vault = data.onepassword_vault.tf + manual_vault = data.onepassword_vault.manual_global + vault = data.onepassword_vault.copy_global name = name } ] : [], - var.secrets.dev != null ? [ - for name in var.secrets.dev : { - manual_vault = data.onepassword_vault.manual_dev - vault = data.onepassword_vault.tf_dev - name = name - } - ] : [], - var.secrets.prod != null ? [ - for name in var.secrets.prod : { - manual_vault = data.onepassword_vault.manual_prod - vault = data.onepassword_vault.tf_prod - name = name - } - ] : [] + var.secrets.scoped != null ? flatten([ + for manual_vault, copy_vault in var.scoped_vaults : [ + for name in var.secrets.scoped : { + manual_vault = data.onepassword_vault.manual_scoped[manual_vault] + vault = data.onepassword_vault.copy_scoped[manual_vault] + name = name + } + ] + ]) : [] ) } diff --git a/tf/shared/modules/secrets/manual/variables.tf b/tf/shared/modules/secrets/manual/variables.tf index ec5f05c6a..8757512fb 100644 --- a/tf/shared/modules/secrets/manual/variables.tf +++ b/tf/shared/modules/secrets/manual/variables.tf @@ -1,7 +1,27 @@ variable "secrets" { type = object({ global = optional(list(string)) - dev = optional(list(string)) - prod = optional(list(string)) + scoped = optional(list(string)) }) } + +variable "global_vault" { + type = string + description = "Name of the vault for storing global manual secrets" + default = "tf_manual" +} + +variable "copy_global_vault" { + type = string + description = "Name of the vault for copying global secrets to" + default = "tf" +} + +variable "scoped_vaults" { + type = map(string) + description = "Map of manual vault names to copy vault names for scoped secrets" + default = { + "tf_prod_manual" = "tf_prod" + "tf_dev_manual" = "tf_dev" + } +} From 0158b7b19c4c4b49dca434d14bf8af7df4387cd0 Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Wed, 29 Oct 2025 01:37:40 +0000 Subject: [PATCH 3/8] feat: yucca secrets --- .../shared/1password/account/yucca-secrets.tf | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 tf/deployment/modules/shared/1password/account/yucca-secrets.tf diff --git a/tf/deployment/modules/shared/1password/account/yucca-secrets.tf b/tf/deployment/modules/shared/1password/account/yucca-secrets.tf new file mode 100644 index 000000000..b3a7b52ee --- /dev/null +++ b/tf/deployment/modules/shared/1password/account/yucca-secrets.tf @@ -0,0 +1,47 @@ +module "yucca-manual-secrets" { + source = "./shared/modules/secrets/manual" + + secrets = { + global = [ + TF_STATE_S3_ENDPOINT, + TF_STATE_S3_BUCKET, + TF_STATE_S3_ACCESS_KEY, + TF_STATE_S3_SECRET_KEY, + OVH_APPLICATION_KEY, + OVH_APPLICATION_SECRET, + OVH_CONSUMER_KEY + ] + scoped = [] + global_vault = "yucca_tf_manual" + copy_global_vault = "yucca_tf" + scoped_vaults = { + "yucca_tf_prod_manual" = "yucca_tf_prod" + "yucca_tf_staging_manual" = "yucca_tf_staging" + "yucca_tf_dev_manual" = "yucca_tf_dev" + } + } +} + +module "generated-secrets" { + source = "./shared/modules/secrets/generated" + + secrets = { + global = [ + ] + scoped = [ + ] + } + + global_vault = "yucca_tf" + scoped_vaults = toset([ + "yucca_tf_prod", + "yucca_tf_staging", + "yucca_tf_dev", + ]) +} + +module "github-apps" { + source = "./shared/modules/secrets/github-app" + + app_names = ["IMMICH_TOFU", "IMMICH_PUSH_O_MATIC", "IMMICH_READ_ONLY", "IMMICH_GITHUB_ACTION_CHECKS"] +} From b9d58db1024a3f5459e8f32e7b1bc004533f4849 Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Wed, 29 Oct 2025 17:52:49 +0000 Subject: [PATCH 4/8] feat: seperate futo secrets tf module --- tf/deployment/.env | 1 + .../shared/1password/account/yucca-secrets.tf | 47 ----------- .../futo-account/.terraform.lock.hcl | 79 +++++++++++++++++++ .../shared/1password/futo-account/config.tf | 21 +++++ .../1password/futo-account/providers.tf | 3 + .../1password/futo-account/terragrunt.hcl | 11 +++ .../1password/futo-account/variables.tf | 1 + .../1password/futo-account/yucca-secrets.tf | 39 +++++++++ 8 files changed, 155 insertions(+), 47 deletions(-) delete mode 100644 tf/deployment/modules/shared/1password/account/yucca-secrets.tf create mode 100644 tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl create mode 100644 tf/deployment/modules/shared/1password/futo-account/config.tf create mode 100644 tf/deployment/modules/shared/1password/futo-account/providers.tf create mode 100644 tf/deployment/modules/shared/1password/futo-account/terragrunt.hcl create mode 100644 tf/deployment/modules/shared/1password/futo-account/variables.tf create mode 100644 tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf diff --git a/tf/deployment/.env b/tf/deployment/.env index 68cc2e4e2..9d1b06e68 100644 --- a/tf/deployment/.env +++ b/tf/deployment/.env @@ -7,6 +7,7 @@ export TF_VAR_github_app_id="op://tf/GITHUB_APP_IMMICH_TOFU/app_id" export TF_VAR_github_app_pem_file="op://tf/GITHUB_APP_IMMICH_TOFU/pkcs1" export TF_VAR_github_owner="op://tf/GITHUB_APP_IMMICH_TOFU/owner" export TF_VAR_op_service_account_token="op://tf/1pass_service_account/superuser_token" +export TF_VAR_futo_op_service_account_token="op://tf_prod/yucca_futo_1pass_superuser_service_account/password" export TF_VAR_discord_token="op://tf/IMMICH_TF_DISCORD_BOT_TOKEN/password" export TF_VAR_zitadel_profile_json="op://tf/ZITADEL_PROFILE_JSON/password" export TF_VAR_zitadel_github_client_id="op://tf/GITHUB_OAUTH_APP_IMMICH_ZITADEL_CLIENT_ID/password" diff --git a/tf/deployment/modules/shared/1password/account/yucca-secrets.tf b/tf/deployment/modules/shared/1password/account/yucca-secrets.tf deleted file mode 100644 index b3a7b52ee..000000000 --- a/tf/deployment/modules/shared/1password/account/yucca-secrets.tf +++ /dev/null @@ -1,47 +0,0 @@ -module "yucca-manual-secrets" { - source = "./shared/modules/secrets/manual" - - secrets = { - global = [ - TF_STATE_S3_ENDPOINT, - TF_STATE_S3_BUCKET, - TF_STATE_S3_ACCESS_KEY, - TF_STATE_S3_SECRET_KEY, - OVH_APPLICATION_KEY, - OVH_APPLICATION_SECRET, - OVH_CONSUMER_KEY - ] - scoped = [] - global_vault = "yucca_tf_manual" - copy_global_vault = "yucca_tf" - scoped_vaults = { - "yucca_tf_prod_manual" = "yucca_tf_prod" - "yucca_tf_staging_manual" = "yucca_tf_staging" - "yucca_tf_dev_manual" = "yucca_tf_dev" - } - } -} - -module "generated-secrets" { - source = "./shared/modules/secrets/generated" - - secrets = { - global = [ - ] - scoped = [ - ] - } - - global_vault = "yucca_tf" - scoped_vaults = toset([ - "yucca_tf_prod", - "yucca_tf_staging", - "yucca_tf_dev", - ]) -} - -module "github-apps" { - source = "./shared/modules/secrets/github-app" - - app_names = ["IMMICH_TOFU", "IMMICH_PUSH_O_MATIC", "IMMICH_READ_ONLY", "IMMICH_GITHUB_ACTION_CHECKS"] -} diff --git a/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl b/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl new file mode 100644 index 000000000..3cbebc0b2 --- /dev/null +++ b/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl @@ -0,0 +1,79 @@ +# This file is maintained automatically by "tofu init". +# Manual edits may be lost in future updates. + +provider "registry.opentofu.org/1password/onepassword" { + version = "2.1.0" + constraints = "~> 2.0" + hashes = [ + "h1:B3G7M02HxGCgT4S1+d4ITPR0vj7ZXDzGx+vqkKtk81c=", + "zh:0d6f803760aa7cae0e841cfca17ef04411231170b2844cc0b30556d5476d9dff", + "zh:17badbffb56309f28aee1893a6b93d1cd87ed5157704fb17b93889f0ccf8cc2d", + "zh:185e0c7c66cc159769d7b91c37ab51a546efc13fb99eb206481739a521f75236", + "zh:19e213f8265445a29d8bb7c7b1f0d4e3c1fdfd538178704f8e8378db2dcdf359", + "zh:49929666304f97301f44ee0fdd39f40f63e35ccfb4c81588439bdab6d5bafde0", + "zh:4de33f5630350d6a561d5d62994d525beb8849c94287c2658f39242fe3170cf8", + "zh:4f212a8fbbbaa7a47f1b31857be3bad2d590f92be845c6b252c9716bb70076d9", + "zh:596cc2bd9aaafd2e649aabcff0125afa9d4270f702813c935fbd5694eed002e7", + "zh:618e703a43608c502066c5b909ead45b1f4202f7cebc993f447278477d32cda2", + "zh:61fde3651bcb2e691ee9d82ce1de03588d006f53b2e8e2516910321da8627228", + "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", + "zh:db05022113841a00174bba5e24cfc77195bbc03d24339c5e8ac4346069901e45", + "zh:dcc7792a24c74890081a96ba2bc360d90ab71a4d25232ca18046d9868c835e21", + "zh:f2e67a298d20bf52cb208611767b420962d3f0d518e89cf41cc432551b1faf63", + "zh:f7e587814506c7e74fc1d80b29465c8e4b7bdbf803f7f8c0a8bb498968cdd58d", + ] +} + +provider "registry.opentofu.org/hashicorp/random" { + version = "3.7.2" + constraints = "3.7.2" + hashes = [ + "h1:5wxrQQTchfk/2S1wSi9lx/fmiscVLGI3kL2v/+LccHU=", + "h1:C1D2Vo445WXAeLwSpovebSDR97ohiGvXVixcXJneQTg=", + "h1:KvLLxlMi6iNdlZS+vQAwovIeL2r5Q2s/EXXF+oypKHI=", + "h1:Q1EQQw7icbHSYUSYMlgi4qSXPuJDySuMjXcC0WqzgP8=", + "h1:cFGCdxTlsrteTiaOV/iOQdql7eJkD3F/vtJxenkj9IE=", + "h1:o15Kr/27vFN5AD9YkF48tDrHLSAshEq4Q7sAxIViZHM=", + "h1:rdpkD+Rzr+KCPqOvb1ckzupjWCOum/boRX4FqVboAHQ=", + "h1:ttMGebt31P1FZCEWptLTMpmx1aeDvkJ9nBDivtCCkyM=", + "h1:wz31hqWhHTq9bgIM/3+VNqy89JAICMXSwCmG8A70w0A=", + "h1:yHMBbZOIHlXUuBQ8Mhioe0hwmhermuboq2eNNoCJaf8=", + "zh:2ffeb1058bd7b21a9e15a5301abb863053a2d42dffa3f6cf654a1667e10f4727", + "zh:519319ed8f4312ed76519652ad6cd9f98bc75cf4ec7990a5684c072cf5dd0a5d", + "zh:7371c2cc28c94deb9dba62fbac2685f7dde47f93019273a758dd5a2794f72919", + "zh:9b0ac4c1d8e36a86b59ced94fa517ae9b015b1d044b3455465cc6f0eab70915d", + "zh:c6336d7196f1318e1cbb120b3de8426ce43d4cacd2c75f45dba2dbdba666ce00", + "zh:c71f18b0cb5d55a103ea81e346fb56db15b144459123f1be1b0209cffc1deb4e", + "zh:d2dc49a6cac2d156e91b0506d6d756809e36bf390844a187f305094336d3e8d8", + "zh:d5b5fc881ccc41b268f952dae303501d6ec9f9d24ee11fe2fa56eed7478e15d0", + "zh:db9723eaca26d58c930e13fde221d93501529a5cd036b1f167ef8cff6f1a03cc", + "zh:fe3359f733f3ab518c6f85f3a9cd89322a7143463263f30321de0973a52d4ad8", + ] +} + +provider "registry.opentofu.org/hashicorp/tls" { + version = "4.1.0" + constraints = "4.1.0" + hashes = [ + "h1:E9RjaL6cn8U/IkzfNcmrf/9EtMGjJnwUeXpx85sOGRg=", + "h1:M2wp0tzlf2SDIxQbN5Sxc8o5HCGYZFfyfPwM9MJI3PE=", + "h1:MByilNnYPdjPTlb/qcNgR0DErA6550hI6wd8OJYB1vw=", + "h1:RBhHxjVu41XdAnM4WxxGTz2nYaccHNLalqx4031L8rE=", + "h1:Scu4v7p3hVi6JmyWN4e1KkR31MX48T65dfA3Nfaeb/E=", + "h1:Xb4aKDd/LTy9kSpauyTIe/Y4py2xK2sbImV1LdgMc/Q=", + "h1:m4r9DvgYoUdf1ZeJMd2NGs3b6+8/RPhXUrEex554eQw=", + "h1:p4jzSJLVx9DHkNZ1ax2/bMPTirjZxxN9nmiVx0aFQjA=", + "h1:ujNwtB97C/kEt12+S3mUTWkGaJO8LNbqWoRg1FZ5a80=", + "h1:yNZuPWUgw6Ik2huf9lhsuCGONWo2rsY1MfeceT0BQpw=", + "zh:187a99f0d236fd92da224e2f026c4ca8f1dcbf2b5cddc8e6896801bacfab0d73", + "zh:61a32a01cc46f382014dcf7aff5bcac61fe97bd69d3ccb51c801e9437ecdb9ce", + "zh:683ba18baa2cc336ff83f061b5e4569e2cd7c4a097b53a2d80bb0a26be2fc59a", + "zh:85c7640ea13dcf5ae5f7f3abbf2f21e4b93ce7f333ffee5b4a6acd6b5fe71223", + "zh:882f2c5214fd6d280a500acfd560925a71030ef70e10d11fa2b94815b58ae9b6", + "zh:97cb5e0b81b8687870a6b8a16e9a9cfe546e2fdb7534bdd8302eda0d66393f78", + "zh:c0a0110b15ce45140036fe5bf5a44cb822c2f55b30ff2770faf37d7c3cae3b5e", + "zh:d98c1c63fd0c76704fd7be38c316c305a2c95f3215330f2fb1e6b0b7081bf8e9", + "zh:e703a7adf220ac436f8ebfd06529de865b965fcfc461c7ef7b71afa0de04c8e9", + "zh:e93e241150cd438a0708679cb4aa7976742fde02f4c1725cfdefc405c4eeca1a", + ] +} diff --git a/tf/deployment/modules/shared/1password/futo-account/config.tf b/tf/deployment/modules/shared/1password/futo-account/config.tf new file mode 100644 index 000000000..63f0eb561 --- /dev/null +++ b/tf/deployment/modules/shared/1password/futo-account/config.tf @@ -0,0 +1,21 @@ +terraform { + backend "pg" { + schema_name = "prod_1password_futo_account" + } + required_version = "~> 1.7" + + required_providers { + onepassword = { + source = "1Password/onepassword" + version = "~> 2.0" + } + random = { + source = "hashicorp/random" + version = "3.7.2" + } + tls = { + source = "hashicorp/tls" + version = "4.1.0" + } + } +} diff --git a/tf/deployment/modules/shared/1password/futo-account/providers.tf b/tf/deployment/modules/shared/1password/futo-account/providers.tf new file mode 100644 index 000000000..507429683 --- /dev/null +++ b/tf/deployment/modules/shared/1password/futo-account/providers.tf @@ -0,0 +1,3 @@ +provider "onepassword" { + service_account_token = var.futo_op_service_account_token +} diff --git a/tf/deployment/modules/shared/1password/futo-account/terragrunt.hcl b/tf/deployment/modules/shared/1password/futo-account/terragrunt.hcl new file mode 100644 index 000000000..c63229bc5 --- /dev/null +++ b/tf/deployment/modules/shared/1password/futo-account/terragrunt.hcl @@ -0,0 +1,11 @@ +terraform { + source = "../../../../../" + + extra_arguments custom_vars { + commands = get_terraform_commands_that_need_vars() + } +} + +include "root" { + path = find_in_parent_folders("root.hcl") +} diff --git a/tf/deployment/modules/shared/1password/futo-account/variables.tf b/tf/deployment/modules/shared/1password/futo-account/variables.tf new file mode 100644 index 000000000..2ba1f9318 --- /dev/null +++ b/tf/deployment/modules/shared/1password/futo-account/variables.tf @@ -0,0 +1 @@ +variable "futo_op_service_account_token" {} diff --git a/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf b/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf new file mode 100644 index 000000000..75102ed23 --- /dev/null +++ b/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf @@ -0,0 +1,39 @@ +module "yucca-manual-secrets" { + source = "./shared/modules/secrets/manual" + + secrets = { + global = [ + "TF_STATE_S3_ENDPOINT", + "TF_STATE_S3_BUCKET", + "TF_STATE_S3_ACCESS_KEY", + "TF_STATE_S3_SECRET_KEY", + "OVH_APPLICATION_KEY", + "OVH_APPLICATION_SECRET", + "OVH_CONSUMER_KEY" + ] + scoped = [] + } + global_vault = "yucca_tf_manual" + copy_global_vault = "yucca_tf" + scoped_vaults = { + "yucca_tf_prod_manual" = "yucca_tf_prod" + "yucca_tf_staging_manual" = "yucca_tf_staging" + "yucca_tf_dev_manual" = "yucca_tf_dev" + } +} + +module "generated-secrets" { + source = "./shared/modules/secrets/generated" + + secrets = { + global = [] + scoped = [] + } + + global_vault = "yucca_tf" + scoped_vaults = toset([ + "yucca_tf_prod", + "yucca_tf_staging", + "yucca_tf_dev", + ]) +} From 720086df7b753443ac6e8c14a5d3020491729fc3 Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Thu, 30 Oct 2025 16:25:39 +0000 Subject: [PATCH 5/8] feat: yucca s3 region state secret --- .../modules/shared/1password/futo-account/yucca-secrets.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf b/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf index 75102ed23..912780ab0 100644 --- a/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf +++ b/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf @@ -5,6 +5,7 @@ module "yucca-manual-secrets" { global = [ "TF_STATE_S3_ENDPOINT", "TF_STATE_S3_BUCKET", + "TF_STATE_S3_REGION", "TF_STATE_S3_ACCESS_KEY", "TF_STATE_S3_SECRET_KEY", "OVH_APPLICATION_KEY", From 456c9217d15e38f25da173dba83890fc1cfc9a7a Mon Sep 17 00:00:00 2001 From: Zack Date: Fri, 5 Dec 2025 14:00:54 +0000 Subject: [PATCH 6/8] fix: use environment specific futo 1pass service account --- tf/deployment/.env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tf/deployment/.env b/tf/deployment/.env index 9d1b06e68..abdd0ed49 100644 --- a/tf/deployment/.env +++ b/tf/deployment/.env @@ -7,7 +7,7 @@ export TF_VAR_github_app_id="op://tf/GITHUB_APP_IMMICH_TOFU/app_id" export TF_VAR_github_app_pem_file="op://tf/GITHUB_APP_IMMICH_TOFU/pkcs1" export TF_VAR_github_owner="op://tf/GITHUB_APP_IMMICH_TOFU/owner" export TF_VAR_op_service_account_token="op://tf/1pass_service_account/superuser_token" -export TF_VAR_futo_op_service_account_token="op://tf_prod/yucca_futo_1pass_superuser_service_account/password" +export TF_VAR_futo_op_service_account_token="op://tf_$ENVIRONMENT/yucca_futo_1pass_superuser_service_account/password" export TF_VAR_discord_token="op://tf/IMMICH_TF_DISCORD_BOT_TOKEN/password" export TF_VAR_zitadel_profile_json="op://tf/ZITADEL_PROFILE_JSON/password" export TF_VAR_zitadel_github_client_id="op://tf/GITHUB_OAUTH_APP_IMMICH_ZITADEL_CLIENT_ID/password" From c8a9b5ec7460c312365ed050308c50d5aada754c Mon Sep 17 00:00:00 2001 From: Zack Date: Fri, 5 Dec 2025 14:01:15 +0000 Subject: [PATCH 7/8] feat: yucca tailscale api key and tailnet id secrets --- .../modules/shared/1password/futo-account/yucca-secrets.tf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf b/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf index 912780ab0..bfdcfd305 100644 --- a/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf +++ b/tf/deployment/modules/shared/1password/futo-account/yucca-secrets.tf @@ -10,7 +10,9 @@ module "yucca-manual-secrets" { "TF_STATE_S3_SECRET_KEY", "OVH_APPLICATION_KEY", "OVH_APPLICATION_SECRET", - "OVH_CONSUMER_KEY" + "OVH_CONSUMER_KEY", + "TAILSCALE_API_KEY", + "TAILSCALE_TAILNET_ID" ] scoped = [] } From 79fe1dc189218476bab52e29030b94aa286c08a0 Mon Sep 17 00:00:00 2001 From: Zack Date: Thu, 19 Mar 2026 15:45:20 +0000 Subject: [PATCH 8/8] chore: upgrade tf providers --- .../futo-account/.terraform.lock.hcl | 66 ++++++++----------- .../shared/1password/futo-account/config.tf | 2 +- 2 files changed, 29 insertions(+), 39 deletions(-) diff --git a/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl b/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl index 3cbebc0b2..5a172880c 100644 --- a/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl +++ b/tf/deployment/modules/shared/1password/futo-account/.terraform.lock.hcl @@ -2,52 +2,42 @@ # Manual edits may be lost in future updates. provider "registry.opentofu.org/1password/onepassword" { - version = "2.1.0" + version = "2.2.1" constraints = "~> 2.0" hashes = [ - "h1:B3G7M02HxGCgT4S1+d4ITPR0vj7ZXDzGx+vqkKtk81c=", - "zh:0d6f803760aa7cae0e841cfca17ef04411231170b2844cc0b30556d5476d9dff", - "zh:17badbffb56309f28aee1893a6b93d1cd87ed5157704fb17b93889f0ccf8cc2d", - "zh:185e0c7c66cc159769d7b91c37ab51a546efc13fb99eb206481739a521f75236", - "zh:19e213f8265445a29d8bb7c7b1f0d4e3c1fdfd538178704f8e8378db2dcdf359", - "zh:49929666304f97301f44ee0fdd39f40f63e35ccfb4c81588439bdab6d5bafde0", - "zh:4de33f5630350d6a561d5d62994d525beb8849c94287c2658f39242fe3170cf8", - "zh:4f212a8fbbbaa7a47f1b31857be3bad2d590f92be845c6b252c9716bb70076d9", - "zh:596cc2bd9aaafd2e649aabcff0125afa9d4270f702813c935fbd5694eed002e7", - "zh:618e703a43608c502066c5b909ead45b1f4202f7cebc993f447278477d32cda2", - "zh:61fde3651bcb2e691ee9d82ce1de03588d006f53b2e8e2516910321da8627228", + "h1:CosIqZ6jkgylvF23rLyNixIecZAAhFyb61sLl6GrEsc=", + "zh:025709a6b5f1b3685d277f2c48f7cb8b53d14b3699c1123d7e9a2135c099c533", + "zh:037fc89d150063a8aacdcab08ba26038b489fe2468d509b842d298ea59096ca6", + "zh:233777182b25faf1658e8ce171b684460983bb41cff79fb243662f3f9dc5ca6c", + "zh:2fb5ca2fc8c37b1d1c54da646ed13bf40897941fe92eece784fba496f677b533", + "zh:4b25b5ce1f694ec265e65234fc85d6bdf3810297ffeaced54ad46a1ba28142de", + "zh:5509d1e4fb7b45c63124ec66fd1f9d6757daa8bf1f7bdd724d5adb2965b61436", "zh:890df766e9b839623b1f0437355032a3c006226a6c200cd911e15ee1a9014e9f", - "zh:db05022113841a00174bba5e24cfc77195bbc03d24339c5e8ac4346069901e45", - "zh:dcc7792a24c74890081a96ba2bc360d90ab71a4d25232ca18046d9868c835e21", - "zh:f2e67a298d20bf52cb208611767b420962d3f0d518e89cf41cc432551b1faf63", - "zh:f7e587814506c7e74fc1d80b29465c8e4b7bdbf803f7f8c0a8bb498968cdd58d", + "zh:a23ba946c629ec912b2fcbf606a2eb8853626ec0e0bee749f2d39146a872c082", + "zh:a3d3024485426237d7b4a4350b12dda4d29d88f3942246a9370be35ec2a51e9e", + "zh:a6ef65544ab8fc26d468b38636407a3d2d902e35c51b648729bf97c31d1937f9", + "zh:afbe9480a0da0ad8dc514b277f1e4be36b8931f045021d05c21665ef1ac0b7c8", + "zh:b2e96e69fa9ff7e179dccdef5b785cd020eb46bb2b3d1d507d009d71be6b0c26", + "zh:ceefaede9e8a3104463523ba267e3e985b27a706f7628a9ddd37330c2ca59d4d", + "zh:ea77786bd6809ff4f8043b84a0212fec4de18b7d51bc420417ba10999ca99887", + "zh:f7d8160c3669c8ab76a2da14ea740d91a08ca23d1fb657669e52a840b2b113d9", ] } provider "registry.opentofu.org/hashicorp/random" { - version = "3.7.2" - constraints = "3.7.2" + version = "3.8.1" + constraints = "3.8.1" hashes = [ - "h1:5wxrQQTchfk/2S1wSi9lx/fmiscVLGI3kL2v/+LccHU=", - "h1:C1D2Vo445WXAeLwSpovebSDR97ohiGvXVixcXJneQTg=", - "h1:KvLLxlMi6iNdlZS+vQAwovIeL2r5Q2s/EXXF+oypKHI=", - "h1:Q1EQQw7icbHSYUSYMlgi4qSXPuJDySuMjXcC0WqzgP8=", - "h1:cFGCdxTlsrteTiaOV/iOQdql7eJkD3F/vtJxenkj9IE=", - "h1:o15Kr/27vFN5AD9YkF48tDrHLSAshEq4Q7sAxIViZHM=", - "h1:rdpkD+Rzr+KCPqOvb1ckzupjWCOum/boRX4FqVboAHQ=", - "h1:ttMGebt31P1FZCEWptLTMpmx1aeDvkJ9nBDivtCCkyM=", - "h1:wz31hqWhHTq9bgIM/3+VNqy89JAICMXSwCmG8A70w0A=", - "h1:yHMBbZOIHlXUuBQ8Mhioe0hwmhermuboq2eNNoCJaf8=", - "zh:2ffeb1058bd7b21a9e15a5301abb863053a2d42dffa3f6cf654a1667e10f4727", - "zh:519319ed8f4312ed76519652ad6cd9f98bc75cf4ec7990a5684c072cf5dd0a5d", - "zh:7371c2cc28c94deb9dba62fbac2685f7dde47f93019273a758dd5a2794f72919", - "zh:9b0ac4c1d8e36a86b59ced94fa517ae9b015b1d044b3455465cc6f0eab70915d", - "zh:c6336d7196f1318e1cbb120b3de8426ce43d4cacd2c75f45dba2dbdba666ce00", - "zh:c71f18b0cb5d55a103ea81e346fb56db15b144459123f1be1b0209cffc1deb4e", - "zh:d2dc49a6cac2d156e91b0506d6d756809e36bf390844a187f305094336d3e8d8", - "zh:d5b5fc881ccc41b268f952dae303501d6ec9f9d24ee11fe2fa56eed7478e15d0", - "zh:db9723eaca26d58c930e13fde221d93501529a5cd036b1f167ef8cff6f1a03cc", - "zh:fe3359f733f3ab518c6f85f3a9cd89322a7143463263f30321de0973a52d4ad8", + "h1:EHn3jsqOKhWjbg0X+psk0Ww96yz3N7ASqEKKuFvDFwo=", + "zh:25c458c7c676f15705e872202dad7dcd0982e4a48e7ea1800afa5fc64e77f4c8", + "zh:2edeaf6f1b20435b2f81855ad98a2e70956d473be9e52a5fdf57ccd0098ba476", + "zh:44becb9d5f75d55e36dfed0c5beabaf4c92e0a2bc61a3814d698271c646d48e7", + "zh:7699032612c3b16cc69928add8973de47b10ce81b1141f30644a0e8a895b5cd3", + "zh:86d07aa98d17703de9fbf402c89590dc1e01dbe5671dd6bc5e487eb8fe87eee0", + "zh:8c411c77b8390a49a8a1bc9f176529e6b32369dd33a723606c8533e5ca4d68c1", + "zh:a5ecc8255a612652a56b28149994985e2c4dc046e5d34d416d47fa7767f5c28f", + "zh:aea3fe1a5669b932eda9c5c72e5f327db8da707fe514aaca0d0ef60cb24892f9", + "zh:f56e26e6977f755d7ae56fa6320af96ecf4bb09580d47cb481efbf27f1c5afff", ] } diff --git a/tf/deployment/modules/shared/1password/futo-account/config.tf b/tf/deployment/modules/shared/1password/futo-account/config.tf index 63f0eb561..d1a0f92f8 100644 --- a/tf/deployment/modules/shared/1password/futo-account/config.tf +++ b/tf/deployment/modules/shared/1password/futo-account/config.tf @@ -11,7 +11,7 @@ terraform { } random = { source = "hashicorp/random" - version = "3.7.2" + version = "3.8.1" } tls = { source = "hashicorp/tls"