Skip to content

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 policies
  • terraform/edge/local — dev edge stack for the local cluster: equivalent Cloudflare tunnel deployment
  • terraform/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-local into the local cluster.
  • Uses dev as 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 validation
  • terraform/modules/cloudflare_edge — tunnel publishing, Grafana MCP IP allowlist
  • terraform/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 at terraform/edge/local/terraform.tfstate when 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