Update .gitignore and add Home Service project documentation; enhance Homelab details
All checks were successful
CI / build-check (push) Has been skipped
CI / build-and-push (push) Successful in 4m27s

This commit is contained in:
Nik Afiq 2026-05-06 19:50:06 +09:00
parent 1fc99ca403
commit c6ca4d23fc
4 changed files with 106 additions and 16 deletions

1
.gitignore vendored
View File

@ -1,4 +1,5 @@
.env
.DS_Store
.hugo_build.lock
public/
resources/_gen/

View 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.

View File

@ -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