# flux-operator: a Kubernetes controller that installs and upgrades Flux for you

> The Flux Operator is a CRD controller that manages the lifecycle of Flux CD and the ControlPlane distribution, replacing the bootstrap procedure with a declarative API. It adds self-service ResourceSets, preview environments for pull requests on GitHub, GitLab, Gitea and Azure DevOps, a Flux web UI, and an MCP server for talking to clusters from an AI assistant.

**controlplaneio-fluxcd/flux-operator** — GitOps on Autopilot Mode

- Repository: https://github.com/controlplaneio-fluxcd/flux-operator
- Website: https://fluxoperator.dev
- Stars: 774 · Forks: 78
- Language: Go
- License: AGPL-3.0
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/controlplaneio-fluxcd-flux-operator

## A controller for the controllers

The Flux Operator is a Kubernetes CRD controller that manages the lifecycle of CNCF Flux CD and of the ControlPlane enterprise distribution. The repository description, which is the shortest possible statement of the idea, calls it GitOps on Autopilot Mode.

The framing in the README is Autopilot for Flux CD. The operator offers an alternative to the Flux Bootstrap procedure, and it removes the operational burden of managing Flux across fleets of clusters by fully automating the installation, the configuration, and the upgrade of the Flux controllers based on a declarative API.

That last phrase is the design in one line. The usual way to get Flux into a cluster is to run a bootstrap command against it, which means every new cluster needs a human or a job with credentials, and every upgrade is a repeat of the same manual step. With an operator, the desired state of the Flux installation is a Kubernetes object, and a cluster that joins the fleet gets the controllers installed and kept current by the operator reconciling that object.

The scope of the extension over upstream Flux is wide, and the README lists it in five parts.

Self-service capabilities, deployment windows, and preview environments for pull request testing on GitHub, GitLab, Gitea, and Azure DevOps.

Advanced configuration, which covers Flux multi-tenancy lockdown, sharding, horizontal and vertical scaling, and persistent storage, with fine tuning of the controllers through Kustomize patches, and it streamlines the transition from Git as the delivery mechanism for the desired state to OCI artifacts and S3-compatible storage.

Deep insights, with detailed reports and Prometheus metrics about the controllers' readiness status, reconciler statistics, and cluster state synchronisation, plus the Flux Web UI for a real-time view of the pipelines.

The ResourceSet API, which lets platform teams define their own application standard as a group of Flux and Kubernetes resources that can be templated, parameterised and deployed as a single unit.

And the Flux MCP Server, which connects AI assistants to clusters running the operator.

The licence is AGPL-3.0, the project is not archived, the last push was on 2026-10-21, and the release tags are v0.61.0 from 2026-10-01, v0.60.0 from 2026-09-11, and v0.59.0 from 2026-08-31, so it moves at roughly one release a month.

## Installing the operator, then declaring a FluxInstance

The quickstart has two halves, and the first half is installing the operator itself.

```bash
helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator \
  --namespace flux-system
```

The chart comes from an OCI registry reference rather than a chart repository, and the note under it says the operator can also be installed with Helm, Terraform, OperatorHub, kubectl, and other methods, with the installation guide linked for the details. The artifact hub and operator hub badges in the README are there because both of those channels are supported.

The second half is a FluxInstance resource named flux in the flux-system namespace, which installs the latest Flux stable version.

```yaml
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
  name: flux
  namespace: flux-system
  annotations:
    fluxcd.controlplane.io/reconcileEvery: "1h"
    fluxcd.controlplane.io/reconcileArtifactEvery: "10m"
    fluxcd.controlplane.io/reconcileTimeout: "5m"
spec:
  distribution:
    version: "2.x"
    registry: "ghcr.io/fluxcd"
    artifact: "oci://ghcr.io/controlplaneio-fluxcd/flux-operator-manifests"
  components:
    - source-controller
    - kustomize-controller
    - helm-controller
    - notification-controller
    - image-reflector-controller
    - image-automation-controller
  cluster:
    type: kubernetes
    size: medium
    multitenant: false
    networkPolicy: true
    domain: "cluster.local"
  kustomize:
    patches:
      - target:
          kind: Deployment
        patch: |
          - op: replace
            path: /spec/template/spec/nodeSelector
            value:
              kubernetes.io/os: linux
          - op: add
            path: /spec/template/spec/tolerations
            value:
              - key: "CriticalAddonsOnly"
                operator: "Exists"
```

The three annotations at the top are the reconciliation policy, and they are the first thing to look at. reconcileEvery is how often the operator re-reconciles, an hour in the example, reconcileArtifactEvery is how often it refreshes the artifact it deploys, ten minutes, and reconcileTimeout bounds a single reconciliation, five minutes. Those are the numbers that decide how quickly a change to the Flux installation reaches the cluster, and how much work the operator does when nothing has changed.

The spec is the desired state of the Flux installation itself. The distribution block says which version of Flux to install and where to get the manifests from, with the artifact pointing at an OCI reference. The components list names the six controllers to run, and it is a list rather than a flag, so a cluster that does not need the notification or image controllers simply does not get them.

