# Roadmap Direction and priorities for the homelab — what it should become, beyond current state. ## Near-term (next few sessions) - **House automation** — moved to [khe-home-assistant's roadmap](https://github.com/khelias/khe-home-assistant/blob/main/ROADMAP.md). - **Resource-limit tuning from metrics** — initial `deploy.resources.limits` now cover every long-running container. Watch Docker stats / service behavior and tune caps where Immich shows real workload pressure. - **Healthcheck cleanup** — standardise `start_period`, replace trivial checks with real probes. - **Immich: unused feature surface** — audited 2026-08-03, Tier 1 (multilingual CLIP, fullsize renders, 1080p transcode) landed. Still open, roughly in order: - **Config secrets have nowhere to live.** `immich.config.json` is committed to a public repo and `IMMICH_CONFIG_FILE` locks the admin UI, so SMTP and OAuth cannot be enabled at all until the file is rendered at deploy time from a committed template plus `.env`. Blocks the two items below. - **SMTP** — no album invites, welcome mails or password resets for family accounts today. - **External library** — `library.scan` / `library.watch` unset and nothing from `/srv` is mounted `:ro`, so any pre-Immich archive is invisible. Touches compose mounts and the backup assumption, decide together. - **Per-user storage quota** — unset, so one account can fill the ZFS mirror. - **`duplicateDetection.maxDistance: 0.01`** is near bit-identical only; 0.02-0.03 would surface real burst duplicates. - **`job` concurrency** unset — defaults are conservative against the 2-CPU cap, worth raising temporarily for bulk re-index runs. - **Metrics** — `IMMICH_TELEMETRY_INCLUDE` would expose job-queue and ML latency on `:8081`, but Alloy only ships logs to Loki; no Prometheus in the stack yet, so this is gated on adding one. - **Upload backup assumption** — `backup.sh` skips Immich uploads because they are mirrored to iCloud + Google Photos. That stops being true the moment a family account without such a mirror starts backing up. ## Medium-term (when app phase starts) - **Offsite backup verification** — offsite is live (`restic` → Cloudflare R2, daily, client-side AES-256, `--keep-daily 7 --keep-weekly 4 --keep-monthly 12`; see [infrastructure/offsite-backup.md](infrastructure/offsite-backup.md)), so 3-2-1 is satisfied. Daily `restic check` covers metadata only; schedule a monthly `restic check --read-data-subset` once the repo is large enough to make full-data verification meaningful. - **Bootstrap script for full rebuild** — one entry point that takes a fresh Proxmox host to a fully working homelab. The setup steps are scripted already but have no orchestrator handling the reboot points. - **ZFS datasets that match the NFS export** — `/srv/data` is exported without `crossmnt`, so the VM writes every service's files into `tank/data` itself, Immich's ~400G of photos included. `tank/data/immich` exists but is empty (96K); the nextcloud, paperless and media datasets were empty for the same reason and were destroyed on 2026-10-01. `setup-nfs-share.sh` still creates `tank/data/immich`, so a rebuild repeats the mismatch. Either drop it from the script and destroy the empty dataset, or add `crossmnt` and move the photos into it, which buys per-dataset snapshots and quotas at the cost of copying ~400G. Decide before the rebuild rehearsal below. - **Disaster recovery runbook from a rebuild rehearsal** — the tested restore is done (`restore-verify.yml` restores a Postgres dump from R2 every week). What is left is rebuilding the host once for real and writing the runbook from it; tracked in the estate roadmap in `khe-meta` (1.3). ## Long-term (when app-heavy projects arrive) - **Komodo as GitOps controller** — once adventure-engine, spliit, or similar projects land, a UI + API + rollback become worth the install. A push to `main` already deploys through `deploy.yml`. - **Upgrade strategy documented** — major jumps (PVE 9 → 10, Debian 13 → 14, Immich major) need a rehearsed path. Capture the steps before the first painful upgrade, not after. - **Authentik / Authelia SSO** — once RAM upgrade lands, consolidate auth across services instead of each one managing its own. ## Ambitions Directions that take several seasons, not sessions. None is committed; each has a first step that is worth doing on its own and says what it waits for. The sections above come first. - **A house that runs itself** — moved to [khe-home-assistant's roadmap](https://github.com/khelias/khe-home-assistant/blob/main/ROADMAP.md#ambitions). - **Automated rebuild day.** Once a quarter, a workflow builds the whole homelab from git and the R2 backups on an empty VM, checks the services come up, and records time-to-restore. The number and its trend go on the public architecture page (`khe.ee/architecture`, planned in `khe-meta`). - *Why here:* the pieces exist. The VM is created by cloud-init, a push is the deploy, and `restore-verify.yml` already restores one Postgres dump from R2 every week. This extends that from one database to the whole stack. - *First step:* the manual rebuild rehearsal and DR runbook tracked in the estate roadmap in `khe-meta`, then the bootstrap script from the medium-term list above. Time the manual run; that is the first number. - *Waits for:* the rehearsal fixes, and room to run a second VM. The host has 32GB and the Docker VM takes 16GB, which leaves about 8GB for a second VM, so a full parallel rebuild needs the RAM upgrade, a reduced stack, or a short-lived cloud VM. - *Risk and cost:* a rebuild VM must never talk to the live Cloudflare tunnel, Telegram bot or house devices, so it runs with isolated credentials. What it restores is config, databases and small user data; Immich originals are not in the backup (see below), so the number describes that scope, not a full restore. - **Second site.** A small node at a relative's home, reached over Tailscale, holding a second restic repository of this homelab's backups and, in return, theirs. Later it could serve the public static sites warm when this one is down. - *Why here:* R2 is the only offsite copy today. A second copy under our own control makes 3-2-1 independent of one provider and one account, and makes large data (Immich originals) affordable to keep offsite. - *First step:* a second `restic` repository on any spare disk outside the house, fed by the same `offsite-backup.sh` run, with the same `restic check`. - *Waits for:* a willing host household and a low-power machine. - *Risk and cost:* hardware and electricity at someone else's home, and support calls when their router changes. The static sites already have the edge fallback ([estate ADR-016](https://github.com/khelias/khe-architecture/blob/main/decisions/016-static-fallback-at-the-edge.md)); the case for a second site is data, not availability. - **Agent-operated homelab.** Scheduled agents read Loki alerts, Renovate PRs held for review and Uptime Kuma state, diagnose, and prepare a fix as a branch or a written proposal. The operator reads, approves and pushes; the boundary that the operator runs anything touching the host stays. - *Why here:* the status snapshot and every container's logs are in Loki, which an agent reads read-only through mcp-grafana without SSH, and Renovate auto-merges the routine bumps, so what is left for a human is the judgement calls. OpenClaw was removed on 2026-09-25 because its socket proxy let an LLM agent read every container's env; an agent here reads through those same read-only windows and never gets the Docker socket. - *First step:* a weekly triage note (a scheduled Actions workflow or a `/schedule` routine carries it) listing each alert and held PR with a proposed action. Measure how many proposals the operator accepts unchanged. - *Waits for:* Prometheus metrics (estate roadmap), so diagnoses rest on more than logs. - *Risk and cost:* logs, changelogs and PR bodies are untrusted text an agent reads, so prompt injection is the main threat. Loki OSS has no per-stream access control, so the Vaultwarden, Home Assistant, Immich and trips logs are within reach; the agent queries only the containers a task needs and never quotes personal data or tokens from them. Agents get no write path beyond a branch or a note, and a workflow still never takes a shell command as input. Model cost if a hosted model does the work; no local model runs here since Ollama was removed on 2026-10-01. - **Local AI serving for the apps.** Serve khe-ai-adventure's narration from a local model here instead of a hosted API, so a game costs nothing per play. - *Why here:* Ollama ran here with an OpenAI-compatible API until 2026-10-01, when it was removed for lack of use. Its compose file is in this repo's git history. - *Honest state:* it was CPU-only, capped at 10G RAM and 6 CPUs inside an 8-vCPU, 24GB VM, and ran `qwen2.5:7b`. khe-ai-adventure's own roadmap keeps local models out of the live path until latency, Estonian quality and structured-output reliability are competitive, and nothing measured says a 7B CPU model is. On this hardware the answer is most likely no. - *First step:* re-add the Ollama stack from git history (with the `ai-internal` network it needs), replay a recorded game's prompts against it and score it with the adventure repo's model matrix: turn latency, schema retries, Estonian editor corrections. - *Waits for:* the RTX-class GPU under Hardware, and a measured per-game API cost from the proxy logs to compare against. - *Risk and cost:* a GPU costs money and draws power around the clock, which may exceed the API bill of a low-volume party game. Worth doing only if the GPU is bought for Immich and local models anyway. - **Family data the homelab can stand behind alone.** Today `backup.sh` skips Immich originals because they are mirrored to iCloud and Google Photos. The ambition is the reverse: the homelab holds the primary copy with its own offsite backup, and the third-party mirrors become optional. - *Why here:* Immich already replaces the cloud photo services; only the backup does not yet trust it to. - *First step:* measure the size of Immich originals and price keeping them offsite (R2 beyond its free 10 GB, or the second site). - *Waits for:* the Immich config-secrets and SMTP items above, before family accounts rely on it, and the upload-backup assumption in the Immich list being retired. - *Risk and cost:* until the offsite copy exists and restore-verify covers it, dropping a mirror would make this box the only copy of the family photo archive. The payoff is independence, and money only if a cloud subscription is actually cancelled. ## Hardware Currently: i7-12700K, 32GB DDR5, 2× 12TB ZFS mirror, 2TB NVMe. No discrete GPU. - **RTX-class GPU** — accelerate local LLMs (Ollama, CPU-only `qwen2.5:7b`, was removed on 2026-10-01 for lack of use) and Immich ML (today OpenVINO CPU). IOMMU is already on, iGPU is already passed through for Quick Sync — a discrete card would pass through the same way. - **+32GB DDR5 → 64GB total** — unblocks Authentik SSO, more concurrent services, larger local LLMs, parallel ML workloads. - **UPS** — not yet; power cut is unclean shutdown for the whole homelab. Worth considering once critical family usage grows. - **10GbE upgrade** — only relevant if Immich transfers start saturating the current 2.5GbE link. No evidence of that yet. ## Service wishlist Rough order of impact: - **Quick wins** — Dozzle (Docker log viewer), ntfy (push notifications), IT-Tools (dev utilities) - **Weekend projects** — Forgejo (self-hosted Git), CrowdSec (IPS), KitchenOwl (groceries + recipes) - **When time allows** — Actual Budget, Stirling PDF, Karakeep (bookmarks + AI), FreshRSS, Changedetection.io, Docmost (wiki) - **After RAM upgrade** — Authentik (SSO) or Authelia (lighter alternative) - **Own projects** — adventure-engine revival, Spliit (Splitwise alternative), khe-study iterations - **khe-memory (idea, not started)** — cross-agent memory bank as own project. SQLite + sqlite-vec + local embeddings (`nomic-embed-text`; Ollama, removed on 2026-10-01, would have to come back), MCP server over HTTP. Shared store for Claude Code and Codex CLI on both laptops, reached via Tailscale. Differentiators worth pursuing: auto-ingest from existing `~/.claude/projects/` and `~/.codex/sessions/` history (bootstrap problem solved with real data), cross-agent provenance (track which agent wrote each fact, surface conflicts), memory decay / re-validation lifecycle. Lives under `services/ai/memory/`, ~500MB RAM, no extra DB infrastructure.