Back to articles
Technology Insight

Architecting GitOps for Infrastructure: Declarative OpenTofu Provisioning with Flux

August 13, 2026

Architecting GitOps for Infrastructure: Declarative OpenTofu Provisioning with Flux

Introduction

The shift toward Platform Engineering requires infrastructure provisioning to be as declarative, observable, and automated as application deployments. Traditional Infrastructure-as-Code (IaC) workflows rely on external CI/CD pipelines running speculative plans. This model introduces challenges, including state drift, manual execution bottlenecks, and loosely managed cloud credentials.

By uniting OpenTofu—the open-source evolution of Terraform under the Linux Foundation—with Flux, enterprises can implement a true GitOps model for infrastructure. This approach eliminates configuration drift by continuously reconciling cloud resources against a Git-based source of truth, leveraging Kubernetes as the control plane.

Core Concepts & Architecture

A GitOps-driven infrastructure architecture uses the Kubernetes control plane to orchestrate, execute, and monitor OpenTofu modules. Rather than running execution runners on local machines or ephemeral CI agents, the reconciliation loop is handled by the Flux Tofu/Terraform Controller (tf-controller).

[ Git Repository ] │ (Pushes commits to infra definitions) ▼ [ Flux Source Controller ] │ (Syncs source files) ▼ [ Flux Tofu Controller ] ◄───► [ S3 Backend (State Storage) ] │ (Generates plan/apply) ▼ [ Cloud Provider API (AWS/GCP) ]

The architecture relies on three primary components:

  1. Git Repository (Source of Truth): Contains modularized OpenTofu configuration files and variable definitions.

  2. Flux Source Controller: Continuously polls the repository for changes and packages the directory as a tarball artifact.

  3. Tofu Controller: Watches for artifact updates, instantiates ephemeral runner pods executing the designated OpenTofu binary version, synchronizes the state backend, and applies changes.

This continuous reconciliation loop runs an implicit tofu plan at designated intervals. If actual cloud resources diverge from Git, the controller flags a drift condition, allowing platform teams to automatically remediate or alert on out-of-band modifications.

Hands-on Implementation

To implement GitOps-driven cloud provisioning, we must deploy the Flux Tofu Controller and configure the target resource manifests.

Step 1: Define the GitRepository Source

Configure Flux to track the repository containing your OpenTofu definitions. Save this manifest as source-repository.yaml:

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata: 
  name: opentofu-infra-source
  namespace: flux-system
spec:
  interval: 1m0s
  url: https://github.com/enterprise/opentofu-infrastructure-aws
  ref:
    branch: main

Step 2: Configure the OpenTofu Custom Resource

Create the Terraform resource config (using the OpenTofu runner image) to execute the plan. Create tofu-provisioner.yaml:

apiVersion: infra.contrib.fluxcd.io/v1alpha2
kind: Terraform
metadata:
  name: aws-network-fabric
  namespace: flux-system
spec:
  runnerPodTemplate:
    spec:
      image: ghcr.io/flux-iac/tf-runner:v0.15.0-tofu1.6.2
  interval: 30m
  approvePlan: auto
  path: ./environments/production/vpc
  sourceRef:
    kind: GitRepository
    name: opentofu-infra-source
    namespace: flux-system
  writeOutputsToSecret:
    name: vpc-outputs-secret
    outputs:
  - vpc_id

  - private_subnets

Applying these manifests prompts the controller to fetch the repository, launch a secure runner pod equipped with the OpenTofu v1.6.2 runtime, initialize state backends, and automatically apply the VPC network configuration.

Security & Best Practices

Adopting GitOps for infrastructure changes how cloud credentials and access patterns are secured:

  • Implement Principle of Least Privilege (PoLP): Avoid hardcoding static Cloud Provider API keys in Kubernetes secrets. Instead, configure IAM Roles for Service Accounts (IRSA) on AWS or Workload Identity on GCP. This binds your Kubernetes runner pod directly to temporary, cryptographically validated cloud credentials.

  • State File Encapsulation: Secure your remote state storage (e.g., AWS S3, HashiCorp Consul) with Server-Side Encryption (SSE) and strict IAM policies. Restrict state file access solely to the controller runner pods and designated platform engineering roles.

  • Strict Plan Approval Workflows: For critical environments like production, switch approvePlan to manual. The controller will generate the execution plan, export it to a Kubernetes secret, and pause execution until an authorized engineer runs a patch command or updates a pull request status:

kubectl -n flux-system patch terraform aws-network-fabric \
  --type=merge -p '{"spec":{"approvePlan":"plan-xxxx"}}'

Conclusion

Decoupling infrastructure provisioning from legacy CI/CD pipelines and hosting it inside a Kubernetes-native GitOps pipeline transforms platform scalability. By executing OpenTofu via Flux, enterprises establish a secure, auditable, and self-healing control loop. This architectural pattern reduces configuration drift, enforces rigorous security boundaries through cloud workload identity, and ensures that the infrastructure state remains consistently aligned with the declarative source of truth.