{"id":17487701,"url":"https://github.com/siutsin/otaru","last_synced_at":"2026-05-03T00:04:36.120Z","repository":{"id":195097989,"uuid":"692235562","full_name":"siutsin/otaru","owner":"siutsin","description":"Bare-Metal Home Lab for Kubernetes and Technical Playground","archived":false,"fork":false,"pushed_at":"2026-03-30T03:31:03.000Z","size":10419,"stargazers_count":12,"open_issues_count":1,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-03-30T05:57:25.578Z","etag":null,"topics":["gitops","homelab","k3s","kubernetes","raspberry-pi"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/siutsin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","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":"2023-09-15T22:01:51.000Z","updated_at":"2026-03-30T03:30:38.000Z","dependencies_parsed_at":"2023-09-16T14:02:00.041Z","dependency_job_id":"231a9f58-d538-406d-a89c-ecc6cec5abfc","html_url":"https://github.com/siutsin/otaru","commit_stats":{"total_commits":870,"total_committers":3,"mean_commits":290.0,"dds":0.4494252873563218,"last_synced_commit":"2c752880076c19d7529492ee2e345bafbbe8941d"},"previous_names":["siutsin/raspberrypi-k3s"],"tags_count":86,"template":false,"template_full_name":null,"purl":"pkg:github/siutsin/otaru","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fotaru","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fotaru/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fotaru/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fotaru/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siutsin","download_url":"https://codeload.github.com/siutsin/otaru/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siutsin%2Fotaru/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31311169,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["gitops","homelab","k3s","kubernetes","raspberry-pi"],"created_at":"2024-10-19T03:43:17.761Z","updated_at":"2026-04-27T00:02:15.673Z","avatar_url":"https://github.com/siutsin.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# otaru\n\n![Kubernetes Version](https://img.shields.io/badge/Kubernetes-v1.34.6+k3s1-blue)\n[![Cluster Health](https://img.shields.io/static/v1?label=Cluster%20Health\u0026message=WebGazer\u0026color=brightgreen)](https://www.webgazer.io/s?id=493)\n\n\u003e Over-Engineering at Its Finest.\n\nBare-metal `k3s` home lab and technical playground.\n\nCurrent cluster shape:\n\n- Dedicated `192.168.10.0/24` VLAN for cluster nodes and service virtual IPs\n- `k3s` with embedded etcd on three Raspberry Pi 5 control-plane nodes\n- Flannel `wireguard-native` for pod networking\n- MetalLB + Envoy Gateway for service and ingress load balancing\n- Istio ambient mesh for east-west traffic and Kiali for mesh observability\n\n## Architecture\n\n![Otaru cluster architecture diagram](assets/otaru-architecture.png)\n\n## Hardware\n\n![Raspberry Pi rack setup](assets/rack.jpeg)\n\n\u003c!-- markdownlint-disable MD060 --\u003e\n| Node             | Device                                    | Role           | Boot | Storage                                              |\n|------------------|-------------------------------------------|----------------|------|------------------------------------------------------|\n| `raspberrypi-00` | [Raspberry Pi 5 8GB][rpi5]                | Control plane  | NVMe | [Lexar NM620 256GB][lexar-nm620]                     |\n| `raspberrypi-01` | Raspberry Pi 5 8GB                        | Control plane  | NVMe | [Samsung 980 PRO 2TB (MZ-V8P2T0BW)][samsung-980-pro] |\n| `raspberrypi-02` | Raspberry Pi 5 8GB                        | Control plane  | NVMe | [Crucial P3 Plus 4TB][crucial-p3-plus]               |\n| `raspberrypi-03` | [Raspberry Pi 4 Model B 8GB][rpi4]        | Worker         | SD   | SanDisk Max Endurance 32 GB                          |\n| `ucg-ultra`      | [UniFi Cloud Gateway Ultra][ucg-ultra]    | Router/Gateway | -    | -                                                    |\n| `usw-ultra`      | [UniFi Switch Ultra][usw-ultra]           | PoE switch     | -    | -                                                    |\n| `rackmate-t1`    | [GeeekPi DeskPi RackMate T1][rackmate-t1] | Rack enclosure | -    | -                                                    |\n| `rack-mount`     | [GeeekPi 10\" 2U Rack Mount][rack-mount]   | Pi rack mount  | -    | -                                                    |\n\u003c!-- markdownlint-enable MD060 --\u003e\n\nThe cluster now runs embedded etcd on `raspberrypi-00`, `raspberrypi-01`, and `raspberrypi-02`.\nLonghorn uses the root filesystem on the NVMe-backed nodes directly. `raspberrypi-03` remains a worker\nand is intentionally unschedulable for Longhorn storage.\n\n## Pending Node\n\n| Node     | Device                                     | Planned role  | Boot      | Storage             |\n|----------|--------------------------------------------|---------------|-----------|---------------------|\n| `nuc-00` | [Intel NUC Mini PC Core i3-3217U 8GB][nuc] | Future worker | mSATA/LVM | 64 GB local storage |\n\n## Network Layout\n\n| IP              | Role                 |\n|-----------------|----------------------|\n| `192.168.10.1`  | VLAN gateway         |\n| `192.168.10.50` | Kubernetes API VIP   |\n| `192.168.10.51` | Internal ingress VIP |\n| `192.168.10.60` | `raspberrypi-00`     |\n| `192.168.10.61` | `raspberrypi-01`     |\n| `192.168.10.62` | `raspberrypi-02`     |\n| `192.168.10.63` | `raspberrypi-03`     |\n| `192.168.10.64` | `nuc-00`             |\n\n[nuc]: https://www.intel.com/content/www/us/en/products/sku/71275/intel-nuc-kit-dc3217iye/specifications.html\n[lexar-nm620]: https://www.lexar.com/global/products/Lexar-NM620-M-2-2280-NVMe-SSD/\n[crucial-p3-plus]: https://www.crucial.com/ssd/p3-plus/ct4000p3pssd8\n[samsung-980-pro]: https://www.samsung.com/uk/memory-storage/nvme-ssd/980-pro-2tb-nvme-pcie-gen-4-mz-v8p2t0bw/\n[rackmate-t1]: https://www.amazon.co.uk/dp/B0CS6MHCY8\n[rack-mount]: https://www.amazon.co.uk/dp/B0DRGF68Z9\n[ucg-ultra]: https://uk.store.ui.com/uk/en/category/cloud-gateways-compact/products/ucg-ultra\n[rpi4]: https://thepihut.com/products/raspberry-pi-4-model-b?variant=31994565689406\n[rpi5]: https://thepihut.com/products/raspberry-pi-5?src=raspberrypi\u0026variant=42531604955331\n[usw-ultra]: https://uk.store.ui.com/uk/en/category/switching-utility/collections/pro-ultra/products/usw-ultra\n\n## Cluster Components\n\n\u003c!-- markdownlint-disable MD060 --\u003e\n| Category     | Name                                                                                                | Description                                                                                            |\n|--------------|-----------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|\n| Application  | [Blocky](https://0xerr0r.github.io/blocky/latest/)                                                  | Stateless DNS server                                                                                   |\n| Application  | [changedetection.io](https://github.com/dgtlmoon/changedetection.io)                                | Self-hosted website change detection and alerting                                                      |\n| Application  | [CyberChef](https://github.com/gchq/CyberChef)                                                      | The Cyber Swiss Army Knife by GCHQ                                                                     |\n| Application  | [Excalidraw](https://github.com/excalidraw/excalidraw)                                              | Virtual whiteboard for sketching hand-drawn like diagrams                                              |\n| Application  | [Home Assistant](https://www.home-assistant.io/)                                                    | Home Automation                                                                                        |\n| Application  | [JSON Crack](https://github.com/AykutSarac/jsoncrack.com)                                           | JSON, YAML, etc. visualizer and editor                                                                 |\n| Application  | [Kubernetes MCP Server](https://github.com/containers/kubernetes-mcp-server)                        | Model Context Protocol server for Kubernetes cluster operations                                        |\n| Application  | [TeslaMate](https://github.com/teslamate-org/teslamate/)                                            | Self-hosted data logger for Tesla                                                                      |\n| Application  | [k3s-apiserver-loadbalancer](https://github.com/siutsin/k3s-apiserver-loadbalancer)                 | An operator to update the `kubernetes` service type to `LoadBalancer`                                  |\n| Application  | [冗PowerBot](https://github.com/siutsin/telegram-jung2-bot)                                          | Telegram bot tracks and counts individual message counts in groups                                     |\n| CI/CD        | [Argo CD](https://github.com/argoproj/argo-cd)                                                      | GitOps, drift detection, and reconciliation                                                            |\n| CI/CD        | [Atlantis](https://github.com/runatlantis/atlantis)                                                 | OpenTofu Pull Request Automation, currently disabled in Argo CD                                        |\n| Connectivity | [Envoy Gateway](helm-charts/envoy-gateway)                                                          | Gateway API ingress controller with TLS termination and shared MetalLB virtual IP                      |\n| Connectivity | [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) | Cloudflare Zero Trust Edge                                                                             |\n| Connectivity | [Flannel](https://github.com/flannel-io/flannel)                                                    | `wireguard-native` encrypted pod networking for `k3s`                                                  |\n| Connectivity | [Gateway API Kubernetes](helm-charts/gateway-api-kubernetes)                                        | Virtual IP and Layer 2 announcement for `kubernetes` service's External IP                             |\n| Connectivity | [Gateway API](https://gateway-api.sigs.k8s.io/)                                                     | Kubernetes standard CRDs for managing network traffic                                                  |\n| Connectivity | [MetalLB](helm-charts/metallb)                                                                      | Bare metal `LoadBalancer` implementation for service virtual IP allocation and L2 advertisement        |\n| Connectivity | [httpbin](https://github.com/Kong/httpbin)                                                          | Generic health check service                                                                           |\n| Database     | [CloudNativePG Barman Cloud Plugin](helm-charts/cloudnative-pg-plugin-barman-cloud)                 | PostgreSQL backup plugin for cloud storage providers                                                   |\n| Database     | [CloudNativePG Clusters](helm-charts/cloudnative-pg-clusters)                                       | Multi-cluster PostgreSQL management with B2 backup integration                                         |\n| Database     | [CloudNativePG](https://github.com/cloudnative-pg/cloudnative-pg)                                   | A Kubernetes operator that manages PostgreSQL clusters                                                 |\n| Monitoring   | [Grafana](https://github.com/grafana/grafana)                                                       | Grafana LGTM Stack. Visualisation dashboards                                                           |\n| Monitoring   | [Heartbeats](helm-charts/heartbeats)                                                                | Kubernetes operator for heartbeat monitoring                                                           |\n| Monitoring   | [Kiali](helm-charts/kiali)                                                                          | Service mesh observability UI for Istio                                                                |\n| Monitoring   | [Kubernetes Metrics Server](https://github.com/kubernetes-sigs/metrics-server)                      | Scalable, efficient source of container resource metrics for Kubernetes built-in autoscaling pipelines |\n| Monitoring   | [Monitoring Stack](helm-charts/monitoring)                                                          | Complete monitoring stack with Grafana, Prometheus, and Loki                                           |\n| Scheduling   | [Descheduler](https://github.com/kubernetes-sigs/descheduler)                                       | Evicts pods for optimal cluster node utilisation                                                       |\n| Scheduling   | [k8s-cleaner](https://github.com/gianlucam76/k8s-cleaner)                                           | Automated failed pod cleanup and periodic workload repaving                                            |\n| Scheduling   | [KEDA](https://keda.sh/)                                                                            | Event Driven Autoscaler                                                                                |\n| Scheduling   | [Reloader](https://github.com/stakater/Reloader)                                                    | Watch changes in ConfigMap and Secret and do rolling upgrades                                          |\n| Security     | [1Password Connect](https://github.com/1Password/connect)                                           | Proxy service for 1Password; acts as a secret provider                                                 |\n| Security     | [External Secrets Operator](https://github.com/external-secrets/external-secrets)                   | Extracts secrets from a secret provider                                                                |\n| Security     | [amazon-eks-pod-identity-webhook](https://github.com/aws/amazon-eks-pod-identity-webhook)           | Amazon EKS Pod Identity Webhook for IRSA in bare metal Kubernetes clusters                             |\n| Security     | [cert-manager](https://github.com/cert-manager/cert-manager)                                        | Manages TLS certificates via Let's Encrypt and ACME protocol                                           |\n| Security     | [Istio](helm-charts/istio-base)                                                                     | Service mesh control plane and ambient dataplane (`istiod`, `istio-cni`, `ztunnel`)                    |\n| Security     | [oidc-provider](helm-charts/oidc-provider)                                                          | Kubernetes OIDC provider and JWKS endpoint                                                             |\n| Security     | [zizmor](https://docs.zizmor.sh/)                                                                   | Static analysis for GitHub Actions                                                                     |\n| Storage      | [Longhorn Config](helm-charts/longhorn-config)                                                      | Longhorn configuration and recurring jobs                                                              |\n| Storage      | [Longhorn Volume Lib](helm-charts/longhorn-volume-lib)                                              | Reusable volume templates for Longhorn storage                                                         |\n| Storage      | [Longhorn](https://github.com/longhorn/longhorn)                                                    | Distributed block storage system; backup and restore from/to remote destinations                       |\n\u003c!-- markdownlint-enable MD060 --\u003e\n\n## IaaS, PaaS, and SaaS\n\n\u003c!-- markdownlint-disable MD060 --\u003e\n| Category     | Name          | Service                                                                                  | Description                                  |\n|--------------|---------------|------------------------------------------------------------------------------------------|----------------------------------------------|\n| CI/CD        | GitHub        | [Actions](https://github.com/features/actions)                                           | Run Terragrunt                               |\n| CI/CD        | Sourcery      | [AI Code Reviews](https://docs.sourcery.ai/)                                             | Instant feedback for Pull Requests           |\n| Connectivity | Cloudflare    | [Access](https://developers.cloudflare.com/cloudflare-one/policies/access/)              | Edge Access Control                          |\n| Connectivity | Cloudflare    | [DNS](https://developers.cloudflare.com/dns/)                                            | Authoritative DNS Service                    |\n| Connectivity | Cloudflare    | [Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) | Edge Connectivity                            |\n| Connectivity | UniFi         | [Wifiman](https://ui.com/)                                                               | VPN gateway to home network                  |\n| Monitoring   | Heartbeats    | [Heartbeats Operator](helm-charts/heartbeats)                                            | Kubernetes operator for heartbeat monitoring |\n| Monitoring   | WebGazer      | [Uptime Monitoring](https://www.webgazer.io/)                                            | Health Check                                 |\n| Security     | 1Password     | [Connect](https://developer.1password.com/docs/connect/)                                 | Secrets Automation                           |\n| Security     | AWS           | [STS](https://aws.amazon.com/iam/features/sts/)                                          | OIDC/IRSA JWT token exchange                 |\n| Security     | Let's Encrypt | [Let's Encrypt](https://letsencrypt.org/)                                                | Certificate Authority                        |\n| Security     | Snyk          | [Snyk](https://app.snyk.io/)                                                             | Detects vulnerabilities                      |\n| Storage      | AWS           | [DynamoDB](https://aws.amazon.com/dynamodb/)                                             | Database backend for 冗PowerBot               |\n| Storage      | AWS           | [S3](https://aws.amazon.com/s3/)                                                         | OpenTofu Remote State                        |\n| Storage      | Backblaze     | [B2](https://www.backblaze.com/cloud-storage)                                            | Volume Backup                                |\n\u003c!-- markdownlint-enable MD060 --\u003e\n\n## Bootstrap Cluster\n\n1. **Install Tooling**\n\n    ```shell\n    brew install \\\n      ansible \\\n      direnv \\\n      go-jsonnet \\\n      helm \\\n      kubectl \\\n      opentofu \\\n      terragrunt\n    ```\n\n2. **Add SSH Keys to `known_hosts`**\n\n    ```shell\n    KH=~/.ssh/known_hosts \u0026\u0026 touch \"$KH\" \u0026\u0026 for ip in 192.168.10.{60..63}; do ssh-keygen -f \"$KH\" -R \"$ip\"; ssh-keyscan \"$ip\" \u003e\u003e \"$KH\"; done\n    ```\n\n3. **Set Up Service Credentials**\n\n    Create the local files documented in [Secrets](documentation/secrets.md)\n    before running cluster bootstrap. Keep actual credentials outside this repo.\n\n4. **Bootstrap Cluster**\n\n    ```shell\n    make setup\n    ```\n\n## Oopsy\n\nUpdate host packages and reboot the entire cluster.\n\n```shell\nmake maintenance\n```\n\nUpgrade k3s kubernetes version and restart workloads.\n\n```shell\nmake upgrade\n```\n\nUnlock a LUKS node after boot.\n\n```shell\nmake unlock raspberrypi-01\n```\n\nWipe everything and start from scratch.\n\n```shell\nmake nuke\n```\n\nSet up Raspberry Pi nodes and K3s cluster.\n\n```shell\nmake setup\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiutsin%2Fotaru","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiutsin%2Fotaru","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiutsin%2Fotaru/lists"}