Terraform/Terragrunt Modules#
This page documents the infrastructure-as-code modules in modules/. All modules use OpenTofu (via Terragrunt's terraform_binary = "tofu" setting) with an S3 remote state backend.
Shared Patterns#
Configuration Hierarchy#
root.hcl # S3 backend config, tofu binary
├── common-inputs.yaml # Shared variables (env, domain, etc.)
└── modules/
├── terragrunt.hcl # Common include (find_in_parent_folders)
└── <module>/
└── terragrunt.hcl # Module-specific inputs, deps, providers
root.hcl— Defines the S3 backend and setstofuas the Terraform binarycommon-inputs.yaml— Shared variables: environment (production), project name (homelab-cluster), cluster name, AWS region, kubeconfig path, ArgoCD host, Authentik URL, domain (cowlab.org)modules/terragrunt.hcl— Common include that referencesroot.hclviafind_in_parent_folders()- Per-module
terragrunt.hcl— Loads common inputs, defines module-specific inputs, declares dependencies, and generates provider configurations (Kubernetes, Helm) from kubeconfig
CI/CD Pipeline#
Infrastructure changes are deployed via the deploy.yaml GitHub Actions workflow:
- On pull request — Runs
terragrunt planfor review (no changes applied) - On merge to main — Runs
terragrunt apply - Network access — Uses Tailscale VPN to reach the cluster from CI runners
- State access — Uses AWS OIDC (no static credentials) for S3 state bucket
⚠️ Always open a pull request for Terragrunt changes — never push directly to main.
Module: bootstrap#
- Purpose: Creates the foundational AWS resources needed by all other modules
- Key resources:
- AWS OIDC provider (for GitHub Actions → AWS authentication without static credentials)
- S3 bucket for Terraform state storage
- Notes: Must be applied first. This is the only module that bootstraps its own state.
Module: argocd-install#
- Purpose: Installs ArgoCD into the cluster via Helm chart
- Key resources:
- Helm release for ArgoCD
- Kubernetes namespace (
argocd) - Random client secret for Dex OIDC integration
- Inputs:
argocd_host,dex_url,github_username - Configuration:
- RBAC policies for ArgoCD access control
- Prometheus metrics enabled
- Dex OIDC integration with Authentik as upstream IdP
- Providers: Kubernetes, Helm (generated from kubeconfig)
Module: argocd-configure#
- Purpose: Creates the bootstrap ArgoCD Application that manages all other applications
- Key resources:
argocd_applicationresource namedbootstrap- Points to
manifests/bootstrap/in this repository
- Depends on:
argocd-install(declared via Terragruntdependencyblock) - Inputs:
argocd_host - Providers: Kubernetes (generated from kubeconfig)
- Notes: This is the link between Terragrunt-managed infrastructure and GitOps-managed applications
Module: cloudflare#
- Purpose: Manages DNS records and Cloudflare Zero Trust Tunnel
- Key resources:
- DNS A records: wildcard (
*.cowlab.org→ LB IP), plus specific records for chat, npm, pihole, pikvm, vaultwarden - DNS CNAME record:
docs.cowlab.org→ GitHub Pages - Cloudflare Zero Trust Tunnel: routes
jellyfin.cowlab.orgtotraefik.traefik.svc.cluster.local:80 - Tunnel token (used by
cloudflaredpod in-cluster)
- DNS A records: wildcard (
- Configuration files:
records.tf— DNS record definitionstunnel.tf— Tunnel and routing configuration
Module: s3-backups#
- Purpose: S3 infrastructure for Longhorn distributed storage backups
- Key resources:
- S3 bucket for backup data
- IAM user with scoped permissions
- IAM policy for bucket access
- Notes: Longhorn is configured to use this bucket for automatic volume backups
Module: authentik#
- Purpose: Configuration for the Authentik identity provider
- Key resources:
- Authentik provider and application resources
- Notes: Authentik itself is deployed as a Helm chart in
manifests/cluster/authentik/. This module manages its configuration (providers, applications, flows) via Terraform.