Infrastructure
This document covers the Terraform-managed edge and Cloudflare infrastructure for quant-app.
For how Kubernetes resources are generated from Gradle, see build-system.md. For CI/CD pipeline details, see ci-cd.md.
Overview
Infrastructure is split across three Terraform stacks:
terraform/edge/oci— OCI and Cloudflare-managed production edge: tunnel, DNS, Zero Trust access policiesterraform/edge/local— dev edge stack for the local cluster: equivalent Cloudflare tunnel deploymentterraform/kubernetes— in-cluster monitoring and application workloads that sit behind the edge; reads the Grafana MCP public host from the selected edge state
Terraform Variable Loading
Each Terraform configuration directory contains environment files that load variable values into the shell before running any terraform command:
.env— production variable values.env.stg— staging variable values
Source the appropriate file before running Terraform:
# Production
cd terraform/edge/oci
source .env && terraform plan
# Staging
cd terraform/edge/local
source .env.stg && terraform plan
This applies to all three stacks (terraform/edge/oci, terraform/edge/local, terraform/kubernetes). Never run terraform plan, terraform apply, or terraform destroy in any of these directories without sourcing the correct env file first — commands will fail or use incorrect variable values.
Terraform Edge (terraform/edge)
Production Edge (terraform/edge/oci)
- Reads application hosts from
gradle.prod.properties. - Fails fast if any app host does not belong to the configured Cloudflare zone.
- Grafana and Grafana MCP remain Terraform-owned via
grafana_subdomain/grafana_mcp_subdomain; they are not sourced from Gradle properties.
Local Dev Edge (terraform/edge/local)
- Reads application hosts from
gradle.stg.properties. - Deploys
cloudflared-localinto the local cluster. - Uses
devas the Cloudflare tunnel/app/policy environment label plus the Terraform-owned Grafana hosts. - Fails fast if any app host does not belong to the configured Cloudflare zone.
Shared Modules
Shared edge logic lives in child modules. Prefer updating these rather than the stack-local files when changing cross-cutting behavior:
terraform/modules/app_hosts— hostname parsing and validationterraform/modules/cloudflare_edge— tunnel publishing, Grafana MCP IP allowlistterraform/modules/versions— shared runtime version pins
Configure the Grafana MCP IP allowlist through allowed_ips in the shared module. Override hostname labels only if the public Grafana or Grafana MCP subdomains change.
Cloudflare API Token Requirements
The API token used by both edge stacks must include: Zone:Read, DNS:Edit, Tunnel:Edit, and Access: Apps and Policies:Edit.
Terraform Kubernetes (terraform/kubernetes)
- Owns in-cluster monitoring and application workloads behind the edge.
- Resolves the Grafana MCP ingress host from the edge state configured by
edge_state_path. - Default:
terraform/edge/oci/terraform.tfstate. Point atterraform/edge/local/terraform.tfstatewhen applying against the local cluster.
Deployment Environments
| Environment | Cluster | Edge stack | Properties source | Env file |
|---|---|---|---|---|
| Production | OCI k3s | terraform/edge/oci |
gradle.prod.properties |
.env |
| Staging | local k3d | terraform/edge/local |
gradle.stg.properties |
.env.stg |
Related Documents
- build-system.md — Gradle build types and JKube resource generation
- ci-cd.md — how resources are applied in CI/CD pipelines
- backend-conventions.md — per-module Kubernetes manifest details