home-ops keeps a home Kubernetes cluster in Git and lets Flux apply it
My home or for-home infrastructure written as code, adhering to GitOps practices. Mirror of https://git.bjw-s.dev/bjw-s/home-ops
At a glance
- What is it?
- bjw-s-labs home-ops is a monorepo for a home Kubernetes cluster, written as Infrastructure as Code and reconciled by Flux, with Renovate proposing dependency updates and GitHub Actions doing the work. It is a personal infrastructure repository published in full, which makes it a reference implementation rather than a product, and the interesting parts are the tooling files that keep hundreds of YAML manifests consistent.
- Who is it for?
- home-ops fits a self-hoster who wants a Kubernetes cluster described entirely in Git, who is comfortable with Flux and Talos, and who wants a working example of the supporting tooling rather than just the manifests. Skip it if you are starting from a single node with a handful of services, since a GitOps cluster has a real operating cost, or if your environment does not allow Talos.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly YAML, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One repository describing the whole home cluster
The README opens with a single line that sets the scope, and it is a statement of intent rather than a feature list.
So the subject is a home cluster, and the claim is about the method rather than about a set of applications. The tools named are the conventional GitOps set, with Flux as the reconciler, Renovate for dependency updates, and GitHub Actions for the automation around them, plus Ansible and Terraform for the parts that live outside the cluster.
The repository is a mirror, and the project description says so in as many words.
So the canonical history lives on the author's own Git forge, with GitHub as the published copy. That arrangement is common for people who want their infrastructure source to sit on infrastructure they control, and it also means the GitHub repository is a read-mostly artefact for most followers.
The top-level entries show how the three domains are separated, with `ansible/`, `docker/` and `kubernetes/` directories, and the primary language of the repository is recorded as YAML, which is consistent with a cluster defined by manifests rather than by code.
Flux turns a pull request into a cluster change
The GitOps part is the part that makes the repository more than a backup of configuration.
In a Flux setup, the cluster holds a reference to a Git repository and reconciles the manifests it finds there. The result is that a change to the cluster is a pull request, and the deployment is the merge. There is no imperative step where somebody runs a command against a live cluster, and there is no per-cluster configuration that lives only on a node.
That model has a specific consequence for a home setup, and it is the reason the repository exists rather than a set of scripts. The cluster is disposable in the sense that its desired state is not stored on the cluster at all, so rebuilding a node, replacing a disk or standing up a second cluster is a matter of pointing Flux at the same repository.
The repository carries a `kubernetes/` directory, which is where the cluster definitions live, and the badges at the top of the README show the shape of the running system: a Talos version badge, a Kubernetes version badge, a Flux version badge, and then a set of live cluster statistics.
The cluster statistics are the interesting part. They come from the `home-operations/kromgo` project, and the badges cover the cluster age in days, the node count, the alert count, the pod count, and CPU and memory usage. Rendering live cluster state inside the README turns the repository into a status page, so the front page of a fork shows whether the author's cluster is healthy without anyone visiting a monitoring service.
Renovate handles the update flow that GitOps makes unavoidable
Once the cluster is described in Git, the dependency update question becomes mandatory rather than optional, and this repository answers it with Renovate.
The top-level entries show the configuration in two places, a `.renovate/` directory and a `.renovaterc.json5` file, and the README carries a Renovate badge. Renovate is the tool that scans the manifests for pinned image versions and opens update pull requests, which is exactly what a Flux-managed cluster needs, since nothing upgrades itself.
The interaction with Flux is the part worth understanding. Renovate does not deploy anything. It opens a pull request, the pull request is reviewed and merged, and the merge is what Flux applies. The update path is therefore the same path as any other change, which is the property that makes the setup auditable.
There is a related detail in the tree: a dedicated `.renovate/` directory suggests the configuration is split rather than kept in one place, which is how you end up with per-directory rules, for example treating some application repositories differently from the cluster infrastructure.
For anyone adapting the repository, the Renovate configuration is the file to read first, and it is also the file most likely to need changing, because an update policy that suits one cluster rarely suits another. The rate at which update pull requests arrive, and which updates are allowed to land automatically, are decisions the repository's owner has already made and that a fork inherits.
The tooling files are the part worth copying
Most of the interesting engineering in a repository like this is not in the manifests, it is in the files that keep hundreds of YAML files consistent, and the top-level listing shows a set of them.
There is a `.minijinja.toml`, which configures MiniJinja as the templating engine, and that single file explains why the primary language of the repository is YAML rather than a template language. The manifests are templates that are rendered before Flux sees them, which is how one repository can hold the same application deployed to several clusters with different domains, storage classes or node labels.
Then there is the YAML tooling. A `.yamlfmt.yaml` for formatting, a `.yamllint.yaml` for linting, and a `.yayamlls.yaml` for the YAML language server, which is what gives editor completion and diagnostics on those files. Three separate tools for one file format is not redundancy, it is a formatting standard, a lint standard and an editor integration.
The task runner is a `.justfile`, and there is a `.mise.toml` for tool version management, so the versions of the tools themselves are pinned in the repository. The `.editorconfig` and `.vscode/` directory handle editor defaults, and `.gitattributes` handles line endings.
There is also a set of assistant instruction files, `AGENTS.md`, `CLAUDE.md` and the `.claude/`, `.codex/` and `.agents/` directories. Those are prompts and context for coding assistants, which is a new addition to infrastructure repositories and a sign of how the workflow has shifted. A `.forgejo/` directory sits alongside the GitHub Actions workflows, which is consistent with the mirror arrangement, since the canonical repository lives on the author's own forge and the automation needs to run there.
A published personal cluster, and what a fork inherits
The value of this repository is that it is a working system rather than a template, and the cost of that is that a fork inherits decisions rather than a design.
The first decision is the node operating system. The Talos version badge in the README indicates that the cluster runs on Talos Linux, which is an immutable, API-driven operating system built for Kubernetes. That choice is convenient in a GitOps setup, because the node configuration is declarative and a node can be rebuilt from a declarative spec, but it also means the cluster assumes a Linux distribution that most homelab guides do not use, and a fork that wants plain Debian or Ubuntu nodes has real work to do.
The second is scale. The node count, pod count and usage badges suggest a cluster with several nodes and a meaningful workload, which is the regime where GitOps pays for itself. The same setup for a single node with a dozen services is a lot of machinery for the job.
The third is the secret and endpoint configuration, which is the part that never appears in a public infrastructure repository. Whatever this repository does with sensitive values, a fork has to replace with its own, and that is a deliberate piece of work rather than a copy and paste.
The repository also points at the surrounding community rather than standing alone. The README credits the Home Operations Discord, mentions the `k8s-at-home` topic on GitHub as a source of inspiration for other people's clusters, and links to Kubesearch as a tool for finding things to deploy. The badges come from the `home-operations/kromgo` project, and the Discord is the place where the designs get discussed.
An Apache licensed reference cluster, still moving
The maintenance picture is clear and the project is busy.
The repository is not archived, and the last push was recent, with the repository receiving commits the day before. The licence is Apache-2.0, with the terms in the `LICENSE` file, and the README links to it directly.
See [LICENSE](https://github.com/bjw-s-labs/home-ops/blob/main/LICENSE)That licence choice matters more here than it would for a library, because the thing being licensed is an infrastructure design. A home cluster repository is the kind of artefact people copy wholesale, and Apache-2.0 allows that with attribution and with patent terms, which is a better fit for a reference deployment than a copyleft licence would be.
There are no GitHub releases, which is consistent with the GitOps model rather than a sign of neglect. The history is the log, the versions are image tags and Renovate pull requests, and the upgrade path is the merge of an update pull request. A release tarball would not tell a reader anything useful here.
The topics give the same picture: Flux, GitOps, infrastructure as code, Kubernetes, Renovate and the `k8s-at-home` tag, which is the community label for exactly this kind of repository. The project is one entry in a genre, and its distinguishing feature is that it is published in full, with the cluster's own status badges on the front page, so a reader can see the design and the running result at the same time.
Editorial conclusion
home-ops fits a self-hoster who wants a Kubernetes cluster described entirely in Git, who is comfortable with Flux and Talos, and who wants a working example of the supporting tooling rather than just the manifests. Skip it if you are starting from a single node with a handful of services, since a GitOps cluster has a real operating cost, or if your environment does not allow Talos. Verify first that the cluster and secret handling in the fork matches your own, that the Renovate configuration in the repository suits your update policy, and that the templating pipeline in the .minijinja.toml setup produces the manifests you expect before you push anything to a cluster you care about.
Frequently asked questions
What is the home-ops repository?
It is a monorepo for one person's home infrastructure and Kubernetes cluster, written as Infrastructure as Code and reconciled with Flux, using Ansible, Terraform, Kubernetes, Renovate and GitHub Actions. The GitHub copy is a mirror of the canonical repository at git.bjw-s.dev.
How does Flux apply changes in home-ops?
The cluster reconciles the manifests in the `kubernetes/` directory of the repository, so a change reaches the cluster through a merged pull request rather than through a command run against a live node. The README badges show the running Talos, Kubernetes and Flux versions along with live cluster statistics.
What do the YAML tooling files in home-ops do?
The repository carries `.yamlfmt.yaml` for formatting, `.yamllint.yaml` for linting and `.yayamlls.yaml` for the YAML language server, plus a `.minijinja.toml` that configures MiniJinja as the templating engine used to render the manifests. A `.justfile` provides the task runner and `.mise.toml` pins tool versions.
What role does Renovate play in home-ops?
Renovate scans the manifests for pinned versions and opens update pull requests, which are then merged like any other change and applied by Flux. The configuration lives in a `.renovate/` directory and a `.renovaterc.json5` file at the top level, and the README carries a Renovate badge.
What licence does home-ops use?
Apache-2.0, with the licence text in the `LICENSE` file at the top level, which permits reuse of the cluster design in other people's infrastructure repositories with attribution.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/bjw-s-labs-home-ops)Was this useful?