{"id":38650414,"url":"https://github.com/jyablonski/homelab","last_synced_at":"2026-01-17T09:19:32.051Z","repository":{"id":295181496,"uuid":"988037975","full_name":"jyablonski/homelab","owner":"jyablonski","description":"Homelab Setup \u0026 Resources","archived":false,"fork":false,"pushed_at":"2025-12-21T18:10:39.000Z","size":41,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-23T07:26:02.589Z","etag":null,"topics":["helm","helmfile"],"latest_commit_sha":null,"homepage":"","language":"Makefile","has_issues":false,"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/jyablonski.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":null,"dco":null,"cla":null}},"created_at":"2025-05-22T00:57:00.000Z","updated_at":"2025-12-21T18:10:41.000Z","dependencies_parsed_at":"2025-09-14T21:15:05.716Z","dependency_job_id":"b611dafa-ca21-4ce2-9a58-010e230285c9","html_url":"https://github.com/jyablonski/homelab","commit_stats":null,"previous_names":["jyablonski/homelab"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/jyablonski/homelab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jyablonski%2Fhomelab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jyablonski%2Fhomelab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jyablonski%2Fhomelab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jyablonski%2Fhomelab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jyablonski","download_url":"https://codeload.github.com/jyablonski/homelab/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jyablonski%2Fhomelab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28505208,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T06:57:29.758Z","status":"ssl_error","status_checked_at":"2026-01-17T06:56:03.931Z","response_time":85,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["helm","helmfile"],"created_at":"2026-01-17T09:19:31.425Z","updated_at":"2026-01-17T09:19:32.029Z","avatar_url":"https://github.com/jyablonski.png","language":"Makefile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Homelab\n\n![Validate](https://github.com/jyablonski/homelab/actions/workflows/validate.yaml/badge.svg?branch=main)\n\nPersonal homelab infrastructure running on K3s with automated deployment via Helmfile.\n\n## Overview\n\nThis project provisions a single-node Kubernetes cluster with a complete observability stack, persistent storage, and home automation. Everything is declaratively managed through Helm charts with pinned versions for reproducible deployments.\n\n### What's Included\n\n| Component       | Purpose                                                 |\n| --------------- | ------------------------------------------------------- |\n| MetalLB         | Bare-metal load balancer - assigns LAN IPs to services  |\n| Traefik         | Ingress controller - routes HTTP traffic                |\n| Longhorn        | Distributed block storage - provides persistent volumes |\n| Prometheus      | Metrics collection and alerting                         |\n| Grafana         | Visualization for metrics and logs                      |\n| Loki + Promtail | Log aggregation and querying                            |\n| Headlamp        | Kubernetes dashboard UI                                 |\n| PostgreSQL      | Relational database                                     |\n| Home Assistant  | Home automation platform                                |\n| Authentik       | Identity provider / SSO (WIP)                           |\n\n## Quick Start\n\n### Prerequisites\n\n- Ubuntu/Debian-based Linux system\n- `curl`, `kubectl`, `helm`, `helmfile` installed\n- Sufficient disk space (the cluster needs ~15% free to avoid disk pressure)\n\n### Quick Start\n\n```bash\nmake up\n```\n\nThis will:\n\n1. Install K3s (with built-in Traefik disabled)\n2. Create required namespaces\n3. Deploy all services via Helmfile\n\nFor teardown:\n\n```bash\nmake down\n```\n\nThis will uninstall all services, remove persistent volumes, and uninstall K3s.\n\n### Access Services\n\nAfter deployment, services are accessible via MetalLB-assigned IPs. Check assigned IPs:\n\n```bash\nkubectl get svc -A | grep LoadBalancer\n```\n\nDefault services:\n\n| Service        | Default Port | Credentials                        |\n| -------------- | ------------ | ---------------------------------- |\n| Grafana        | 3000         | admin / admin                      |\n| Prometheus     | 9090         | -                                  |\n| Headlamp       | 8085         | [Generate token](#headlamp-access) |\n| Home Assistant | 8123         | Setup on first visit               |\n| Longhorn UI    | 30085        | -                                  |\n| PostgreSQL     | 5432         | jacob / password                   |\n\n#### Headlamp Access\n\nHeadlamp requires a service account token that has to be generated dynamically (insecure auth is not supported yet).\n\n```bash\nkubectl create token headlamp -n kube-system --duration=8760h\n```\n\nPaste the token into the Headlamp login screen. Your browser will remember it.\n\n## Project Structure\n\n```\nhomelab/\n├── helmfile.yaml              # Main deployment manifest - all releases with pinned versions\n├── Makefile                   # Cluster lifecycle commands (up/down)\n├── scripts/\n│   └── setup.sh               # Post-install setup script\n└── services/\n    ├── authentik/\n    │   └── values.yaml\n    ├── loki/\n    │   └── values.yaml\n    ├── longhorn/\n    │   └── values.yaml\n    ├── prometheus/\n    │   └── values.yaml        # Includes Grafana config\n    ├── etc...                 # Other service charts and values\n```\n\n## How It Works\n\n### Networking\n\n```\nInternet/LAN Request\n        ↓\n    MetalLB (assigns external IP from pool, e.g., 192.168.76.240-250)\n        ↓\n    Service (LoadBalancer type)\n        ↓\n    Pod\n```\n\nMetalLB assigns IPs from a configured pool to `LoadBalancer` services. Each service gets a dedicated IP accessible from your LAN.\n\n### Storage\n\nLonghorn provides persistent volumes backed by local disk. Volumes are stored at `/var/lib/longhorn/` and managed through Kubernetes PVCs.\n\nFor single-node clusters, replica count is set to 1 (no redundancy). Data persists across pod restarts but not node failures.\n\n### Observability\n\n```\nPods write to stdout/stderr\n        ↓\nContainer runtime writes to /var/log/pods/\n        ↓\nPromtail (DaemonSet) tails logs, adds labels\n        ↓\nLoki stores and indexes logs\n        ↓\nGrafana queries both Prometheus (metrics) and Loki (logs)\n```\n\n- Prometheus scrapes metrics from pods, nodes, and Kubernetes components\n- Promtail collects logs from all pods on each node\n- Loki stores logs with 7-day retention\n- Grafana provides dashboards for node metrics as well as logs exploration\n\n### Chart Version Pinning\n\nAll Helm charts are pinned to specific versions in `helmfile.yaml` for reproducible deployments. To upgrade a chart:\n\n1. Check available versions: `helm search repo \u003cchart\u003e --versions`\n2. Update the `version:` field in `helmfile.yaml`\n3. Run `helmfile sync`\n\n## Future State\n\n### Pi-hole\n\nLocal DNS resolution to enable services to be accessed via hostnames instead of IPs or port numbers. Example:\n\n- `http://grafana.home`\n- `http://homeassistant.home`\n\n### Multi-Node Cluster\n\nExpand to 3+ nodes for high availability:\n\n- Longhorn replication across nodes (bump `defaultReplicaCount` to 3)\n- Pod scheduling across nodes for redundancy\n- Proper ingress with DNS-based routing via Traefik\n\n### Authentik SSO\n\nCentralized authentication for all services:\n\n- OIDC integration with Grafana, Headlamp, etc.\n- Single sign-on across the homelab\n- User management and access control\n\n### Ingress + DNS\n\nReplace direct LoadBalancer IPs with hostname-based routing:\n\n- Local DNS (Pi-hole or router) pointing `*.home.local` to Traefik IP\n- Traefik ingress rules routing by hostname\n- Optional: TLS with self-signed certs or Let's Encrypt\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjyablonski%2Fhomelab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjyablonski%2Fhomelab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjyablonski%2Fhomelab/lists"}