The cluster block is about the shape of the installation. The type is kubernetes, the size is medium, multitenant is false, networkPolicy is true, and the domain is the cluster DNS domain. Those settings are what the multi-tenancy lockdown, the sharding, and the scaling options in the feature list refer to, and they are the ones to get right before the operator rolls out to a whole fleet.

And the kustomize block is the escape hatch, a list of patches applied to the generated manifests. The example patches a node selector onto the deployments and adds a toleration for the CriticalAddonsOnly taint, which is the standard way to keep the control plane pods off a tainted node pool.

## Syncing from Git, and the secret a private repository needs

The second part of the quickstart is how the cluster gets its desired state, and it is a short addition to the same resource.

```yaml
apiVersion: fluxcd.controlplane.io/v1
kind: FluxInstance
metadata:
  name: flux
  namespace: flux-system
spec:
  sync:
    kind: GitRepository
    url: "https://github.com/my-org/my-fleet.git"
    ref: "refs/heads/main"
    path: "clusters/my-cluster"
    pullSecret: "flux-system"
  # distribution omitted for brevity
```

The sync block names a source kind, which here is a GitRepository, a URL, a ref, a path inside the repository, and the name of a secret holding credentials. The path is per cluster, which is the whole point of the fleet model: one repository holds the configuration for every cluster, and the operator points each cluster at its own directory.

For a private repository, the credential has to exist in the flux-system namespace first, and the README shows the Flux CLI creating it.

```bash
flux create secret git flux-system \
  --url=https://github.com/my-org/my-fleet.git \
  --username=git \
  --password=$GITHUB_TOKEN
```

The note after it points at the cluster sync guide for configuring syncing from Git repositories, container registries, and S3-compatible storage, which are the three sources the feature list mentions. That third one is a real change in practice, because moving the delivery mechanism from Git to an object store is what makes the operator useful for artefacts that are built rather than authored, and the sync configuration is where that choice is expressed.

One thing to keep in mind when you read the example: the pullSecret is a name in the cluster, not the credentials themselves. The secret has to be created in every cluster that syncs from a private source, which is the operational step that the operator does not do for you.

## ResourceSets, preview environments, and the MCP server

The three features that go beyond installation and upgrade are what make the operator interesting to a platform team.

The ResourceSet API is the self-service piece. It lets platform teams define their own application standard as a group of Flux and Kubernetes resources, and those resources can be templated, parameterised and deployed as a single unit on self-service environments. The distinction from plain Flux is that a ResourceSet is a reusable template with parameters, so an application team requests an environment by supplying values rather than by writing manifests. The README links a separate introduction page for it, which suggests the API has more surface than a paragraph can carry.

Preview environments are the part that connects the operator to the pull request workflow. The operator supports ephemeral environments for pull request testing across GitHub, GitLab, Gitea, and Azure DevOps, and the ResourceSet API integrates with Git pull requests to create those environments for testing and validation. Four forges is a notable coverage, and it is the feature that turns GitOps from a deployment process into a review process, because the environment that proves the change works is the same machinery that will deploy it.

The Flux MCP Server is the newest-sounding piece, and it is the one with the most obvious audience. It connects AI assistants to Kubernetes clusters running the operator, so you can analyse a deployment across environments, troubleshoot issues, and perform operations using conversational prompts. The dependency list confirms it is a real implementation rather than a description, with the Model Context Protocol Go SDK at version 1.7.0 in the module requirements, and the Makefile has a separate mcp-build target alongside cli-build, so the CLI, the MCP server, and the operator are three separate binaries built from the same repository.

The observability story is the fourth piece. The operator produces reports and Prometheus metrics about the controllers' readiness status, reconciler statistics, and cluster state synchronisation, and the Flux Web UI gives a real-time view of the pipelines, which is where you monitor deployments, track reconciliation status, and troubleshoot. The README describes the operator as a key component of the ControlPlane enterprise offering, designed to automate the rollout of new Flux versions, CVE patches and hotfixes to production, and says it is end-to-end tested along with the ControlPlane Flux distribution on Red Hat OpenShift, Amazon EKS, Azure AKS, and Google GKE.

## The build, the generated APIs, and the container

The repository layout is the standard controller-runtime shape, and the tooling is worth a look because it shows how the CRDs and the deployment artefacts are produced.

The api directory holds the API types, cmd holds the operator entry point, internal holds the implementation, and web holds the web UI, which is embedded into the binary. There is a config directory for the manifests and the CRD bases, an actions directory, a docs directory, a test directory, and a hack directory with the boilerplate header file used by the generators.

The Makefile shows the generation step. The generate target runs controller-gen twice, once for object deep copies with a header file, and once for the RBAC role and the CRDs, writing them to config/crd/bases. So the CRDs in the repository are generated from the Go types, which is the arrangement that keeps the API and the schema from drifting.

