feat: add auth.futo.cloud custom domain for prod customer zitadel (#1768)

This commit is contained in:
Zack Pollard
2026-07-01 21:14:01 +01:00
committed by GitHub
parent e3dd4f5819
commit c5660eba3d
6 changed files with 66 additions and 9 deletions
@@ -25,6 +25,26 @@ provider "registry.opentofu.org/1password/onepassword" {
]
}
provider "registry.opentofu.org/cloudflare/cloudflare" {
version = "5.21.1"
constraints = "5.21.1"
hashes = [
"h1:Lh5LHSNKoKwCx4F/YlRjoLZ+jZLxnoxEfOMzUX9n4zg=",
"h1:gNF1Sro3G9nXhtdkitXwDVKxI1jpBAf8KPv+Y4kAJwk=",
"h1:hU72otEs26Wx6tcJD9igX6I/BQtVgeRuaIe3s/hn6bQ=",
"h1:iWJb0lHfVWmCJQSyroXOT8zQlFOT8k1caHcfaooG5wk=",
"zh:049719425b8be43d9d4f0c208217aca0baa22374f061d7ff92f02563490f649c",
"zh:0a8a3c1b26680b437fe9e7910ca81e532d36f8efacfb14f45690b6a779856993",
"zh:32b61f80892243f7ab8e453fa038c1f3e2aac733ccb98307c2cfe798b2793b32",
"zh:42c27f3cd62979e70716c51f682a3d131d51ad76d86dff83d8cdbfffcebac841",
"zh:4c8cd464f9b6ecde5cd4430bbba4be3b810826105e51ef6328b6a2b69f821443",
"zh:586ea42ef74d6c5bc4c9b89da6b1f8618a19f4e80272fe8d615e7d5b11c491af",
"zh:b09b86c7cac7085e01c9b7a828f09d13c44589d3e3cd42f0b694ca3e4cd3ed0a",
"zh:eac80665e60c701b37a6318f4e405d67f1720f8da5f93135c6256049282d3367",
"zh:f809ab383cca0a5f83072981c64208cbd7fa67e986a86ee02dd2c82333221e32",
]
}
provider "registry.opentofu.org/hashicorp/null" {
version = "3.3.0"
constraints = "~> 3.2"
@@ -21,12 +21,11 @@ before Terraform can run. Do this in the ZITADEL Cloud console and 1Password:
1. Create a new instance for customer auth in the FUTO ZITADEL Cloud account.
One per env — prod first, dev/staging later (or vice versa).
2. Add the custom domain:
- prod → `auth.futo.tech`
- staging → `auth.staging.futo.tech` (or chosen equivalent)
- dev → `auth.dev.futo.tech` (or chosen equivalent)
DNS is managed via the existing Cloudflare modules.
2. Custom domain — **prod only**: `auth.futo.cloud`. Add it on the instance in
the ZITADEL Cloud console. The `auth.futo.cloud` CNAME → the prod instance
URL is managed by this module (`dns.tf`, in the futo `futo.cloud` zone), so
no manual DNS is needed. dev/staging have no custom domain — they use the
generated `<name>.zitadel.cloud` instance URL directly.
3. In each instance, create a machine user with role `IAM_OWNER`, generate a
JWT key, and download the profile JSON.
4. Apply `modules/shared/1password/futo-account` — the manual-secrets module
@@ -40,8 +39,9 @@ before Terraform can run. Do this in the ZITADEL Cloud console and 1Password:
- `CUSTOMER_ZITADEL_SMTP_SENDER_ADDRESS`
Replace each stub password in `yucca_tf_${env}_manual` with the real value
(custom domain from step 2, profile JSON from step 3, SMTP credentials
for the chosen provider, and sender address e.g. `no-reply@futo.tech`).
(`CUSTOMER_ZITADEL_DOMAIN` = the instance URL `<name>.zitadel.cloud`, profile
JSON from step 3, SMTP credentials for the chosen provider, and sender
address e.g. `no-reply@futo.cloud`).
Re-apply `shared/1password/futo-account` so the copy-secrets module
mirrors each value into the `yucca_tf_${env}` vault that this module
reads from via `data "onepassword_item"` lookups at plan/apply time. No
@@ -7,6 +7,10 @@ terraform {
source = "zitadel/zitadel"
version = "2.12.8"
}
cloudflare = {
source = "cloudflare/cloudflare"
version = "5.21.1"
}
onepassword = {
source = "1Password/onepassword"
version = "~> 2.1"
@@ -0,0 +1,29 @@
data "terraform_remote_state" "futo_cloudflare_api_keys" {
backend = "pg"
config = {
conn_str = var.tf_state_postgres_conn_str
schema_name = "prod_cloudflare_futo_api_keys"
}
}
data "cloudflare_zone" "futo_cloud" {
filter = {
name = "futo.cloud"
}
}
# Prod only: auth.futo.cloud -> the prod instance URL, which is exactly what
# CUSTOMER_ZITADEL_DOMAIN holds (the provider connects to it). dev/staging use
# the generated <name>.zitadel.cloud URL directly with no custom domain.
# DNS-only so ZITADEL terminates TLS for the custom domain.
resource "cloudflare_dns_record" "customer_auth" {
count = var.env == "prod" ? 1 : 0
zone_id = data.cloudflare_zone.futo_cloud.id
name = "auth.futo.cloud"
type = "CNAME"
content = data.onepassword_item.customer_zitadel_domain.password
ttl = 1
proxied = false
}
@@ -7,3 +7,7 @@ provider "zitadel" {
provider "onepassword" {
service_account_token = var.futo_op_service_account_token
}
provider "cloudflare" {
api_token = data.terraform_remote_state.futo_cloudflare_api_keys.outputs.terraform_key_futo_cloudflare_account
}
@@ -27,5 +27,5 @@ remote_state {
}
dependencies {
paths = []
paths = ["../../../shared/cloudflare/futo-api-keys"]
}