Skip to main content
The Four-Repo GitOps Structure for My Homelab Platform

The Four-Repo GitOps Structure for My Homelab Platform

·6 mins·
Andrei Vasiliu
Author
Andrei Vasiliu
Romanian expat in Italy. Platform Engineer by trade, homelab builder by passion. Documenting every step of building enterprise-grade infrastructure at home.
Table of Contents

The Journey So Far
#

In this series, we’ve built a powerful foundation for a homelab Kubernetes platform. We started by installing Talos Omni to get a centralized management plane. Then, we walked the “scenic route” by manually provisioning a cluster to understand the nuts and bolts. Finally, we achieved true velocity by automating cluster creation, turning our Kubernetes infrastructure into a disposable, on-demand resource.

Now, with the ability to create clusters in minutes, we face the next enterprise-grade challenge: How do we manage the applications and platform services running on it?

It’s not enough to just have a cluster; we need a structured, scalable, and maintainable way to deploy and configure everything from the service mesh to the applications themselves. This is where we move from simply running Kubernetes to building a true platform.

This post outlines my GitOps architecture, which is based on a four-repository model. This structure provides a clear separation of concerns and establishes a robust workflow for managing the entire software lifecycle on my homelab cluster.

Why Not Just One Big Repository?
#

When starting with GitOps, the simplest approach is often a single repository containing everything: your ArgoCD manifests, your platform tools (like Istio or cert-manager), and all your application configurations. This works well for a small number of services, but as I’ve learned from managing production environments with hundreds of microservices across multiple clusters, it quickly becomes unwieldy.

A single-repo approach leads to several problems:

  • Blurred Ownership: Who is responsible for what? Platform engineers and application developers all commit to the same repository, increasing the risk of conflicting changes.
  • Configuration Drift: It becomes difficult to manage environment-specific configurations cleanly. You often end up with complex Kustomize overlays or Helm value files that are hard to read.
  • Promotion Path Complexity: Promoting an application from a development to a production environment can be a messy process of copying files or cherry-picking commits.
  • Blast Radius: A mistake in one part of the repository (e.g., a platform tool configuration) can potentially break application deployments, and vice-versa.

To avoid these pitfalls, I’ve adopted a multi-repository strategy that separates concerns, mirroring the way we manage complex systems in production.

The Four Pillars of My GitOps Platform
#

My architecture is composed of four interconnected GitHub repositories, each with a distinct purpose. ArgoCD watches these repositories and uses them to assemble the complete desired state of the cluster.

diagram

Let’s break down the role of each one.

1. homelab-k8s-argo-config: The Platform Foundation
#

This repository is the source of truth for the platform itself. It contains the ArgoCD configurations for all the foundational services that my applications will depend on. Think of it as the layer managed by the “platform team” (in this case, me).

Purpose:

  • Defines and configures core infrastructure components like Istio (service mesh), cert-manager (certificate management), external-dns (DNS automation), and external-secrets (secret synchronization).
  • Contains ArgoCD AppProject definitions to enforce security and organization.
  • Manages the namespaces and RBAC policies for the entire cluster.

This repository establishes the stable base upon which all applications will run.

2. homelab-k8s-base-manifests: The Blueprint Factory
#

This repository holds the reusable deployment templates. To ensure consistency, I don’t want to write Kubernetes manifests from scratch for every application. Instead, I use standardized Helm charts that define common deployment patterns.

Purpose:

  • Provides a library of production-ready Helm charts.
  • Includes a common chart that can be used to deploy most stateless web applications and APIs with a standard set of features (Deployments, Services, Ingresses, etc.).
  • Allows for application-specific charts for services with unique requirements.

By using these base charts, I ensure that every application is deployed in a consistent and predictable way.

3. homelab-k8s-environments: The High-Velocity Configuration Registry
#

This repository is different from the others; it’s a high-frequency repository that is often updated automatically by CI/CD pipelines. It has a critical job: it tracks not only which version of each application is deployed in each environment (which are separate Kubernetes clusters), but also stores other configuration artifacts generated during the build process.

Purpose:

  • Acts as a central registry for application versions (e.g., Docker image tags).
  • Stores pipeline-generated data. For example, if an application uses gRPC and Istio is configured to translate incoming REST calls, the pipeline can generate and store a protoDescriptorBin file here for Istio to consume.
  • The dev configuration is updated automatically by a CI/CD pipeline, enabling continuous delivery to my development cluster.
  • The prod configuration is updated manually via pull requests, creating a controlled promotion process for the production cluster.

This repository acts as the dynamic bridge between my CI/CD system and my GitOps state, allowing for automated, pipeline-driven configuration to be safely consumed by ArgoCD.

4. homelab-k8s-environments-apps: The Configuration Hub
#

This is the repository that ties everything together. It contains the ArgoCD Application manifests that tell ArgoCD how to build and deploy each application.

Purpose:

  • Contains an ArgoCD Application definition for every service.
  • Specifies which Helm chart to use from homelab-k8s-base-manifests.
  • Provides the environment-specific Helm values.yaml files (e.g., resource limits, replica counts, environment variables).
  • References the homelab-k8s-environments repository to get the correct application version.

This repository effectively combines the “what” (the Helm chart), the “which version” (the image tag), and the “how” (the configuration values) to create a complete application deployment.

Explore the Repositories
#

More details on each repository’s planned structure can be found on my GitHub. Currently, they contain detailed READMEs outlining their purpose, but they will evolve step-by-step as the homelab is built. Everything will be public: the pipelines, the processes, the applications I deploy, and the configurations that bind them together.

The Deployment Flow in Action
#

This structure creates a clear and auditable workflow for making changes.

Scenario 1: A New Application Version Deploys to DEV
#

  1. A developer pushes a code change, and the CI pipeline builds a new Docker image (v1.2.4).
  2. The CI pipeline automatically commits a change to the homelab-k8s-environments repository, updating the version for that application in the dev environment to v1.2.4.
  3. ArgoCD detects this change and automatically syncs the application, pulling the new Docker image into the development cluster.

Scenario 2: Promoting an Application to Production
#

  1. After testing in dev, the v1.2.4 version is deemed stable and ready for production.
  2. A developer opens a pull request against the homelab-k8s-environments repository to change the version for the application in the prod configuration to v1.2.4.
  3. The pull request is reviewed, approved, and merged.
  4. ArgoCD detects the change in the prod configuration and syncs the application, rolling out the new version to the production cluster.

Conclusion: An Enterprise Pattern for the Homelab
#

This four-repository structure brings a level of organization and control that I have validated in production environments managing hundreds of microservices across multiple clusters. It provides:

  • Clear Separation of Concerns: The platform, application blueprints, versions, and configurations are all managed independently.
  • Scalability: Adding new applications or environments is a structured process, not an ad-hoc task.
  • Auditable and Controlled Promotions: The Git history provides a clear record of every change, and promotions to production are managed through pull requests.

Now that the blueprint for the platform is defined, the next step is to bring it to life. In the upcoming posts, I’ll start implementing this structure, beginning with the homelab-k8s-argo-config repository to lay down the foundational services for my new Kubernetes platform.

Stay tuned. Andrei