The default target runs test, lint, build, cli-build, and mcp-build, and the test target depends on tidy, generate, fmt, vet, and envtest, with the Kubernetes version used for the envtest binaries pinned at 1.36.0. The image name defaults to the ghcr.io registry path, and the version variables are derived from the GitHub release tag, with a development version built from the branch name, the short commit, and a timestamp.

The container build is a two stage build. The builder is a golang:1.27 image, and the build runs with CGO_ENABLED=0 and GOFIPS140=latest, which is the knob that selects the Go cryptography implementation with FIPS 140 compliance. The binary is built with the version injected through ldflags, and stripped with -s and -w, and the runtime image is the distroless static base running as the non-root user 65532. The license file is copied into the image, which is what the AGPL requires.

The module itself targets Go 1.27 and is built around the Flux cd libraries, with the api, auth, cache, kustomize, runtime, server-side apply, tar, and version packages from the fluxcd organisation, plus go-git, go-containerregistry, the AWS SDK for CodeCommit and marketplace metering, the GitHub and Azure DevOps clients, the Gitea SDK, and the OpenID Connect library.

## Licence, cadence, and what to check before the rollout

Two practical points close this out.

The first is the licence. The operator is AGPL-3.0, and the Makefile header carries the SPDX identifier. A controller that runs inside your cluster and talks to it is a network service in the terms of the licence, so the copyleft obligations reach the distribution of a modified version. The Dockerfile copies the LICENSE into the image, which is the mechanism the project uses to satisfy that. If your organisation has a policy about AGPL components in the cluster, that is the conversation to have first, and the LICENSE file is the thing to read.

The second is the cadence and the shape of the API. The version numbers are in the low sixties, and the releases land roughly monthly, with the last three being v0.59.0 in August 2026, v0.60.0 in September, and v0.61.0 in October. A project at version 0.61 with a monthly release train and an active development branch in the repository is one to pin deliberately, with a deliberate upgrade process, rather than one to track automatically.

Before you turn it on across a fleet, the checks in the quickstart are the ones worth doing first. Confirm the distribution version you want, since the example uses a 2.x range rather than a pinned version, and the operator will keep that instance current within that range. Confirm the component list, because a controller you do not need is a controller you have to patch. Confirm the cluster settings, in particular multitenant and networkPolicy, since those two decide whether the installation is isolated. And confirm the reconcile intervals in the annotations, because they set both the latency of a change and the idle load the operator puts on every cluster in the fleet.

## Conclusion

flux-operator fits a platform team that runs Flux across a fleet of clusters and wants the controllers installed, patched and upgraded from one declarative resource instead of a bootstrap script per cluster, and that wants preview environments and self-service templates for its application teams. It does not fit a single cluster where the standard Flux install is enough, and it does not fit an organisation that cannot accept an AGPL licensed controller in its cluster. Verify first that the FluxInstance you write pins the distribution version and the component list you intend, that the reconcile intervals and timeout in the annotations match how quickly you want changes applied, and that the cluster settings such as multitenant and networkPolicy are what your security model requires before the operator rolls the controllers out to every cluster in the fleet.

## FAQ

### What does the Flux Operator do?

It is a Kubernetes CRD controller that manages the lifecycle of Flux CD and the ControlPlane distribution, automating the installation, configuration and upgrade of the Flux controllers from a declarative API. The README frames it as an alternative to the Flux Bootstrap procedure for fleets of clusters.

### How do I install the Flux Operator?

With a Helm install from the OCI registry, helm install flux-operator oci://ghcr.io/controlplaneio-fluxcd/charts/flux-operator with the namespace flux-system. The README also says it can be installed with Terraform, OperatorHub, kubectl, and other methods.

### What is a FluxInstance and what can I set in it?

It is the custom resource that describes the desired state of a Flux installation, with a distribution block for the version and artifact, a components list for the controllers to run, a cluster block for type, size, multi-tenancy, network policy and domain, a kustomize block for patches, and a sync block for the source of the cluster state.

### What are the ResourceSet API and preview environments for?

The ResourceSet API lets platform teams define an application standard as a group of Flux and Kubernetes resources that are templated, parameterised and deployed as a single unit, and it integrates with Git pull requests to create ephemeral preview environments for testing, across GitHub, GitLab, Gitea and Azure DevOps.

### What is the Flux MCP Server?

It connects AI assistants to Kubernetes clusters running the operator, so a deployment can be analysed across environments, issues troubleshot, and operations performed through conversational prompts. It is built as a separate binary alongside the operator and the CLI.

## Sources

- [controlplaneio-fluxcd/flux-operator on GitHub](https://github.com/controlplaneio-fluxcd/flux-operator)
- [License: AGPL-3.0](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/LICENSE)
- [Project website](https://fluxoperator.dev)
- [README](https://github.com/controlplaneio-fluxcd/flux-operator/blob/main/README.md)
- [Releases](https://github.com/controlplaneio-fluxcd/flux-operator/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/controlplaneio-fluxcd-flux-operator
