Step 5: Bootstrap GitHub GitOps and encrypted secrets
This step should take approximately 30 to 40 minutes.
Overview
Flux changes the deployment flow from "run this command against the cluster" to "review and merge this desired state." SOPS lets the same repository contain encrypted secret values without treating base64 as protection.
Practice the skill
-
Create a private GitHub repository named
homelab-gitops, clone it locally, and create the directory structure from Step 4. Protectmainwith pull-request review if you use the repository with others. -
Generate an age key on your secure workstation and store a recovery copy outside the cluster.
age-keygen -o age.agekey age-keygen -y age.agekeyThe private key is never committed. Put its public recipient in
.sops.yamland encrypt only KubernetesdataandstringDatafields. -
Create the Flux decryption secret and bootstrap Flux to GitHub. Follow the current Flux GitHub bootstrap instructions for your authentication method.
kubectl -n flux-system create secret generic sops-age \ --from-file=age.agekey=./age.agekey flux bootstrap github \ --owner=EXAMPLE \ --repository=homelab-gitops \ --branch=main \ --path=clusters/home -
Add a
Kustomizationthat enables SOPS decryption and reconciles infrastructure before services.spec: interval: 10m path: ./clusters/home/infrastructure prune: true decryption: provider: sops secretRef: name: sops-age -
Prove the workflow with an encrypted example Secret and harmless ConfigMap. Commit, push, and watch Flux reconcile.
flux get kustomizations flux get helmreleases -A -
Establish the image workflow for your own software: GitHub Actions builds a digest-addressed image, updates the GitOps repository in a pull request, and Flux applies the merged digest. Third-party charts are version pinned and upgraded in dedicated pull requests.
What you learned
- Git is the audit trail and recovery source for cluster configuration.
- The age private key is a recovery asset; lose it and encrypted Git secrets cannot be read.
- Image tags are mutable; deploy immutable digests for software you build.
Continue learning
Continue to Step 6: Expose only public applications through Cloudflare.
Step 4: Add local storage placement and LAN ingress
Reserve one node for durable single-instance services, install MetalLB, and establish an internal-only Traefik entry point.
Step 6: Expose only public applications through Cloudflare
Use Cloudflare Tunnel and a separate public ingress class while preserving a LAN-only route for internal services.