Update .gitignore and add Home Service project documentation; enhance Homelab details
This commit is contained in:
parent
1fc99ca403
commit
c6ca4d23fc
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
.env
|
||||
.DS_Store
|
||||
.hugo_build.lock
|
||||
public/
|
||||
resources/_gen/
|
||||
83
content/projects/home-service.md
Normal file
83
content/projects/home-service.md
Normal file
@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "Home Service"
|
||||
date: 2026-05-06
|
||||
draft: false
|
||||
description: "Discord slash-command bot for home automation, built with Go microservices, gRPC, and a local LLM for natural language intent detection."
|
||||
tags: ["go", "grpc", "protobuf", "microservices", "homeautomation", "ollama", "opentelemetry"]
|
||||
github: "https://gitea.nik4nao.com/nik/home-services"
|
||||
url: ""
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
A Go microservice system that controls Home Assistant devices through Discord slash commands.
|
||||
Direct commands (`/light`, `/switch`) go straight to a typed gRPC gateway. Free-form
|
||||
natural language (`/ai query`) routes through a local LLM (Ollama) for intent extraction
|
||||
before dispatching the resolved action. All three services run on my homelab Kubernetes
|
||||
cluster, deployed via ArgoCD.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Discord user
|
||||
│
|
||||
├── /light, /switch ──(gRPC / mTLS)──▶ ha-gateway ──(REST)──▶ Home Assistant
|
||||
│
|
||||
└── /ai query ────────(gRPC / mTLS)──▶ ai-gateway ──(HTTP)──▶ Ollama
|
||||
│ (structured JSON intent)
|
||||
└──(gRPC / mTLS)──▶ ha-gateway ──(REST)──▶ Home Assistant
|
||||
```
|
||||
|
||||
Three services, each its own Go module, communicating over mTLS-secured gRPC.
|
||||
Proto definitions live in a shared `gen` module compiled with `buf`.
|
||||
|
||||
## Stack
|
||||
|
||||
- **Language:** Go — multi-module workspace (`go.work`)
|
||||
- **API layer:** gRPC + Protocol Buffers, schema managed with buf
|
||||
- **Auth:** mTLS between all services — certificates provisioned by cert-manager
|
||||
- **LLM:** Ollama (local, self-hosted) — structured JSON intent extraction
|
||||
- **External APIs:** Home Assistant REST API, Discord Gateway API
|
||||
- **Observability:** OpenTelemetry instrumentation in every service, traces exported to Tempo
|
||||
- **CI/CD:** Gitea Actions — multi-arch image builds (amd64 + arm64) on every push to `main`
|
||||
- **Deployment:** K3s via ArgoCD, credentials managed with Sealed Secrets
|
||||
|
||||
## Architecture Pattern
|
||||
|
||||
Each service follows a hexagonal (ports and adapters) layout:
|
||||
|
||||
- `core/domain` — domain types (intents, lights, entities), no framework dependencies
|
||||
- `core/ports` — interfaces the app layer depends on (driven ports)
|
||||
- `adapters/primary` — inbound adapters: gRPC server, Discord slash-command handler
|
||||
- `adapters/secondary` — outbound adapters: Home Assistant REST client, Ollama HTTP client, gRPC clients
|
||||
|
||||
Dependencies point inward — adapters depend on ports, ports know nothing about adapters.
|
||||
|
||||
## Highlights
|
||||
|
||||
- `ai-gateway` prompts Ollama with user text and a cached list of known HA lights, parses
|
||||
the model's structured JSON response as an intent, and executes it through `ha-gateway` —
|
||||
unsupported or malformed responses return a plain explanation without taking action
|
||||
- Light discovery results are cached in `ai-gateway` with a configurable TTL, reducing
|
||||
round-trips to `ha-gateway` on every AI query
|
||||
- mTLS enforced on all gRPC channels — `TLS_DIR` points each service to its cert bundle;
|
||||
certificates are issued by the cluster's internal CA via cert-manager
|
||||
- `discord-bot` tracks in-flight AI requests so graceful shutdown waits briefly before
|
||||
terminating, avoiding dropped responses
|
||||
- OpenTelemetry spans propagated across all three service boundaries — full distributed
|
||||
traces visible in Grafana Tempo
|
||||
- Multi-arch images (amd64 + arm64) built on every push via Gitea Actions and pushed to
|
||||
the self-hosted container registry
|
||||
- Test coverage at the domain and adapter layer in each service
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Port | Responsibility |
|
||||
|---|---|---|
|
||||
| `ha-gateway` | 50051 | gRPC boundary for Home Assistant — entity, light, and switch RPCs |
|
||||
| `ai-gateway` | 50052 | Intent extraction via Ollama, dispatches resolved actions to ha-gateway |
|
||||
| `discord-bot` | — | Slash-command registration and routing (`/light`, `/switch`, `/ai`) |
|
||||
|
||||
## Status
|
||||
|
||||
Active and in daily use.
|
||||
@ -2,9 +2,9 @@
|
||||
title: "Homelab Kubernetes Cluster"
|
||||
date: 2026-03-17
|
||||
draft: false
|
||||
description: "Self-hosted k3s cluster on bare-metal with Gitea CI/CD, multi-arch builds, Authentik SSO, and ~15 running workloads."
|
||||
tags: ["kubernetes", "k3s", "homelab", "infrastructure", "traefik", "authentik"]
|
||||
github: ""
|
||||
description: "Self-hosted k3s cluster on bare-metal with ArgoCD GitOps, Authentik SSO, full observability stack, and ~20 running workloads."
|
||||
tags: ["kubernetes", "k3s", "homelab", "infrastructure", "traefik", "authentik", "argocd", "ansible"]
|
||||
github: "https://gitea.nik4nao.com/nik/homelab"
|
||||
url: ""
|
||||
---
|
||||
|
||||
@ -19,35 +19,41 @@ operational patterns without a cloud bill.
|
||||
| Host | Role | Specs |
|
||||
|---|---|---|
|
||||
| Minisforum UM780 XTX | K3s control-plane | AMD Ryzen 7 8745H |
|
||||
| HP ProDesk (nik-debian) | K3s storage agent | NFS server, mergerfs media pool |
|
||||
| Mac Mini M2 | Standalone Docker host | ARM, outside the cluster |
|
||||
| HP ProDesk (nik-debian) | K3s storage agent | NFS server, media pool |
|
||||
| Mac Mini M2 | Standalone Docker host (Ollama, Watch Party) | ARM, outside the cluster |
|
||||
|
||||
## Stack
|
||||
|
||||
- **Distribution:** k3s
|
||||
- **GitOps:** Argo CD — app-of-apps pattern, all cluster state reconciled from git
|
||||
- **Ingress:** Traefik v3
|
||||
- **TLS:** cert-manager — Let's Encrypt (public) + internal CA (LAN)
|
||||
- **TLS:** cert-manager — Let's Encrypt (public) + internal CA (`*.home.arpa`)
|
||||
- **Auth:** Authentik SSO — OIDC + forwardAuth proxy, TOTP MFA enforced
|
||||
- **DNS:** Pihole (primary + secondary, externalIPs)
|
||||
- **Storage:** NFS (Debian) + local-path dynamic provisioner
|
||||
- **Secrets:** Sealed Secrets — encrypted at rest, committed to repo
|
||||
- **CI/CD:** Gitea Actions + act_runner, Docker buildx multiarch (amd64 + arm64)
|
||||
- **Registry:** Gitea built-in container registry
|
||||
- **Observability:** Prometheus + Grafana + Loki + Promtail
|
||||
- **IaC:** Ansible (host-level), Helm + raw manifests (cluster-level), all tracked in Gitea
|
||||
- **Observability:** kube-prometheus-stack, Grafana, Loki, Tempo, OpenTelemetry Collector
|
||||
- **VPN:** WireGuard
|
||||
- **IaC:** Ansible (host bootstrap), Helm values + raw manifests (cluster-level), reconciled by Argo CD
|
||||
|
||||
## Highlights
|
||||
|
||||
- All cluster state is managed as code in a Gitea monorepo — single-file manifests per service, organised by concern
|
||||
- Authentik SSO protects all web-facing services via Traefik forwardAuth; OIDC integrated with Gitea and Grafana
|
||||
- All cluster state is declared in a Gitea monorepo and reconciled by Argo CD with `selfHeal: true` — changes flow through git, not kubectl
|
||||
- App-of-apps pattern: a single root `Application` in Argo CD manages all child Applications, each pointing at a manifest directory or Helm values file
|
||||
- Sealed Secrets used for all sensitive credentials committed to the repo — encrypted with the in-cluster controller public key, safe to store in git
|
||||
- Authentik SSO protects all web-facing services via Traefik forwardAuth; OIDC integrated with Gitea, Grafana, and Argo CD
|
||||
- Full distributed tracing with OpenTelemetry Collector + Tempo — home-services traces visible end-to-end in Grafana
|
||||
- Dual-cert TLS strategy: internal CA for `*.home.arpa` services, Let's Encrypt for `*.nik4nao.com` public services; CA installer page serves `ca.crt` and an iOS/macOS mobileconfig profile
|
||||
- Multi-arch image builds (amd64 + arm64) via buildx on every push to `main`, pushed to the self-hosted registry
|
||||
- Dual-cert TLS strategy: internal CA for `*.home.arpa` services, Let's Encrypt for `*.nik4nao.com` public services
|
||||
- Pihole running as primary + secondary with externalIPs for LAN-wide DNS and ad-blocking
|
||||
- DDNS CronJob keeps the public A record in sync via the Porkbun API
|
||||
|
||||
## Running Workloads
|
||||
|
||||
Traefik, cert-manager, Pihole, Authentik, Gitea, Prometheus, Grafana, Loki, Promtail,
|
||||
Jellyfin, qBittorrent, JDownloader, Photoview, Dashy, Glances, DDNS CronJob, this portfolio site.
|
||||
Argo CD, Traefik, cert-manager, Sealed Secrets, Pihole, Authentik, Gitea, Prometheus, Grafana,
|
||||
Loki, Tempo, OpenTelemetry Collector, Glances, Jellyfin, qBittorrent, JDownloader, Photoview,
|
||||
Immich, Home Assistant, HA Gateway, AI Gateway, Discord Bot, Dashy, DDNS CronJob, this portfolio site.
|
||||
|
||||
## Status
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 5a2b4c0f1fdb9180d525930b2c8f68a90221d245
|
||||
Subproject commit 4acd067c48195ac503541ba75f9259c7158d3792
|
||||
Loading…
x
Reference in New Issue
Block a user