Quick Start: Deploying Applications with Flux (Infra-Owned Registry)

• 5 min read

This guide shows how to deploy a new application into a cluster using one shared Flux installation and an infra-owned app registry.

You will:

  • Keep your application repo clean (no Flux CRDs)
  • Use standard Kustomize base/ + overlays/
  • Register the app with one small change in the infra repo

Prerequisites

  • You have kubectl access to the cluster
  • You have the Flux CLI installed
  • You have an infra/cluster Git repository ready (can be empty)

Step 0: Bootstrap Flux (Infra Repo)

Flux bootstrap installs Flux controllers into the cluster and commits the core sync manifests into your infra repo.

Validate prerequisites

flux check --pre

Bootstrap (example: GitHub)

flux bootstrap github \
  --owner=YOUR_GH_ORG \
  --repository=YOUR_INFRA_REPO \
  --branch=main \
  --path=clusters/prod \
  --personal=false

After bootstrap, your infra repo will include:

clusters/prod/flux-system/
  gotk-components.yaml
  gotk-sync.yaml
  kustomization.yaml

Flux will now continuously reconcile the infra repo path you bootstrapped.


Step 1: Add the Apps Registry Entry Point

Flux bootstrap syncs only clusters/prod/flux-system/ by default. To enable app onboarding via an infra-owned registry, add one additional Flux Kustomization that points at your apps registry directory.

Create the apps registry directory

In your infra repo:

clusters/prod/apps/
  kustomization.yaml

clusters/prod/apps/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources: []

This file will later list one registry file per application.

Create the Flux Kustomization that activates the registry

Create clusters/prod/apps-registry.yaml:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps-registry
  namespace: flux-system
spec:
  interval: 10m
  prune: true
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./clusters/prod/apps

Ensure Flux sync includes it

Edit clusters/prod/flux-system/kustomization.yaml (this is the Kustomize file, not the Flux CR) and include the new registry Kustomization:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - gotk-components.yaml
  - gotk-sync.yaml
  - ../apps-registry.yaml

Commit and push. Your cluster now has a single entry point that activates all app registry entries under clusters/prod/apps/.

At this point:

  • Flux is installed
  • Infra repo is being reconciled
  • App registry directory is active
  • No applications are deployed yet

Understanding Path Resolution: Flux vs Kustomize

Understanding how paths are resolved is critical when working with Flux and Kustomize. They intentionally behave differently.

Flux Kustomization.spec.path

Always resolved relative to the Git repository root referenced by sourceRef. Never relative to the location of the YAML file.

Example:

spec:
  path: ./clusters/prod/apps

This always means:

<git-repo-root>/clusters/prod/apps

This is why Flux paths often look “absolute” inside the repo.

Kustomize kustomization.yaml paths

Paths in kustomization.yaml (e.g. resources:) are resolved relative to the directory containing that kustomization.yaml.

Example:

resources:
  - app-foo.yaml

Resolved as:

clusters/prod/apps/app-foo.yaml

Mental model

Flux chooses the entry directory. Kustomize resolves everything underneath it.

Keeping this distinction clear avoids the most common Flux path mistakes.


Step 2: Create the Application Repository

Create a new Git repository for your app with the following structure:

base/
  kustomization.yaml
  deployment.yaml
  service.yaml

overlays/
  prod/
    kustomization.yaml

base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

overlays/prod/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base

patchesStrategicMerge:
  - replicas.yaml

Verify your manifests work locally:

kustomize build overlays/prod

Step 3: Create a Deploy Key for the App Repo

Create a deploy key for the app repository and grant it read-only access.

In the cluster, create a Secret (in the flux-system namespace):

apiVersion: v1
kind: Secret
metadata:
  name: app-foo-git-ssh
  namespace: flux-system
type: Opaque
stringData:
  identity: |
    -----BEGIN OPENSSH PRIVATE KEY-----
    ...
    -----END OPENSSH PRIVATE KEY-----
  known_hosts: |
    github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...

Step 4: Register the App in the Infra Repo

In the infra repo, add a new registry entry:

clusters/prod/apps/app-foo.yaml:

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: app-foo
  namespace: flux-system
spec:
  interval: 1m
  url: ssh://git@github.com/yourorg/app-foo.git
  ref:
    branch: main
  secretRef:
    name: app-foo-git-ssh
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: app-foo
  namespace: flux-system
spec:
  interval: 10m
  prune: true
  sourceRef:
    kind: GitRepository
    name: app-foo
  path: ./overlays/prod
  targetNamespace: app-foo

Add the file to the registry Kustomize list:

# clusters/prod/apps/kustomization.yaml
resources:
  - app-foo.yaml

Commit and push.


Step 5: Watch Flux Deploy the App

Flux will now:

  1. Fetch the app repository
  2. Build overlays/prod
  3. Apply the manifests into namespace app-foo
  4. Continuously reconcile changes

Observe progress with:

flux get kustomizations
flux get sources git

Updating the App

Push changes to the app repo and Flux reconciles automatically. No infra repo changes required.


Removing the App

  1. Remove app-foo.yaml from clusters/prod/apps/
  2. Commit and push

Flux will prune the app’s registry objects and stop reconciliation.


Why This Model Works

  • Clear ownership: infra owns topology, apps own manifests
  • Minimal Flux surface area: one registry entry point
  • Predictable lifecycle: Git add/remove == deploy/undeploy
  • Scales cleanly to many apps and teams

TL;DR

  • One Flux installation per cluster
  • Infra repo owns the app registry
  • App repos use base/ + overlays/ (standard Kustomize, no Flux CRDs)
  • One small registry entry in the infra repo deploys an app
  • Git add/remove in the registry == deploy/undeploy