{"id":50318392,"url":"https://github.com/dhvcc/homelab","last_synced_at":"2026-05-29T01:32:45.186Z","repository":{"id":349601373,"uuid":"1107689519","full_name":"dhvcc/homelab","owner":"dhvcc","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-14T15:03:51.000Z","size":71,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-14T17:10:27.632Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Jinja","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/dhvcc.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-12-01T13:35:55.000Z","updated_at":"2026-05-14T15:03:56.000Z","dependencies_parsed_at":"2026-05-14T17:03:44.426Z","dependency_job_id":null,"html_url":"https://github.com/dhvcc/homelab","commit_stats":null,"previous_names":["dhvcc/homelab"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dhvcc/homelab","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhvcc%2Fhomelab","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhvcc%2Fhomelab/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhvcc%2Fhomelab/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhvcc%2Fhomelab/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dhvcc","download_url":"https://codeload.github.com/dhvcc/homelab/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dhvcc%2Fhomelab/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33633468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"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":[],"created_at":"2026-05-29T01:32:44.995Z","updated_at":"2026-05-29T01:32:45.173Z","avatar_url":"https://github.com/dhvcc.png","language":"Jinja","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Homelab\n\nHA k3s cluster on NixOS, bootstrapped with Ansible and reconciled with ArgoCD.\n\n## Notes\n\n- Currently all nodes are master+worker\n- Longhorn config relies on having at least 2 replicas (\u003e=2 nodes)\n- Logs Drilldown plugin is downloaded straight from GH Releases, skipping any of the grafana cloud stuff\n- Nixos-init uses the whole disk, formatting and installing on it\n\n## TODO\n- [ ] Fix loki-canary drop rules\n- [ ] TF For CF\n- [ ] Better support for custom dashboards\n- [ ] Better way of declaring plugin GH links for Grafana\n- [x] Home Assistant + IoT network bridge\n\n\n## Stack\n\n- **NixOS** - declarative OS configuration\n- **k3s** - lightweight Kubernetes\n- **ArgoCD** - GitOps reconciliation for cluster apps\n- **Cloudflare Tunnels** - zero-trust SSH and ingress access\n- **Longhorn** - distributed block storage\n- **kube-prometheus-stack** - Prometheus, Grafana, Alertmanager, node-exporter\n- **Loki + Promtail** - log aggregation\n\n## Setup\n\n### 1. Configure Inventory\n\n```bash\ncd ansible/inventory\ncp hosts.yml.example hosts.yml\ncp group_vars/all.yml.example group_vars/all.yml\n```\n\nEdit `hosts.yml` with node IPs and Cloudflare SSH tunnel tokens.  \nEdit `group_vars/all.yml` with `k3s_token`, `cloudflare_ingress_tunnel_token`, and any optional ArgoCD repo overrides.\n\nFor each control-plane node in `hosts.yml`:\n- `ansible_host` is only for operator access and SSH. It can be a Cloudflare/public hostname.\n- `k3s_address` is the node's control-plane/peer address used by k3s. Use a LAN IP or internal DNS name, not a public Cloudflare hostname.\n- `k3s_join_address` is optional. When set, non-seed nodes join that LAN/internal k3s endpoint instead of the seed node's `k3s_address`.\n\n### 2. Install NixOS\n\nPer node:\n1. Boot NixOS minimal ISO\n2. Set password: `passwd nixos`\n3. Run: `ansible-playbook playbooks/nixos-init.yml -i inventory/hosts.yml --limit \u003cnode\u003e`\n4. Remove USB and reboot\n5. Change password from default \"changeme\" set by the config\n\nFirst node in `k8s_control_plane` is the cluster seed.\nBy default, other control-plane nodes join that seed via its `k3s_address`.\n\n### 3. Bootstrap ArgoCD\n\n```bash\ncd ansible\n\nansible-playbook playbooks/install-argocd.yml -i inventory/hosts.yml\n```\n\nThis installs ArgoCD, applies the upstream `AppProject` and root `Application`, and bootstraps the rest of the stack from Git. After this point, update Kubernetes apps by changing manifests or values in Git and letting ArgoCD sync them.\n\nIf you want ArgoCD to track a private repo instead of upstream defaults, set `argocd_repo_url`, `argocd_target_revision`, and optional repo credentials in `group_vars/all.yml` before running the playbook.\n\n### 4. Operate Apps with GitOps\n\n- Edit values under `k8s/helm/\u003capp\u003e/values.yaml` or manifests under `k8s/`.\n- Commit and push those changes to the repo ArgoCD is tracking.\n- Let ArgoCD reconcile the cluster; no Ansible run is needed for app updates.\n\nUpstream ships fully usable ArgoCD applications pointing at this repo by default. A private repo can layer on top by patching `repoURL` and `targetRevision` to follow itself instead.\n\n### Optional: Longhorn R2 Backups\n\nFor declarative Longhorn backups:\n```bash\n# 1. Configure r2_* variables in ansible/inventory/group_vars/all.yml\n# 2. Create the backup secret in your tracked repo or bootstrap it separately\n# 3. Edit k8s/helm/longhorn/values.yaml to configure defaultBackupStore\n# 4. Commit and push; ArgoCD will apply the Longhorn change\n```\n\nKeep backup secrets out of Git unless your private repo already has a sealed/external secret flow.\n\n### Optional: Home Network Bridge (IoT Access)\n\nBridges homelab to home network (192.168.0.0/24) via OpenWRT's 5GHz WiFi radio. Enables Home Assistant to reach IoT devices on the home network.\n\n```bash\n# 1. Add openwrt host to hosts.yml (see hosts.yml.example)\n# 2. Configure home_wifi_ssid and home_wifi_password in group_vars/all.yml\n# 3. Run bridge playbook\nansible-playbook playbooks/openwrt-home-lan.yml -i inventory/hosts.yml\n```\n\nTraffic is NAT'd — no changes needed on the home network. To revert:\n```bash\n# SSH to OpenWRT, then:\nuci revert wireless; uci revert network; uci revert firewall; /etc/init.d/network restart\n```\n\n## Operations\n\nUpdate node config:\n```bash\nansible-playbook playbooks/nixos-update.yml -i inventory/hosts.yml\n```\n\nArgoCD-managed apps update from Git. Ansible is only for node lifecycle, bootstrap, and non-GitOps machine configuration.\n\nFor control-plane recovery, make sure `k3s_address` and any `k3s_join_address` values stay on the LAN or internal DNS. Do not point k3s peer/bootstrap traffic at public Cloudflare hostnames from `ansible_host`.\n\nReset k3s on a node (rejoin cluster):\n```bash\nansible-playbook playbooks/nixos-update.yml -i inventory/hosts.yml -e reset_k3s=true --limit \u003cnode\u003e\n```\n\n## SSH via Cloudflare (Short-Lived Certs)\n\nSet these per control-plane node in `ansible/inventory/hosts.yml`:\n- `cloudflare_ssh_ca_pubkey`\n- `cloudflare_ssh_allowed_principals` (must include your Cloudflare cert principal)\n\nGenerate per-node local SSH config blocks (localhost only):\n```bash\ncd ansible\nansible-playbook playbooks/configure-local-cloudflare-ssh.yml -i inventory/hosts.yml\n```\n\nThis writes explicit entries for each `k8s_control_plane` host in `~/.ssh/config` and keeps cert generation per host/app.\n\nThen connect directly using inventory hostnames:\n```bash\nssh nixos@\u003ccontrol-plane-ansible_host\u003e\n```\n\nTo see your principal from a generated cert:\n```bash\nssh-keygen -Lf ~/.cloudflared/\u003chost\u003e-cf_key-cert.pub\n```\n\nPassword auth remains enabled by default for rollback (`ssh_password_auth_enabled: true`) and can be disabled later by setting it to `false` and applying `nixos-update.yml`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhvcc%2Fhomelab","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdhvcc%2Fhomelab","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdhvcc%2Fhomelab/lists"}