{"id":35142123,"url":"https://github.com/nsudhanva/homelab","last_synced_at":"2026-05-01T05:31:45.229Z","repository":{"id":329769997,"uuid":"1120602571","full_name":"nsudhanva/homelab","owner":"nsudhanva","description":"@nsudhanva and @maanasanarayan personal bare metal Kubernetes homelab setup. Uses Ubuntu 24.04 with bare metal Kubernetes, ArgoCD for GitOps, Tailscale Kubernetes Operator and more!","archived":false,"fork":false,"pushed_at":"2025-12-22T15:28:42.000Z","size":95,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-12-23T06:03:02.483Z","etag":null,"topics":["ansible","argocd","gitops","homelab","kubernetes","longhorn"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nsudhanva.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-21T15:08:07.000Z","updated_at":"2025-12-22T15:40:10.000Z","dependencies_parsed_at":"2025-12-23T06:03:07.905Z","dependency_job_id":null,"html_url":"https://github.com/nsudhanva/homelab","commit_stats":null,"previous_names":["nsudhanva/homelab"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/nsudhanva/homelab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsudhanva%2Fhomelab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsudhanva%2Fhomelab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsudhanva%2Fhomelab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsudhanva%2Fhomelab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nsudhanva","download_url":"https://codeload.github.com/nsudhanva/homelab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nsudhanva%2Fhomelab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28099620,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-28T02:00:05.685Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansible","argocd","gitops","homelab","kubernetes","longhorn"],"created_at":"2025-12-28T12:03:04.414Z","updated_at":"2026-05-01T05:31:45.215Z","avatar_url":"https://github.com/nsudhanva.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Homelab\n\nA self-hosted bare-metal Kubernetes cluster on Ubuntu 24.04 LTS.\n\n- Uses Ansible for automated node provisioning with ArgoCD for GitOps-based cluster management\n- Traffic flows through Tailscale for secure ingress and Envoy Gateway for routing, with Vault and External Secrets handling credentials\n- Longhorn provides distributed storage with basic backup capabilities\n- A local rehearsal workflow using Multipass VMs allows validating changes before deploying to hardware\n- Additional cloud providers can follow the same pattern but are not documented yet\n\n## Table of contents\n\n- [Features](#features)\n- [Architecture](#architecture)\n  - [Core systems map](#core-systems-map)\n  - [Platform services map](#platform-services-map)\n  - [Network topology](#network-topology)\n- [Quick start](#quick-start)\n  - [Bare metal bring-up](#bare-metal-bring-up)\n  - [From scratch flow](#from-scratch-flow)\n  - [Local rehearsal](#local-rehearsal)\n- [Documentation](#documentation)\n- [Repository layout](#repository-layout)\n- [Applications](#applications)\n- [GitOps model](#gitops-model)\n- [Operations](#operations)\n- [Conventions](#conventions)\n- [Monitoring topology](#monitoring-topology)\n- [Maintainers](#maintainers)\n\n## Features\n\n- Multi-node bare-metal Kubernetes with kubeadm and Cilium\n- GitOps-managed infrastructure and apps via ArgoCD ApplicationSets\n- Tailscale Gateway API ingress with split-horizon DNS\n- Vault + External Secrets for centralized secret management\n- Longhorn storage, Prometheus monitoring, and optional GPU plugins\n- Automated image updates with ArgoCD Image Updater\n- Metrics Server for resource usage in Headlamp\n- ExternalDNS automation for Gateway API routes\n- Envoy Gateway data plane for Gateway API\n- Kubescape operator for cluster security scanning\n\n## Architecture\n\n### Core systems map\n\n```mermaid\nflowchart LR\n  subgraph Repo[\"Homelab Git repo\"]\n    Ansible[\"ansible/\"]\n    Bootstrap[\"bootstrap/\"]\n    Infra[\"infrastructure/\"]\n    Apps[\"apps/\"]\n  end\n\n  subgraph Nodes[\"Ubuntu 24.04 nodes\"]\n    Prep[\"Ansible provisioning\"]\n    Kubeadm[\"kubeadm init/join\"]\n  end\n\n  subgraph Cluster[\"Kubernetes cluster\"]\n    Argo[\"ArgoCD + ApplicationSets\"]\n    Workloads[\"Infra + apps\"]\n  end\n\n  Ansible --\u003e Prep\n  Prep --\u003e Kubeadm\n  Kubeadm --\u003e Argo\n  Bootstrap --\u003e Argo\n  Infra --\u003e Argo\n  Apps --\u003e Argo\n  Argo --\u003e Workloads\n```\n\n### Platform services map\n\n```mermaid\nflowchart TB\n  subgraph Edge[\"Edge \u0026 ingress\"]\n    Tailscale[\"Tailscale Gateway API\"]\n    Envoy[\"Envoy Gateway\"]\n    DNS[\"ExternalDNS + split-horizon CoreDNS\"]\n  end\n\n  subgraph Platform[\"Platform services\"]\n    Vault[\"Vault\"]\n    ESO[\"External Secrets\"]\n    Longhorn[\"Longhorn\"]\n    Metrics[\"Prometheus + Grafana\"]\n  end\n\n  subgraph Apps[\"User apps\"]\n    Headlamp[\"Headlamp\"]\n    Docs[\"Docs\"]\n    Homer[\"Homer\"]\n    Media[\"Jellyfin + Filebrowser\"]\n  end\n\n  Tailscale --\u003e Envoy\n  DNS --\u003e Envoy\n  Envoy --\u003e Apps\n  Vault --\u003e ESO\n  ESO --\u003e Apps\n  Longhorn --\u003e Apps\n  Metrics --\u003e Apps\n```\n\n### Network topology\n\n```mermaid\nflowchart LR\n  Public[\"Public DNS\"]\n  Tailnet[\"Tailscale tailnet\"]\n  ExternalDNS[\"ExternalDNS\"]\n  Gateway[\"Tailscale Gateway API\"]\n  Envoy[\"Envoy Gateway\"]\n  Routes[\"HTTPRoutes\"]\n  Services[\"Cluster Services\"]\n  CoreDNS[\"CoreDNS rewrite\"]\n\n  ExternalDNS --\u003e Public\n  Public --\u003e Gateway\n  Tailnet --\u003e Gateway\n  Gateway --\u003e Envoy\n  Envoy --\u003e Routes\n  Routes --\u003e Services\n  CoreDNS --\u003e Services\n```\n\n## Quick start\n\nBare metal is the primary target. The local VM flow exists to rehearse changes before touching hardware.\n\n### Bare metal bring-up\n\nProvision nodes, bootstrap Kubernetes, then hand off to ArgoCD.\n\n```bash\nnano ansible/inventory/hosts.yaml\nansible-playbook -i ansible/inventory/hosts.yaml ansible/playbooks/provision-cpu.yaml\n\nsudo kubeadm init --pod-network-cidr=10.244.0.0/16\nmkdir -p $HOME/.kube\nsudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config\nsudo chown $(id -u):$(id -g) $HOME/.kube/config\nkubectl taint nodes --all node-role.kubernetes.io/control-plane-\n\nCILIUM_VERSION=$(grep -E \"cilium_version:\" ansible/group_vars/all.yaml | head -n 1 | awk -F'\"' '{print $2}')\ncilium install --version \"$CILIUM_VERSION\" --values infrastructure/cilium/values.cilium\n\nkubectl apply -k bootstrap/argocd\nkubectl wait --for=condition=available --timeout=600s deployment/argocd-server -n argocd\nkubectl apply -f bootstrap/root.yaml\n```\n\nGuided flow: \u003chttps://docs.sudhanva.me/how-to/from-scratch\u003e and \u003chttps://docs.sudhanva.me/tutorials\u003e\n\n### From scratch flow\n\n```mermaid\nflowchart TB\n  subgraph Workstation[\"Workstation\"]\n    Inventory[\"ansible/inventory/hosts.yaml\"]\n    Vars[\"ansible/group_vars/all.yaml\"]\n    Playbooks[\"ansible/playbooks/*\"]\n  end\n\n  subgraph Nodes[\"Ubuntu 24.04 nodes\"]\n    OS[\"OS baseline + containerd\"]\n    Kubelet[\"kubelet + kubeadm\"]\n  end\n\n  subgraph ControlPlane[\"Control plane\"]\n    Init[\"kubeadm init\"]\n    Kubeconfig[\"/etc/kubernetes/admin.conf\"]\n    CNI[\"Cilium install\"]\n    Argo[\"ArgoCD bootstrap\"]\n  end\n\n  subgraph GitOps[\"GitOps reconciliation\"]\n    AppSets[\"ApplicationSets\"]\n    InfraApps[\"infra-* apps\"]\n    UserApps[\"app-* apps\"]\n  end\n\n  Inventory --\u003e Playbooks\n  Vars --\u003e Playbooks\n  Playbooks --\u003e OS\n  OS --\u003e Kubelet\n  Kubelet --\u003e Init\n  Init --\u003e Kubeconfig\n  Kubeconfig --\u003e CNI\n  CNI --\u003e Argo\n  Argo --\u003e AppSets\n  AppSets --\u003e InfraApps\n  AppSets --\u003e UserApps\n```\n\n### Local rehearsal\n\nUse Multipass to validate the full flow on your workstation.\n\n```bash\n./scripts/local-cluster.sh up\n```\n\nLow-resource rehearsal:\n\n```bash\nWORKER_COUNT=0 VM_CPUS=2 VM_MEMORY=3G VM_DISK=12G CILIUM_HUBBLE_ENABLED=false ./scripts/local-cluster.sh up\n```\n\nTear down:\n\n```bash\n./scripts/local-cluster.sh down\n```\n\n## Documentation\n\nDocs site: \u003chttps://docs.sudhanva.me\u003e\n\nBuild locally:\n\n```bash\ncd docs\nbun install\nbun dev\n```\n\nRecommended reading paths:\n\n- Start from scratch: \u003chttps://docs.sudhanva.me/how-to/from-scratch\u003e\n- Add a worker node: \u003chttps://docs.sudhanva.me/how-to/add-worker-node\u003e\n- Prereqs and system prep: \u003chttps://docs.sudhanva.me/tutorials/prerequisites\u003e\n- GitOps model: \u003chttps://docs.sudhanva.me/explanation/automation-model\u003e\n- Infra catalog: \u003chttps://docs.sudhanva.me/reference/infrastructure-components\u003e\n- App catalog: \u003chttps://docs.sudhanva.me/reference/applications\u003e\n\n## Repository layout\n\n```bash\nansible/          Node provisioning\nbootstrap/        ArgoCD bootstrap and ApplicationSets\ninfrastructure/   Cluster components managed by ArgoCD\napps/             User workloads managed by ArgoCD\nclusters/         Cluster-specific overrides\nscripts/          Automation helpers\ndocs/             Astro Starlight documentation\n```\n\n## Applications\n\n| App | Purpose | Hostname |\n| --- | --- | --- |\n| Docs | Documentation site for cluster guides | `docs.sudhanva.me` |\n| Headlamp | Kubernetes UI with OIDC support and metrics integration | `headlamp.sudhanva.me` |\n| Homer | Home dashboard with service shortcuts | `home.sudhanva.me` |\n| Jellyfin | Media streaming with GPU acceleration when available | `jellyfin.sudhanva.me` |\n| Filebrowser | File manager for the media volume | `filebrowser.sudhanva.me` |\n| ArgoCD | GitOps control plane UI | `argocd.sudhanva.me` |\n| Longhorn | Storage UI | `longhorn.sudhanva.me` |\n| Vault | Secrets UI | `vault.sudhanva.me` |\n| Hubble UI | Cilium network visibility | `hubble.sudhanva.me` |\n| Grafana | Metrics dashboards | `grafana.sudhanva.me` |\n| Prometheus | Metrics queries | `prometheus.sudhanva.me` |\n| Alertmanager | Alerting UI | `alertmanager.sudhanva.me` |\n\n## GitOps model\n\nArgoCD reconciles everything under `infrastructure/` and `apps/` using ApplicationSets. Manual `kubectl apply` is discouraged after bootstrap.\n\nAdding apps:\n\n- Create `apps/\u003capp\u003e/app.yaml` to define the ArgoCD app name/path/namespace\n- Add Kubernetes manifests in the same folder\n- Add `kustomization.yaml` if you want Image Updater to write overrides\n\nImage updates:\n\n- ArgoCD Image Updater writes `.argocd-source-\u003capp\u003e.yaml` files into app folders\n- These files are not Kubernetes resources and are ignored by kubeconform\n\n## Operations\n\nRoutine checks:\n\n```bash\nkubectl get nodes\nkubectl get pods -A\nkubectl get apps -n argocd\n```\n\nBefore pushing:\n\n```bash\npre-commit run --all-files\n```\n\n## Conventions\n\n- ApplicationSets generate `infra-*` and `app-*` ArgoCD applications from folders\n- App folders use `app.yaml` for app metadata and manifests in the same directory\n- `kustomization.yaml` enables Image Updater overrides per app\n- Image updates write `.argocd-source-\u003capp\u003e.yaml` files into app folders\n\n## Monitoring topology\n\n```mermaid\nflowchart TB\n  subgraph CRDs[\"Prometheus Operator CRDs\"]\n    CRD[\"monitoring.coreos.com/*\"]\n  end\n\n  subgraph Stack[\"Monitoring stack\"]\n    Prometheus[\"Prometheus\"]\n    Alertmanager[\"Alertmanager\"]\n    Grafana[\"Grafana\"]\n  end\n\n  subgraph Sources[\"Metrics sources\"]\n    ServiceMonitors[\"ServiceMonitors\"]\n    NodeExporter[\"node-exporter\"]\n    KSM[\"kube-state-metrics\"]\n    Apps[\"App metrics\"]\n  end\n\n  CRD --\u003e Prometheus\n  CRD --\u003e Alertmanager\n  CRD --\u003e Grafana\n  ServiceMonitors --\u003e Prometheus\n  NodeExporter --\u003e Prometheus\n  KSM --\u003e Prometheus\n  Apps --\u003e ServiceMonitors\n  Prometheus --\u003e Alertmanager\n  Prometheus --\u003e Grafana\n```\n\n## Maintainers\n\n- [Sudhanva Narayana](https://sudhanva.me)\n- [Maanasa Narayan](https://maanasanarayan.github.io)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnsudhanva%2Fhomelab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnsudhanva%2Fhomelab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnsudhanva%2Fhomelab/lists"}