Skip to content

Platform (Stage 2)

Stage 2 is Terraform. It assumes a working Kubernetes cluster from Stage 1 and deploys 20 modules onto it.

Every module is a directory under stage2/, wired together in stage2/main.tf. All input variables live in the root stage2/variables.tf and are passed down, so a module never reads a variable directly.

Always-on modules

These have no count, so they deploy on every apply.

Module Deploys
Preflight Cross-module compatibility checks that must pass before cluster changes
Kubernetes CoreDNS configuration, Prometheus CRDs
NGINX Ingress Ingress controller, fronted by MetalLB
Cert-Manager TLS certificates from Let's Encrypt
Longhorn Distributed block storage, the default StorageClass
MinIO S3-compatible object storage
Monitoring Prometheus, Grafana, AlertManager, ElastAlert2
Kubecost Cluster cost attribution
OAuth2 Proxy Auth0-backed authentication in front of the web UIs
ArgoCD GitOps continuous deployment
Stakater Reloader Restarts workloads when a Secret or ConfigMap changes

Gated modules

Controlled by an enable flag. The Terraform idiom is count = var.<name>_enable ? 1 : 0, so a disabled module is simply not in the plan.

Module Gate Default
GitLab Platform host_machine_architecture == "amd64" auto, AMD64 only
Logging logging_module_enable true
ArgoCD Image Updater argocd_image_updater_enable false
Datadog datadog_enable false
Cloudflare Tunnel cloudflare_tunnel_enable false
Sealed Secrets sealed_secrets_enable true
LiteLLM litellm_enable false
OmniRoute omniroute_enable false
Tailscale tailscale_enable false
WireGuard wireguard_enable false

The stage2/vpn/ module has no module-level gate, so it is always in the plan and its vpn namespace is always created. Its two backends, Tailscale and WireGuard, are gated per resource by tailscale_enable and wireguard_enable, both false by default and independent of each other.

GitLab is AMD64 only

registry.gitlab.com/gitlab-org/build/cng/kubectl publishes no ARM64 image. On an ARM64 control plane the GitLab module is skipped entirely, which also removes ArgoCD's depends_on source.

Ordering

Modules do not deploy in file order. See the dependency graph for the actual depends_on DAG and why the ordering matters.