From 4472e73ae10b4dacda8e1cdbff132e3a5f256750 Mon Sep 17 00:00:00 2001 From: dtoro Date: Fri, 26 Jun 2026 19:06:49 +0200 Subject: [PATCH] Yuvomi deployment: LXC 129 house.hubris.network, Docker, Caddy, DNS, VPS traefik, Authentik OIDC, Paperless WebDAV bridge --- .zennotes/note-meta-cache-v1.json | 2 +- containers/129-house.md | 48 +++ containers/index.md | 1 + infrastructure/ingress.md | 1 + inventory.yaml | 11 + plans/2026-06-25-yuvomi-deployment.md | 443 ++++++++++++++++++++++++++ plans/index.md | 2 + 7 files changed, 507 insertions(+), 1 deletion(-) create mode 100644 containers/129-house.md create mode 100644 plans/2026-06-25-yuvomi-deployment.md diff --git a/.zennotes/note-meta-cache-v1.json b/.zennotes/note-meta-cache-v1.json index b861af2..f1c5ca5 100644 --- a/.zennotes/note-meta-cache-v1.json +++ b/.zennotes/note-meta-cache-v1.json @@ -1 +1 @@ -{"version":1,"entries":[{"path":"AGENTS.md","mtimeMs":1780354352988.1921,"size":4987,"meta":{"path":"AGENTS.md","title":"AGENTS","folder":"inbox","siblingOrder":5,"createdAt":1780354352981.0715,"updatedAt":1780354352988.1921,"size":4987,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"AGENTS.md — orientation for any agent on a homelab client You are running on a machine that is part of the hubris homelab. The full context is in this checkout at . This file is the entry point. Read it once at start, th","isSymlink":false}},{"path":"CONTRIBUTING.md","mtimeMs":1780346816514.084,"size":2674,"meta":{"path":"CONTRIBUTING.md","title":"CONTRIBUTING","folder":"inbox","siblingOrder":6,"createdAt":1780346816513.5295,"updatedAt":1780346816514.084,"size":2674,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"Contributing to the Homelab Wiki Voice Concise, technical, sysadmin-to-sysadmin. No marketing prose, no exclamation marks. Page templates Container page ( ) Cross-cutting page ( ) Plan ( ) Investigation ( ) Linking disci","isSymlink":false}},{"path":"HERMES.md","mtimeMs":1780354337315.819,"size":3101,"meta":{"path":"HERMES.md","title":"HERMES","folder":"inbox","siblingOrder":7,"createdAt":1780354337308.1587,"updatedAt":1780354337315.819,"size":3101,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"HERMES.md — Agent persona for homelab clients This file is the canonical agent persona for all AI agents running on machines in the hubris homelab. It prescribes behaviour, token-efficiency conventions, and the source-of","isSymlink":false}},{"path":"README.md","mtimeMs":1780560778432.5747,"size":4930,"meta":{"path":"README.md","title":"README","folder":"inbox","siblingOrder":8,"createdAt":1780560778426.7786,"updatedAt":1780560778432.5747,"size":4930,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Homelab Wiki — Living documentation for the hubris Proxmox homelab. Every node, every cross-cutting system, and every meaningful incident is its own page; pages are linked so you can start anywhere and walk the graph. La","isSymlink":false}},{"path":"containers/101-jellyfin.md","mtimeMs":1780345724703.8516,"size":1501,"meta":{"path":"containers/101-jellyfin.md","title":"101-jellyfin","folder":"inbox","siblingOrder":0,"createdAt":1780345724703.7935,"updatedAt":1780345724703.8516,"size":1501,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"101 — Media server: serves the movies / TV / anime / music / audiobooks / podcasts libraries from to LAN clients. At a glance - Hostname: - IP: - Privilege: unprivileged + idmap (so it can write to the group on ) - Resou","isSymlink":false}},{"path":"containers/102-nfs-export.md","mtimeMs":1780345724703.9788,"size":6678,"meta":{"path":"containers/102-nfs-export.md","title":"102-nfs-export","folder":"inbox","siblingOrder":1,"createdAt":1780345724703.8984,"updatedAt":1780345724703.9788,"size":6678,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"102 — Dedicated, single-purpose LXC that re-exports over NFSv4 to clients that can't use the host's PVE virtiofs path — currently only 100-zimaos, which ships a kernel without virtiofs support. At a glance - Hostname: - ","isSymlink":false}},{"path":"containers/103-paperless.md","mtimeMs":1780560805423.0337,"size":1924,"meta":{"path":"containers/103-paperless.md","title":"103-paperless","folder":"inbox","siblingOrder":2,"createdAt":1780560805416.4663,"updatedAt":1780560805423.0337,"size":1924,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"103 — Paperless-ngx for document management. Ingests scans / PDFs from and serves OCR'd indexed copies. At a glance - Hostname: - IP: - Privilege: privileged - Resources: 2 cores / 3 GiB RAM / 8 GiB rootfs - Mounts: ↔ (c","isSymlink":false}},{"path":"containers/104-gitea.md","mtimeMs":1780345724704.2058,"size":3905,"meta":{"path":"containers/104-gitea.md","title":"104-gitea","folder":"inbox","siblingOrder":3,"createdAt":1780345724704.1404,"updatedAt":1780345724704.2058,"size":3905,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"104 — Self-hosted git server. Source of truth for all repositories that auto-deploy across the lab. At a glance - Hostname: - IP: - Privilege: privileged - Resources: 1 core / 1 GiB RAM / 8 GiB rootfs - Mounts: ↔ (under ","isSymlink":false}},{"path":"containers/105-apps.md","mtimeMs":1780352727930.0833,"size":10839,"meta":{"path":"containers/105-apps.md","title":"105-apps","folder":"inbox","siblingOrder":4,"createdAt":1780352727923.2222,"updatedAt":1780352727930.0833,"size":10839,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"105 — Docker host for everything that doesn't justify its own LXC. Currently runs Artifacto, Booklore, PlantUML server, Portainer (and historically WriteFreely / blog), plus the homelab-context distribution services (MCP","isSymlink":false}},{"path":"containers/106-auth-outpost.md","mtimeMs":1780782336629.5935,"size":5011,"meta":{"path":"containers/106-auth-outpost.md","title":"106-auth-outpost","folder":"inbox","siblingOrder":5,"createdAt":1780782336621.4434,"updatedAt":1780782336629.5935,"size":5011,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"106 — Authentik forward-auth outpost for LAN-gated apps. A stateless proxy that connects outbound to the VPS Authentik core and serves forward-auth locally, so Caddy (121) never hairpins auth through VPS Traefik. At a gl","isSymlink":false}},{"path":"containers/107-dns.md","mtimeMs":1780779036582.4163,"size":5515,"meta":{"path":"containers/107-dns.md","title":"107-dns","folder":"inbox","siblingOrder":6,"createdAt":1780779036572.9216,"updatedAt":1780779036582.4163,"size":5515,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"107 — Homelab DNS server (Technitium). Replaces the dnsmasq that lived on 124 — authentik; single-purpose, one job. At a glance - Hostname: - IP: (static — stable, decoupled from any app) - Privilege: privileged (Docker-","isSymlink":false}},{"path":"containers/114-nextcloud.md","mtimeMs":1780345724704.6995,"size":8636,"meta":{"path":"containers/114-nextcloud.md","title":"114-nextcloud","folder":"inbox","siblingOrder":7,"createdAt":1780345724704.615,"updatedAt":1780345724704.6995,"size":8636,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"114 — Personal cloud / file collaboration. Source-of-truth for the photo libraries surfaced by mulita (120). At a glance - Hostname: - IP: - Privilege: privileged - Resources: 4 cores / 6 GiB RAM / 25 GiB rootfs - Mounts","isSymlink":false}},{"path":"containers/118-elementsynapse.md","mtimeMs":1780778973248.468,"size":6368,"meta":{"path":"containers/118-elementsynapse.md","title":"118-elementsynapse","folder":"inbox","siblingOrder":8,"createdAt":1780778973241.1172,"updatedAt":1780778973248.468,"size":6368,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"118 — Matrix homeserver (Synapse). Backs . At a glance - Hostname: - IP: - Privilege: unprivileged - Resources: 1 core / 2 GiB RAM / 16 GiB rootfs (grown from 8 GiB on 2026-05-15 after disk-full incident) - Mounts: none ","isSymlink":false}},{"path":"containers/119-sophia.md","mtimeMs":1780345724704.9253,"size":752,"meta":{"path":"containers/119-sophia.md","title":"119-sophia","folder":"inbox","siblingOrder":9,"createdAt":1780345724704.8606,"updatedAt":1780345724704.9253,"size":752,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"119 — Single-container workload \"sophia\". Reads/writes under . At a glance - Hostname: - IP: - Privilege: privileged - Resources: 2 cores / 1 GiB RAM / 10 GiB rootfs - Mounts: ↔ - Public hostname: none Permissions LXC ha","isSymlink":false}},{"path":"containers/120-mule-images.md","mtimeMs":1780345724705.116,"size":40719,"meta":{"path":"containers/120-mule-images.md","title":"120-mule-images","folder":"inbox","siblingOrder":10,"createdAt":1780345724704.9697,"updatedAt":1780345724705.116,"size":40719,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"120 — Hosts — the photos app at . PhotoPrism + Go sidecar + SvelteKit, replacing the legacy FastAPI/Celery stack as of 2026-05-22 (see Changelog). Auto-deploys from on . At a glance - Hostname: - IP: - Privilege: privile","isSymlink":false}},{"path":"containers/121-caddy.md","mtimeMs":1781344617107.1443,"size":7222,"meta":{"path":"containers/121-caddy.md","title":"121-caddy","folder":"inbox","siblingOrder":11,"createdAt":1781344617100.2546,"updatedAt":1781344617107.1443,"size":7222,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"121 — The reverse proxy. Terminates TLS for every hostname on the LAN/mesh and forwards to the right backend. At a glance - Hostname: - IP: - Privilege: unprivileged - Resources: 1 core / 512 MiB RAM / 6 GiB rootfs - Mou","isSymlink":false}},{"path":"containers/122-arriman.md","mtimeMs":1781344598212.5852,"size":10156,"meta":{"path":"containers/122-arriman.md","title":"122-arriman","folder":"inbox","siblingOrder":12,"createdAt":1781344598204.7722,"updatedAt":1781344598212.5852,"size":10156,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"122 — Docker host running the \\arr stack via compose. Replaced the old yunohost-based LXC 100 on 2026-04-21. At a glance - Hostname: - IP: - Privilege: privileged - Resources: 4 cores / 8 GiB RAM / 24 GiB rootfs - Mounts","isSymlink":false}},{"path":"containers/123-claudio-bot.md","mtimeMs":1780560778655.496,"size":4318,"meta":{"path":"containers/123-claudio-bot.md","title":"123-claudio-bot","folder":"inbox","siblingOrder":13,"createdAt":1780560778648.8645,"updatedAt":1780560778655.496,"size":4318,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"123 — (DEPRECATED — destroyed 2026-06-04) This LXC was destroyed on 2026-06-04. Replaced by Hermes Agent on mac-mini. Monitoring migrated to skill + 15-min Hermes cronjob. Repos and archived (read-only) on Gitea. See dep","isSymlink":false}},{"path":"containers/126-plato.md","mtimeMs":1780345724705.7505,"size":5515,"meta":{"path":"containers/126-plato.md","title":"126-plato","folder":"inbox","siblingOrder":14,"createdAt":1780345724705.6843,"updatedAt":1780345724705.7505,"size":5515,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"126 — Docker host for Plato — a cross-linked notes workspace (SvelteKit SPA embedded into a Go HTTP server, SQLite-backed). LAN+mesh only, no public ingress. At a glance - Hostname: - IP: - Privilege: privileged - Resour","isSymlink":false}},{"path":"containers/127-mule-photos-new.md","mtimeMs":1780345724705.8857,"size":15220,"meta":{"path":"containers/127-mule-photos-new.md","title":"127-mule-photos-new","folder":"inbox","siblingOrder":15,"createdAt":1780345724705.7952,"updatedAt":1780345724705.8857,"size":15220,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"127 — Side-by-side PhotoPrism M0 test of the branch at . Production LXC 120 keeps running on the legacy stack at until M5 cutover. At a glance - Hostname: - IP: - Privilege: unpriv - Resources: 6 cores / 8 GiB RAM / 40 G","isSymlink":false}},{"path":"containers/index.md","mtimeMs":1780560778862.5242,"size":5300,"meta":{"path":"containers/index.md","title":"index","folder":"inbox","siblingOrder":16,"createdAt":1780560778855.459,"updatedAt":1780560778862.5242,"size":5300,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"LXC containers — index All containers live on . Each row links to the per-container page. | ID | Name | IP | Priv | Cores | RAM | Disk | Mounts | Public hostname | Status | | --- | ---------------- | --------------- | --","isSymlink":false}},{"path":"hosts/hubris.md","mtimeMs":1780430511541.5146,"size":14052,"meta":{"path":"hosts/hubris.md","title":"hubris","folder":"inbox","siblingOrder":8,"createdAt":1780430511541.3574,"updatedAt":1780430511541.5146,"size":14052,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"— Proxmox host Single-node Proxmox VE running 1 VM and 13 LXC containers. The whole homelab. At a glance - Role: Proxmox VE 9.1.2 hypervisor (kernel ) - Hardware: GMKtec NucBox M6 Ultra — AMD Ryzen 5 7640HS (Phoenix APU)","isSymlink":false}},{"path":"infrastructure/auto-deploy.md","mtimeMs":1780607505150.4668,"size":12356,"meta":{"path":"infrastructure/auto-deploy.md","title":"auto-deploy","folder":"inbox","siblingOrder":0,"createdAt":1780607505144.4097,"updatedAt":1780607505150.4668,"size":12356,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Auto-deploy — gitea-webhook pipelines Several configs and apps in the lab live in repos on gitea (104) and auto-redeploy on push. All pipelines follow one of two shapes. Two shapes Shape A — checkout IS the working tree ","isSymlink":false}},{"path":"infrastructure/backups.md","mtimeMs":1780560830473.088,"size":7139,"meta":{"path":"infrastructure/backups.md","title":"backups","folder":"inbox","siblingOrder":1,"createdAt":1780560830466.1775,"updatedAt":1780560830473.088,"size":7139,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Backups — restic on external drive (DISABLED) Chunked monthly restic backup of 's irreplaceable subset. Disabled 2026-04-22 as part of the hubris crash-loop A/B test. Status DISABLED 2026-04-22. All four timers 'd: - - -","isSymlink":false}},{"path":"infrastructure/dns.md","mtimeMs":1780779020259.7522,"size":12807,"meta":{"path":"infrastructure/dns.md","title":"dns","folder":"inbox","siblingOrder":2,"createdAt":1780779020251.5957,"updatedAt":1780779020259.7522,"size":12807,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"DNS — split-horizon LAN clients resolve to the Caddy reverse proxy ( ). Public clients resolve to the IONOS VPS ( ) via an IONOS wildcard, where they hit the VPS traefik public ingress. There is no wildcard on the LAN si","isSymlink":false}},{"path":"infrastructure/homelab-context.md","mtimeMs":1780560830894.8496,"size":8047,"meta":{"path":"infrastructure/homelab-context.md","title":"homelab-context","folder":"inbox","siblingOrder":3,"createdAt":1780560830888.2087,"updatedAt":1780560830894.8496,"size":8047,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Homelab context distribution The cross-client context-and-secrets system that makes every agent (Claude Code, Hermes Agent, future MCP-capable clients) on every machine in the lab self-locating and able to read the same ","isSymlink":false}},{"path":"infrastructure/ingress.md","mtimeMs":1780607419863.8228,"size":7418,"meta":{"path":"infrastructure/ingress.md","title":"ingress","folder":"inbox","siblingOrder":4,"createdAt":1780607419858.2424,"updatedAt":1780607419863.8228,"size":7418,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Public ingress — VPS traefik + cert mirror How home services reach the open internet without exposing the home network. Two-stage pattern: traefik on the IONOS VPS terminates TLS at the public edge, then reverse-proxies ","isSymlink":false}},{"path":"infrastructure/media-permissions.md","mtimeMs":1780345724709.1672,"size":7283,"meta":{"path":"infrastructure/media-permissions.md","title":"media-permissions","folder":"inbox","siblingOrder":5,"createdAt":1780345724709.099,"updatedAt":1780345724709.1672,"size":7283,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Media permissions — GID 10000 Standard for any LXC reading/writing on hubris. Applied 2026-04-20. Standard Every LXC that mounts participates in a shared group with GID 10000. Shared subtrees are owned by that group with","isSymlink":false}},{"path":"infrastructure/mesh.md","mtimeMs":1780345724709.2966,"size":16161,"meta":{"path":"infrastructure/mesh.md","title":"mesh","folder":"inbox","siblingOrder":6,"createdAt":1780345724709.2087,"updatedAt":1780345724709.2966,"size":16161,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Mesh — Tailscale → Netbird migration The hubris fleet is migrating from Tailscale to Netbird. Netbird is the target end-state. In-progress as of 2026-04-21. Current state - PVE host uses Netbird ( , ). Its resolver is th","isSymlink":false}},{"path":"infrastructure/monitoring.md","mtimeMs":1780560749315.5925,"size":2427,"meta":{"path":"infrastructure/monitoring.md","title":"monitoring","folder":"inbox","siblingOrder":7,"createdAt":1780560749307.7988,"updatedAt":1780560749315.5925,"size":2427,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Monitoring — Hermes health watchdog Homelab health monitoring via Hermes Agent on mac-mini. Replaced the legacy + IPC pipeline on 2026-06-04. Current approach Two layers: 1. On-demand: ask Hermes \"how's the homelab?\" or ","isSymlink":false}},{"path":"infrastructure/network.md","mtimeMs":1780519747474.5557,"size":4717,"meta":{"path":"infrastructure/network.md","title":"network","folder":"inbox","siblingOrder":8,"createdAt":1780519747466.9673,"updatedAt":1780519747474.5557,"size":4717,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Network Physical and logical network topology for the homelab. Why The homelab runs on a dedicated internal subnet ( ) isolated from the main household LAN ( ). Isolation is enforced at Proxmox: LXC/VM traffic is bridged","isSymlink":false}},{"path":"infrastructure/ssh-access.md","mtimeMs":1780560830582.1829,"size":6692,"meta":{"path":"infrastructure/ssh-access.md","title":"ssh-access","folder":"inbox","siblingOrder":9,"createdAt":1780560830574.8628,"updatedAt":1780560830582.1829,"size":6692,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"SSH access How to reach every host in the fleet from any workstation, with LAN as the primary path and Netbird as the automatic backup. Architecture SSH access relies on three layers: 1. Homelab inventory ( ) — the singl","isSymlink":false}},{"path":"infrastructure/vps-hardening.md","mtimeMs":1780345724709.625,"size":6246,"meta":{"path":"infrastructure/vps-hardening.md","title":"vps-hardening","folder":"inbox","siblingOrder":10,"createdAt":1780345724709.56,"updatedAt":1780345724709.625,"size":6246,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"VPS hardening — / IONOS VPS that runs the Netbird control plane and the public ingress traefik. Hardened 2026-04-23 from its stock-Plesk state. At a glance - Hostname: - OS: Debian 13 - Mesh: netbird (peer of the lab mes","isSymlink":false}},{"path":"investigations/2026-04-21-hubris-crash-loop.md","mtimeMs":1780345724709.907,"size":9313,"meta":{"path":"investigations/2026-04-21-hubris-crash-loop.md","title":"2026-04-21-hubris-crash-loop","folder":"inbox","siblingOrder":0,"createdAt":1780345724709.8374,"updatedAt":1780345724709.907,"size":9313,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-04-21 — Hubris crash loop (thermal + USB drive) Summary hard-locked repeatedly on 2026-04-21 (silent CPU hangs, no panic, no OOM, no MCE). Two contributors identified: idle CPU sitting at 95 °C on the governor, and ","isSymlink":false}},{"path":"investigations/2026-05-31-authentik-vps-migration.md","mtimeMs":1780682878779.1663,"size":10574,"meta":{"path":"investigations/2026-05-31-authentik-vps-migration.md","title":"2026-05-31-authentik-vps-migration","folder":"inbox","siblingOrder":1,"createdAt":1780682878770.9727,"updatedAt":1780682878779.1663,"size":10574,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-05-31 — Authentik migrated from LXC 124 to the VPS Summary The NetBird management server (on the VPS) crash-looped 1200+ times because it fetches the Authentik OIDC discovery document on startup, and Authentik was o","isSymlink":false}},{"path":"investigations/2026-06-01-mac-mini-onboarding.md","mtimeMs":1780352998861.152,"size":10453,"meta":{"path":"investigations/2026-06-01-mac-mini-onboarding.md","title":"2026-06-01-mac-mini-onboarding","folder":"inbox","siblingOrder":2,"createdAt":1780352998852.268,"updatedAt":1780352998861.152,"size":10453,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"mac-mini onboarding — post-mortem & lessons learned Onboarded the workstation (macOS Sequoia, arm64) into the hubris homelab context system with the profile. What follows is a chronological recap of every hitch, the fix,","isSymlink":false}},{"path":"investigations/2026-06-03-moonlight-sunshine-wifi-jitter.md","mtimeMs":1780603450911.2507,"size":4835,"meta":{"path":"investigations/2026-06-03-moonlight-sunshine-wifi-jitter.md","title":"2026-06-03-moonlight-sunshine-wifi-jitter","folder":"inbox","siblingOrder":3,"createdAt":1780603450904.6553,"updatedAt":1780603450911.2507,"size":4835,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-06-03 — Moonlight/Sunshine game streaming unstable over WiFi Summary runs Sunshine as the game-streaming server; runs Moonlight as the client. Despite both machines being on the same physical subnet (192.168.178.0/2","isSymlink":false}},{"path":"investigations/2026-06-06-authentik-session-lifetime.md","mtimeMs":1780782295099.0022,"size":5395,"meta":{"path":"investigations/2026-06-06-authentik-session-lifetime.md","title":"2026-06-06-authentik-session-lifetime","folder":"inbox","siblingOrder":4,"createdAt":1780782295097.0544,"updatedAt":1780782295099.0022,"size":5395,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-06-06 — Frequent Authentik login prompts fixed (session duration) Summary User needed to re-authenticate to Authentik several times per day. Root cause was the Django session being configured as a session cookie (cl","isSymlink":false}},{"path":"investigations/2026-06-06-caddyfile-truncation.md","mtimeMs":1780779049721.1035,"size":3404,"meta":{"path":"investigations/2026-06-06-caddyfile-truncation.md","title":"2026-06-06-caddyfile-truncation","folder":"inbox","siblingOrder":5,"createdAt":1780779049719.0457,"updatedAt":1780779049721.1035,"size":3404,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Investigation: Caddyfile truncation — all LAN services down (2026-06-06) Date: 2026-06-06 Status: resolved Duration: 10 hours (from last known good state 12:39 UTC to restoration 22:40 UTC) Symptom All URLs except and re","isSymlink":false}},{"path":"investigations/index.md","mtimeMs":1780782305966.2124,"size":1462,"meta":{"path":"investigations/index.md","title":"index","folder":"inbox","siblingOrder":6,"createdAt":1780782305957.9714,"updatedAt":1780782305966.2124,"size":1462,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Investigations Time-stamped incident reports and experiments. One entry per incident; the entry is the canonical source. Per-node changelog entries link back here. Index | Date | Title | Status | | ------------ | -------","isSymlink":false}},{"path":"operations/agent-enrollment.md","mtimeMs":1780352899324.4644,"size":20327,"meta":{"path":"operations/agent-enrollment.md","title":"agent-enrollment","folder":"inbox","siblingOrder":0,"createdAt":1780352899317.3433,"updatedAt":1780352899324.4644,"size":20327,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Agent enrollment — bootstrap a client into the homelab context system This walks through enrolling a new machine (workstation, LXC, or VM) so it joins the cross-client context system: a clone of this repo that auto-syncs","isSymlink":false}},{"path":"operations/commands.md","mtimeMs":1780748225789.4978,"size":4717,"meta":{"path":"operations/commands.md","title":"commands","folder":"inbox","siblingOrder":1,"createdAt":1780748225782.4604,"updatedAt":1780748225789.4978,"size":4717,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Operations cheatsheet Run from the hubris host as root. When working from on Linux you're already on hubris — don't / . Proxmox CLI | Command | Use | | --- | --- | | / | List LXC containers / VMs | | / | Container / VM c","isSymlink":false}},{"path":"operations/hermes-agent.md","mtimeMs":1780353006683.7876,"size":9974,"meta":{"path":"operations/hermes-agent.md","title":"hermes-agent","folder":"inbox","siblingOrder":2,"createdAt":1780353006675.6958,"updatedAt":1780353006683.7876,"size":9974,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Hermes agent — Nous-Hermes-powered Goose sessions on a homelab client Onboards Nous Research's Hermes (a fine-tuned Llama variant) as a working terminal agent on a homelab client. Builds on top of standard client enrollm","isSymlink":false}},{"path":"operations/runbook-dpkg-interrupted.md","mtimeMs":1780345724711.7874,"size":4106,"meta":{"path":"operations/runbook-dpkg-interrupted.md","title":"runbook-dpkg-interrupted","folder":"inbox","siblingOrder":3,"createdAt":1780345724711.7278,"updatedAt":1780345724711.7874,"size":4106,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Runbook — recover from dpkg-interrupted state You're here because an apt run got killed mid-transaction and the target now has packages that are unpacked but not configured. Symptoms: - refuses to do anything new: `Error","isSymlink":false}},{"path":"plans/2026-06-01-slate-ax-to-sodola-migration.md","mtimeMs":1780428851172.3645,"size":5150,"meta":{"path":"plans/2026-06-01-slate-ax-to-sodola-migration.md","title":"2026-06-01-slate-ax-to-sodola-migration","folder":"inbox","siblingOrder":0,"createdAt":1780428851172.1816,"updatedAt":1780428851172.3645,"size":5150,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-06-01 — Slate AX → SODOLA Migration Status: Done — 2026-06-02 Hardware: SODOLA 5-Port 2.5Gbit Managed Switch replacing GL.iNet Slate AX Router: Fritz!Box 7590 Goal Remove the Slate AX sub-router. It adds double-NAT,","isSymlink":false}},{"path":"plans/2026-06-04_130000-deprecate-claudio-bot.md","mtimeMs":1780560132354.6191,"size":16425,"meta":{"path":"plans/2026-06-04_130000-deprecate-claudio-bot.md","title":"2026-06-04_130000-deprecate-claudio-bot","folder":"inbox","siblingOrder":1,"createdAt":1780560132346.9568,"updatedAt":1780560132354.6191,"size":16425,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"Deprecate claudio-bot (LXC 123) — Hermes Agent now serves as control plane Goal Phase out the claudio-bot ecosystem (LXC 123, claudio-monitor, IPC server) now that Hermes Agent is configured and running on mac-mini. Herm","isSymlink":false}},{"path":"plans/index.md","mtimeMs":1780428855320.4988,"size":839,"meta":{"path":"plans/index.md","title":"index","folder":"inbox","siblingOrder":2,"createdAt":1780428855320.358,"updatedAt":1780428855320.4988,"size":839,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Plans Pre-flight runbooks for planned changes that haven't happened yet. Once executed, move the outcome to (if anything interesting happened) or just a changelog entry on the affected node pages. Index | Date | Title | ","isSymlink":false}},{"path":"secrets/README.md","mtimeMs":1780345724713.5586,"size":2088,"meta":{"path":"secrets/README.md","title":"README","folder":"inbox","siblingOrder":0,"createdAt":1780345724713.4932,"updatedAt":1780345724713.5586,"size":2088,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"secrets/ SOPS-encrypted YAML files. The plaintext lives only in transit and in the operator's head — committed files are always ciphertext. Conventions - One file per logical grouping (e.g. , , ). - Recipients are declar","isSymlink":false}},{"path":"vms/100-zimaos.md","mtimeMs":1780520488274.1562,"size":11160,"meta":{"path":"vms/100-zimaos.md","title":"100-zimaos","folder":"inbox","siblingOrder":0,"createdAt":1780520488267.3223,"updatedAt":1780520488274.1562,"size":11160,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"100 — ZimaOS (IceWhale / CasaOS-family NAS distro), installed as a Proxmox VM to evaluate it as a potential primary NAS frontend in front of — alongside the existing fleet (nextcloud (114), jellyfin (101), mule-images (1","isSymlink":false}},{"path":"vms/108-haos.md","mtimeMs":1780345724714.3467,"size":2017,"meta":{"path":"vms/108-haos.md","title":"108-haos","folder":"inbox","siblingOrder":1,"createdAt":1780345724714.2927,"updatedAt":1780345724714.3467,"size":2017,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"108 — Home Assistant OS — the only VM on hubris (HAOS doesn't run cleanly in an LXC, hence the qm tenant). At a glance - Type: QEMU VM - HAOS version: 16.3 (last verified) - IP: - Resources: 4 GiB RAM, 32 GiB boot disk -","isSymlink":false}}]} +{"version":1,"entries":[{"path":"AGENTS.md","mtimeMs":1782077981774.8025,"size":5175,"meta":{"path":"AGENTS.md","title":"AGENTS","folder":"inbox","siblingOrder":7,"createdAt":1782077981774.6897,"updatedAt":1782077981774.8025,"size":5175,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"AGENTS.md — orientation for any agent on a homelab client You are running on a machine that is part of the hubris homelab. The full context is in this checkout at . This file is the entry point. Read it once at start, th","isSymlink":false}},{"path":"CAVEMAN.md","mtimeMs":1782077981774.9321,"size":1535,"meta":{"path":"CAVEMAN.md","title":"CAVEMAN","folder":"inbox","siblingOrder":8,"createdAt":1782077981774.8496,"updatedAt":1782077981774.9321,"size":1535,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"CAVEMAN.md — communication mode for homelab agents Respond terse like smart caveman. All technical substance stay. Only fluff die. Rules Drop: articles (a/an/the), filler (just/really/basically/actually/simply), pleasant","isSymlink":false}},{"path":"CONTRIBUTING.md","mtimeMs":1780346816514.084,"size":2674,"meta":{"path":"CONTRIBUTING.md","title":"CONTRIBUTING","folder":"inbox","siblingOrder":9,"createdAt":1780346816513.5295,"updatedAt":1780346816514.084,"size":2674,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"Contributing to the Homelab Wiki Voice Concise, technical, sysadmin-to-sysadmin. No marketing prose, no exclamation marks. Page templates Container page ( ) Cross-cutting page ( ) Plan ( ) Investigation ( ) Linking disci"}},{"path":"HERMES.md","mtimeMs":1780354337315.819,"size":3101,"meta":{"path":"HERMES.md","title":"HERMES","folder":"inbox","siblingOrder":10,"createdAt":1780354337308.1587,"updatedAt":1780354337315.819,"size":3101,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"HERMES.md — Agent persona for homelab clients This file is the canonical agent persona for all AI agents running on machines in the hubris homelab. It prescribes behaviour, token-efficiency conventions, and the source-of"}},{"path":"README.md","mtimeMs":1780560778432.5747,"size":4930,"meta":{"path":"README.md","title":"README","folder":"inbox","siblingOrder":11,"createdAt":1780560778426.7786,"updatedAt":1780560778432.5747,"size":4930,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Homelab Wiki — Living documentation for the hubris Proxmox homelab. Every node, every cross-cutting system, and every meaningful incident is its own page; pages are linked so you can start anywhere and walk the graph. La"}},{"path":"containers/101-jellyfin.md","mtimeMs":1780345724703.8516,"size":1501,"meta":{"path":"containers/101-jellyfin.md","title":"101-jellyfin","folder":"inbox","siblingOrder":0,"createdAt":1780345724703.7935,"updatedAt":1780345724703.8516,"size":1501,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"101 — Media server: serves the movies / TV / anime / music / audiobooks / podcasts libraries from to LAN clients. At a glance - Hostname: - IP: - Privilege: unprivileged + idmap (so it can write to the group on ) - Resou"}},{"path":"containers/102-nfs-export.md","mtimeMs":1780345724703.9788,"size":6678,"meta":{"path":"containers/102-nfs-export.md","title":"102-nfs-export","folder":"inbox","siblingOrder":1,"createdAt":1780345724703.8984,"updatedAt":1780345724703.9788,"size":6678,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"102 — Dedicated, single-purpose LXC that re-exports over NFSv4 to clients that can't use the host's PVE virtiofs path — currently only 100-zimaos, which ships a kernel without virtiofs support. At a glance - Hostname: - "}},{"path":"containers/103-paperless.md","mtimeMs":1780560805423.0337,"size":1924,"meta":{"path":"containers/103-paperless.md","title":"103-paperless","folder":"inbox","siblingOrder":2,"createdAt":1780560805416.4663,"updatedAt":1780560805423.0337,"size":1924,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"103 — Paperless-ngx for document management. Ingests scans / PDFs from and serves OCR'd indexed copies. At a glance - Hostname: - IP: - Privilege: privileged - Resources: 2 cores / 3 GiB RAM / 8 GiB rootfs - Mounts: ↔ (c"}},{"path":"containers/104-gitea.md","mtimeMs":1780345724704.2058,"size":3905,"meta":{"path":"containers/104-gitea.md","title":"104-gitea","folder":"inbox","siblingOrder":3,"createdAt":1780345724704.1404,"updatedAt":1780345724704.2058,"size":3905,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"104 — Self-hosted git server. Source of truth for all repositories that auto-deploy across the lab. At a glance - Hostname: - IP: - Privilege: privileged - Resources: 1 core / 1 GiB RAM / 8 GiB rootfs - Mounts: ↔ (under "}},{"path":"containers/105-apps.md","mtimeMs":1780352727930.0833,"size":10839,"meta":{"path":"containers/105-apps.md","title":"105-apps","folder":"inbox","siblingOrder":4,"createdAt":1780352727923.2222,"updatedAt":1780352727930.0833,"size":10839,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"105 — Docker host for everything that doesn't justify its own LXC. Currently runs Artifacto, Booklore, PlantUML server, Portainer (and historically WriteFreely / blog), plus the homelab-context distribution services (MCP"}},{"path":"containers/106-auth-outpost.md","mtimeMs":1780782336629.5935,"size":5011,"meta":{"path":"containers/106-auth-outpost.md","title":"106-auth-outpost","folder":"inbox","siblingOrder":5,"createdAt":1780782336621.4434,"updatedAt":1780782336629.5935,"size":5011,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"106 — Authentik forward-auth outpost for LAN-gated apps. A stateless proxy that connects outbound to the VPS Authentik core and serves forward-auth locally, so Caddy (121) never hairpins auth through VPS Traefik. At a gl"}},{"path":"containers/107-dns.md","mtimeMs":1780779036582.4163,"size":5515,"meta":{"path":"containers/107-dns.md","title":"107-dns","folder":"inbox","siblingOrder":6,"createdAt":1780779036572.9216,"updatedAt":1780779036582.4163,"size":5515,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"107 — Homelab DNS server (Technitium). Replaces the dnsmasq that lived on 124 — authentik; single-purpose, one job. At a glance - Hostname: - IP: (static — stable, decoupled from any app) - Privilege: privileged (Docker-"}},{"path":"containers/114-nextcloud.md","mtimeMs":1780345724704.6995,"size":8636,"meta":{"path":"containers/114-nextcloud.md","title":"114-nextcloud","folder":"inbox","siblingOrder":7,"createdAt":1780345724704.615,"updatedAt":1780345724704.6995,"size":8636,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"114 — Personal cloud / file collaboration. Source-of-truth for the photo libraries surfaced by mulita (120). At a glance - Hostname: - IP: - Privilege: privileged - Resources: 4 cores / 6 GiB RAM / 25 GiB rootfs - Mounts"}},{"path":"containers/118-elementsynapse.md","mtimeMs":1780778973248.468,"size":6368,"meta":{"path":"containers/118-elementsynapse.md","title":"118-elementsynapse","folder":"inbox","siblingOrder":8,"createdAt":1780778973241.1172,"updatedAt":1780778973248.468,"size":6368,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"118 — Matrix homeserver (Synapse). Backs . At a glance - Hostname: - IP: - Privilege: unprivileged - Resources: 1 core / 2 GiB RAM / 16 GiB rootfs (grown from 8 GiB on 2026-05-15 after disk-full incident) - Mounts: none "}},{"path":"containers/119-sophia.md","mtimeMs":1780345724704.9253,"size":752,"meta":{"path":"containers/119-sophia.md","title":"119-sophia","folder":"inbox","siblingOrder":9,"createdAt":1780345724704.8606,"updatedAt":1780345724704.9253,"size":752,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"119 — Single-container workload \"sophia\". Reads/writes under . At a glance - Hostname: - IP: - Privilege: privileged - Resources: 2 cores / 1 GiB RAM / 10 GiB rootfs - Mounts: ↔ - Public hostname: none Permissions LXC ha"}},{"path":"containers/120-mule-images.md","mtimeMs":1780345724705.116,"size":40719,"meta":{"path":"containers/120-mule-images.md","title":"120-mule-images","folder":"inbox","siblingOrder":10,"createdAt":1780345724704.9697,"updatedAt":1780345724705.116,"size":40719,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"120 — Hosts — the photos app at . PhotoPrism + Go sidecar + SvelteKit, replacing the legacy FastAPI/Celery stack as of 2026-05-22 (see Changelog). Auto-deploys from on . At a glance - Hostname: - IP: - Privilege: privile"}},{"path":"containers/121-caddy.md","mtimeMs":1781344617107.1443,"size":7222,"meta":{"path":"containers/121-caddy.md","title":"121-caddy","folder":"inbox","siblingOrder":11,"createdAt":1781344617100.2546,"updatedAt":1781344617107.1443,"size":7222,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"121 — The reverse proxy. Terminates TLS for every hostname on the LAN/mesh and forwards to the right backend. At a glance - Hostname: - IP: - Privilege: unprivileged - Resources: 1 core / 512 MiB RAM / 6 GiB rootfs - Mou"}},{"path":"containers/122-arriman.md","mtimeMs":1781344598212.5852,"size":10156,"meta":{"path":"containers/122-arriman.md","title":"122-arriman","folder":"inbox","siblingOrder":12,"createdAt":1781344598204.7722,"updatedAt":1781344598212.5852,"size":10156,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"122 — Docker host running the \\arr stack via compose. Replaced the old yunohost-based LXC 100 on 2026-04-21. At a glance - Hostname: - IP: - Privilege: privileged - Resources: 4 cores / 8 GiB RAM / 24 GiB rootfs - Mounts"}},{"path":"containers/123-claudio-bot.md","mtimeMs":1780560778655.496,"size":4318,"meta":{"path":"containers/123-claudio-bot.md","title":"123-claudio-bot","folder":"inbox","siblingOrder":13,"createdAt":1780560778648.8645,"updatedAt":1780560778655.496,"size":4318,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"123 — (DEPRECATED — destroyed 2026-06-04) This LXC was destroyed on 2026-06-04. Replaced by Hermes Agent on mac-mini. Monitoring migrated to skill + 15-min Hermes cronjob. Repos and archived (read-only) on Gitea. See dep"}},{"path":"containers/126-plato.md","mtimeMs":1780345724705.7505,"size":5515,"meta":{"path":"containers/126-plato.md","title":"126-plato","folder":"inbox","siblingOrder":14,"createdAt":1780345724705.6843,"updatedAt":1780345724705.7505,"size":5515,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"126 — Docker host for Plato — a cross-linked notes workspace (SvelteKit SPA embedded into a Go HTTP server, SQLite-backed). LAN+mesh only, no public ingress. At a glance - Hostname: - IP: - Privilege: privileged - Resour"}},{"path":"containers/127-mule-photos-new.md","mtimeMs":1780345724705.8857,"size":15220,"meta":{"path":"containers/127-mule-photos-new.md","title":"127-mule-photos-new","folder":"inbox","siblingOrder":15,"createdAt":1780345724705.7952,"updatedAt":1780345724705.8857,"size":15220,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"127 — Side-by-side PhotoPrism M0 test of the branch at . Production LXC 120 keeps running on the legacy stack at until M5 cutover. At a glance - Hostname: - IP: - Privilege: unpriv - Resources: 6 cores / 8 GiB RAM / 40 G"}},{"path":"containers/index.md","mtimeMs":1780560778862.5242,"size":5300,"meta":{"path":"containers/index.md","title":"index","folder":"inbox","siblingOrder":16,"createdAt":1780560778855.459,"updatedAt":1780560778862.5242,"size":5300,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"LXC containers — index All containers live on . Each row links to the per-container page. | ID | Name | IP | Priv | Cores | RAM | Disk | Mounts | Public hostname | Status | | --- | ---------------- | --------------- | --"}},{"path":"hosts/hubris.md","mtimeMs":1780430511541.5146,"size":14052,"meta":{"path":"hosts/hubris.md","title":"hubris","folder":"inbox","siblingOrder":10,"createdAt":1780430511541.3574,"updatedAt":1780430511541.5146,"size":14052,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"— Proxmox host Single-node Proxmox VE running 1 VM and 13 LXC containers. The whole homelab. At a glance - Role: Proxmox VE 9.1.2 hypervisor (kernel ) - Hardware: GMKtec NucBox M6 Ultra — AMD Ryzen 5 7640HS (Phoenix APU)"}},{"path":"infrastructure/auto-deploy.md","mtimeMs":1780607505150.4668,"size":12356,"meta":{"path":"infrastructure/auto-deploy.md","title":"auto-deploy","folder":"inbox","siblingOrder":0,"createdAt":1780607505144.4097,"updatedAt":1780607505150.4668,"size":12356,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Auto-deploy — gitea-webhook pipelines Several configs and apps in the lab live in repos on gitea (104) and auto-redeploy on push. All pipelines follow one of two shapes. Two shapes Shape A — checkout IS the working tree "}},{"path":"infrastructure/backups.md","mtimeMs":1780560830473.088,"size":7139,"meta":{"path":"infrastructure/backups.md","title":"backups","folder":"inbox","siblingOrder":1,"createdAt":1780560830466.1775,"updatedAt":1780560830473.088,"size":7139,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Backups — restic on external drive (DISABLED) Chunked monthly restic backup of 's irreplaceable subset. Disabled 2026-04-22 as part of the hubris crash-loop A/B test. Status DISABLED 2026-04-22. All four timers 'd: - - -"}},{"path":"infrastructure/dns.md","mtimeMs":1781736008617.1628,"size":13044,"meta":{"path":"infrastructure/dns.md","title":"dns","folder":"inbox","siblingOrder":2,"createdAt":1781736008610.1042,"updatedAt":1781736008617.1628,"size":13044,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"DNS — split-horizon LAN clients resolve to the Caddy reverse proxy ( ). Public clients resolve to the IONOS VPS ( ) via an IONOS wildcard, where they hit the VPS traefik public ingress. There is no wildcard on the LAN si","isSymlink":false}},{"path":"infrastructure/homelab-context.md","mtimeMs":1780560830894.8496,"size":8047,"meta":{"path":"infrastructure/homelab-context.md","title":"homelab-context","folder":"inbox","siblingOrder":3,"createdAt":1780560830888.2087,"updatedAt":1780560830894.8496,"size":8047,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Homelab context distribution The cross-client context-and-secrets system that makes every agent (Claude Code, Hermes Agent, future MCP-capable clients) on every machine in the lab self-locating and able to read the same "}},{"path":"infrastructure/ingress.md","mtimeMs":1780607419863.8228,"size":7418,"meta":{"path":"infrastructure/ingress.md","title":"ingress","folder":"inbox","siblingOrder":4,"createdAt":1780607419858.2424,"updatedAt":1780607419863.8228,"size":7418,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Public ingress — VPS traefik + cert mirror How home services reach the open internet without exposing the home network. Two-stage pattern: traefik on the IONOS VPS terminates TLS at the public edge, then reverse-proxies "}},{"path":"infrastructure/media-permissions.md","mtimeMs":1780345724709.1672,"size":7283,"meta":{"path":"infrastructure/media-permissions.md","title":"media-permissions","folder":"inbox","siblingOrder":5,"createdAt":1780345724709.099,"updatedAt":1780345724709.1672,"size":7283,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Media permissions — GID 10000 Standard for any LXC reading/writing on hubris. Applied 2026-04-20. Standard Every LXC that mounts participates in a shared group with GID 10000. Shared subtrees are owned by that group with"}},{"path":"infrastructure/mesh.md","mtimeMs":1780345724709.2966,"size":16161,"meta":{"path":"infrastructure/mesh.md","title":"mesh","folder":"inbox","siblingOrder":6,"createdAt":1780345724709.2087,"updatedAt":1780345724709.2966,"size":16161,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Mesh — Tailscale → Netbird migration The hubris fleet is migrating from Tailscale to Netbird. Netbird is the target end-state. In-progress as of 2026-04-21. Current state - PVE host uses Netbird ( , ). Its resolver is th"}},{"path":"infrastructure/monitoring.md","mtimeMs":1780560749315.5925,"size":2427,"meta":{"path":"infrastructure/monitoring.md","title":"monitoring","folder":"inbox","siblingOrder":7,"createdAt":1780560749307.7988,"updatedAt":1780560749315.5925,"size":2427,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Monitoring — Hermes health watchdog Homelab health monitoring via Hermes Agent on mac-mini. Replaced the legacy + IPC pipeline on 2026-06-04. Current approach Two layers: 1. On-demand: ask Hermes \"how's the homelab?\" or "}},{"path":"infrastructure/network.md","mtimeMs":1781735999883.6902,"size":4996,"meta":{"path":"infrastructure/network.md","title":"network","folder":"inbox","siblingOrder":8,"createdAt":1781735999876.1707,"updatedAt":1781735999883.6902,"size":4996,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Network Physical and logical network topology for the homelab. Why The homelab runs on a dedicated internal subnet ( ) isolated from the main household LAN ( ). Isolation is enforced at Proxmox: LXC/VM traffic is bridged","isSymlink":false}},{"path":"infrastructure/ssh-access.md","mtimeMs":1780560830582.1829,"size":6692,"meta":{"path":"infrastructure/ssh-access.md","title":"ssh-access","folder":"inbox","siblingOrder":9,"createdAt":1780560830574.8628,"updatedAt":1780560830582.1829,"size":6692,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"SSH access How to reach every host in the fleet from any workstation, with LAN as the primary path and Netbird as the automatic backup. Architecture SSH access relies on three layers: 1. Homelab inventory ( ) — the singl"}},{"path":"infrastructure/vps-hardening.md","mtimeMs":1780345724709.625,"size":6246,"meta":{"path":"infrastructure/vps-hardening.md","title":"vps-hardening","folder":"inbox","siblingOrder":10,"createdAt":1780345724709.56,"updatedAt":1780345724709.625,"size":6246,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"VPS hardening — / IONOS VPS that runs the Netbird control plane and the public ingress traefik. Hardened 2026-04-23 from its stock-Plesk state. At a glance - Hostname: - OS: Debian 13 - Mesh: netbird (peer of the lab mes"}},{"path":"investigations/2026-04-21-hubris-crash-loop.md","mtimeMs":1780345724709.907,"size":9313,"meta":{"path":"investigations/2026-04-21-hubris-crash-loop.md","title":"2026-04-21-hubris-crash-loop","folder":"inbox","siblingOrder":0,"createdAt":1780345724709.8374,"updatedAt":1780345724709.907,"size":9313,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-04-21 — Hubris crash loop (thermal + USB drive) Summary hard-locked repeatedly on 2026-04-21 (silent CPU hangs, no panic, no OOM, no MCE). Two contributors identified: idle CPU sitting at 95 °C on the governor, and "}},{"path":"investigations/2026-05-31-authentik-vps-migration.md","mtimeMs":1780682878779.1663,"size":10574,"meta":{"path":"investigations/2026-05-31-authentik-vps-migration.md","title":"2026-05-31-authentik-vps-migration","folder":"inbox","siblingOrder":1,"createdAt":1780682878770.9727,"updatedAt":1780682878779.1663,"size":10574,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-05-31 — Authentik migrated from LXC 124 to the VPS Summary The NetBird management server (on the VPS) crash-looped 1200+ times because it fetches the Authentik OIDC discovery document on startup, and Authentik was o"}},{"path":"investigations/2026-06-01-mac-mini-onboarding.md","mtimeMs":1780352998861.152,"size":10453,"meta":{"path":"investigations/2026-06-01-mac-mini-onboarding.md","title":"2026-06-01-mac-mini-onboarding","folder":"inbox","siblingOrder":2,"createdAt":1780352998852.268,"updatedAt":1780352998861.152,"size":10453,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"mac-mini onboarding — post-mortem & lessons learned Onboarded the workstation (macOS Sequoia, arm64) into the hubris homelab context system with the profile. What follows is a chronological recap of every hitch, the fix,"}},{"path":"investigations/2026-06-03-moonlight-sunshine-wifi-jitter.md","mtimeMs":1780603450911.2507,"size":4835,"meta":{"path":"investigations/2026-06-03-moonlight-sunshine-wifi-jitter.md","title":"2026-06-03-moonlight-sunshine-wifi-jitter","folder":"inbox","siblingOrder":3,"createdAt":1780603450904.6553,"updatedAt":1780603450911.2507,"size":4835,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-06-03 — Moonlight/Sunshine game streaming unstable over WiFi Summary runs Sunshine as the game-streaming server; runs Moonlight as the client. Despite both machines being on the same physical subnet (192.168.178.0/2"}},{"path":"investigations/2026-06-06-authentik-session-lifetime.md","mtimeMs":1780782295099.0022,"size":5395,"meta":{"path":"investigations/2026-06-06-authentik-session-lifetime.md","title":"2026-06-06-authentik-session-lifetime","folder":"inbox","siblingOrder":4,"createdAt":1780782295097.0544,"updatedAt":1780782295099.0022,"size":5395,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-06-06 — Frequent Authentik login prompts fixed (session duration) Summary User needed to re-authenticate to Authentik several times per day. Root cause was the Django session being configured as a session cookie (cl"}},{"path":"investigations/2026-06-06-caddyfile-truncation.md","mtimeMs":1780779049721.1035,"size":3404,"meta":{"path":"investigations/2026-06-06-caddyfile-truncation.md","title":"2026-06-06-caddyfile-truncation","folder":"inbox","siblingOrder":5,"createdAt":1780779049719.0457,"updatedAt":1780779049721.1035,"size":3404,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Investigation: Caddyfile truncation — all LAN services down (2026-06-06) Date: 2026-06-06 Status: resolved Duration: 10 hours (from last known good state 12:39 UTC to restoration 22:40 UTC) Symptom All URLs except and re"}},{"path":"investigations/index.md","mtimeMs":1780782305966.2124,"size":1462,"meta":{"path":"investigations/index.md","title":"index","folder":"inbox","siblingOrder":6,"createdAt":1780782305957.9714,"updatedAt":1780782305966.2124,"size":1462,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Investigations Time-stamped incident reports and experiments. One entry per incident; the entry is the canonical source. Per-node changelog entries link back here. Index | Date | Title | Status | | ------------ | -------"}},{"path":"operations/agent-enrollment.md","mtimeMs":1780352899324.4644,"size":20327,"meta":{"path":"operations/agent-enrollment.md","title":"agent-enrollment","folder":"inbox","siblingOrder":0,"createdAt":1780352899317.3433,"updatedAt":1780352899324.4644,"size":20327,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Agent enrollment — bootstrap a client into the homelab context system This walks through enrolling a new machine (workstation, LXC, or VM) so it joins the cross-client context system: a clone of this repo that auto-syncs"}},{"path":"operations/commands.md","mtimeMs":1780748225789.4978,"size":4717,"meta":{"path":"operations/commands.md","title":"commands","folder":"inbox","siblingOrder":1,"createdAt":1780748225782.4604,"updatedAt":1780748225789.4978,"size":4717,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Operations cheatsheet Run from the hubris host as root. When working from on Linux you're already on hubris — don't / . Proxmox CLI | Command | Use | | --- | --- | | / | List LXC containers / VMs | | / | Container / VM c"}},{"path":"operations/hermes-agent.md","mtimeMs":1780353006683.7876,"size":9974,"meta":{"path":"operations/hermes-agent.md","title":"hermes-agent","folder":"inbox","siblingOrder":2,"createdAt":1780353006675.6958,"updatedAt":1780353006683.7876,"size":9974,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Hermes agent — Nous-Hermes-powered Goose sessions on a homelab client Onboards Nous Research's Hermes (a fine-tuned Llama variant) as a working terminal agent on a homelab client. Builds on top of standard client enrollm"}},{"path":"operations/runbook-dpkg-interrupted.md","mtimeMs":1780345724711.7874,"size":4106,"meta":{"path":"operations/runbook-dpkg-interrupted.md","title":"runbook-dpkg-interrupted","folder":"inbox","siblingOrder":3,"createdAt":1780345724711.7278,"updatedAt":1780345724711.7874,"size":4106,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Runbook — recover from dpkg-interrupted state You're here because an apt run got killed mid-transaction and the target now has packages that are unpacked but not configured. Symptoms: - refuses to do anything new: `Error"}},{"path":"plans/2026-06-01-slate-ax-to-sodola-migration.md","mtimeMs":1780428851172.3645,"size":5150,"meta":{"path":"plans/2026-06-01-slate-ax-to-sodola-migration.md","title":"2026-06-01-slate-ax-to-sodola-migration","folder":"inbox","siblingOrder":0,"createdAt":1780428851172.1816,"updatedAt":1780428851172.3645,"size":5150,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"2026-06-01 — Slate AX → SODOLA Migration Status: Done — 2026-06-02 Hardware: SODOLA 5-Port 2.5Gbit Managed Switch replacing GL.iNet Slate AX Router: Fritz!Box 7590 Goal Remove the Slate AX sub-router. It adds double-NAT,"}},{"path":"plans/2026-06-04_130000-deprecate-claudio-bot.md","mtimeMs":1780560132354.6191,"size":16425,"meta":{"path":"plans/2026-06-04_130000-deprecate-claudio-bot.md","title":"2026-06-04_130000-deprecate-claudio-bot","folder":"inbox","siblingOrder":1,"createdAt":1780560132346.9568,"updatedAt":1780560132354.6191,"size":16425,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"Deprecate claudio-bot (LXC 123) — Hermes Agent now serves as control plane Goal Phase out the claudio-bot ecosystem (LXC 123, claudio-monitor, IPC server) now that Hermes Agent is configured and running on mac-mini. Herm"}},{"path":"plans/index.md","mtimeMs":1780428855320.4988,"size":839,"meta":{"path":"plans/index.md","title":"index","folder":"inbox","siblingOrder":2,"createdAt":1780428855320.358,"updatedAt":1780428855320.4988,"size":839,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"Plans Pre-flight runbooks for planned changes that haven't happened yet. Once executed, move the outcome to (if anything interesting happened) or just a changelog entry on the affected node pages. Index | Date | Title | "}},{"path":"secrets/README.md","mtimeMs":1780345724713.5586,"size":2088,"meta":{"path":"secrets/README.md","title":"README","folder":"inbox","siblingOrder":0,"createdAt":1780345724713.4932,"updatedAt":1780345724713.5586,"size":2088,"tags":[],"wikilinks":[],"hasAttachments":false,"excerpt":"secrets/ SOPS-encrypted YAML files. The plaintext lives only in transit and in the operator's head — committed files are always ciphertext. Conventions - One file per logical grouping (e.g. , , ). - Recipients are declar"}},{"path":"vms/100-zimaos.md","mtimeMs":1780520488274.1562,"size":11160,"meta":{"path":"vms/100-zimaos.md","title":"100-zimaos","folder":"inbox","siblingOrder":0,"createdAt":1780520488267.3223,"updatedAt":1780520488274.1562,"size":11160,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"100 — ZimaOS (IceWhale / CasaOS-family NAS distro), installed as a Proxmox VM to evaluate it as a potential primary NAS frontend in front of — alongside the existing fleet (nextcloud (114), jellyfin (101), mule-images (1"}},{"path":"vms/108-haos.md","mtimeMs":1780345724714.3467,"size":2017,"meta":{"path":"vms/108-haos.md","title":"108-haos","folder":"inbox","siblingOrder":1,"createdAt":1780345724714.2927,"updatedAt":1780345724714.3467,"size":2017,"tags":[],"wikilinks":[],"hasAttachments":true,"excerpt":"108 — Home Assistant OS — the only VM on hubris (HAOS doesn't run cleanly in an LXC, hence the qm tenant). At a glance - Type: QEMU VM - HAOS version: 16.3 (last verified) - IP: - Resources: 4 GiB RAM, 32 GiB boot disk -"}}]} diff --git a/containers/129-house.md b/containers/129-house.md new file mode 100644 index 0000000..8c2a54a --- /dev/null +++ b/containers/129-house.md @@ -0,0 +1,48 @@ +# 129 — `house` + +Yuvomi family planner (formerly Oikos). Self-hosted family planner with 14 modules: calendar, tasks, meals, groceries, budget, documents, notes, contacts, birthdays, housekeeping, recipes, reminders. + +## At a glance + +- **Hostname:** `house` +- **IP:** `192.168.8.212` (static) +- **Privilege:** unprivileged +- **Resources:** 1 core / 1344 MiB RAM / 8 GiB rootfs (Debian 13) +- **Mounts:** none +- **Public hostname:** [`house.hubris.network`](../infrastructure/ingress.md) → VPS traefik → Caddy + +## Service / port map + +| Service | Listen | Notes | +|---------|--------|-------| +| `oikos` (Yuvomi) | `0.0.0.0:3000` | Docker Compose at `/opt/yuvomi/`, image `ghcr.io/ulsklyc/yuvomi` | + +## Integrations + +- **Authentik SSO (OIDC):** Provider `Provider for Yuvomi` (PK 31) in Authentik on VPS. Env vars in `/opt/yuvomi/.env`: `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET`. Redirect URI: `https://house.hubris.network/auth/oidc/callback`. +- **Paperless WebDAV bridge:** Yuvomi documents stored on WebDAV server at [paperless (103)](103-paperless.md) port `:8088`, serving `/mnt/library/documents/import/yuvomi/`. Documents placed there by Yuvomi are auto-consumed by Paperless-ngx. +- **Weather widget:** Open-Meteo (free, no API key). Munich coordinates set. +- **Google Calendar:** Pending — see plan for token extraction from [trmnl (128)](128-trmnl.md). + +## Config paths + +- `/opt/yuvomi/docker-compose.yml` — downloaded from upstream +- `/opt/yuvomi/.env` — config including secrets (untracked) +- `/opt/yuvomi/data/` — SQLCipher SQLite DB (`oikos.db`) +- `/opt/yuvomi/backups/` — auto backups +- `/opt/yuvomi/modules/` — Yuvomi modules (empty for now) + +## Related + +- [Caddy (121)](121-caddy.md) — LAN reverse proxy (`house.hubris.network → 192.168.8.212:3000`) +- [VPS ingress](../infrastructure/ingress.md) — public edge (cert mirror + traefik router) +- [DNS (107)](107-dns.md) — Technitium A record `house → 192.168.8.175` (LAN path via Caddy) +- [Paperless (103)](103-paperless.md) — WebDAV bridge for document import +- [TRMNL (128)](128-trmnl.md) — Google Calendar tokens source +- [Deployment plan](../plans/2026-06-25-yuvomi-deployment.md) + +## Changelog + +### 2026-06-26 — provisioned + +LXC 129 created (Debian 13, unprivileged, `192.168.8.212`). Docker installed. Yuvomi container running on `:3000` from `ghcr.io/ulsklyc/yuvomi:latest`. Caddy block + DNS A record + VPS traefik router `house-public` for public access. Authentik OIDC provider created (PK 31). WebDAV document bridge on paperless LXC (103) at `:8088` for Paperless auto-import. \ No newline at end of file diff --git a/containers/index.md b/containers/index.md index 363ccfd..2b7055e 100644 --- a/containers/index.md +++ b/containers/index.md @@ -17,6 +17,7 @@ All containers live on [`hubris`](../hosts/hubris.md). Each row links to the per | 124 | [authentik](124-authentik.md) | 192.168.8.180 | priv | 2 | 4 GiB | 20 GiB | — | `auth.hubris.network` | running | | 126 | [plato](126-plato.md) | 192.168.8.190 | priv | 2 | 2 GiB | 8 GiB | `/mnt/library/documents/plato` | `plato.hubris.network` | running | | 128 | [trmnl](128-trmnl.md) | 192.168.8.211 | unpriv | 1 | 768 MiB | 8 GiB | — | `trmnl.hubris.network` | running | +| 129 | [house](129-house.md) | 192.168.8.212 | unpriv | 1 | 1344 MiB | 8 GiB | — | `house.hubris.network` | running | ## Recently destroyed (kept for archaeology) diff --git a/infrastructure/ingress.md b/infrastructure/ingress.md index f717575..cb06518 100644 --- a/infrastructure/ingress.md +++ b/infrastructure/ingress.md @@ -43,6 +43,7 @@ LAN clients resolve via the [Technitium DNS on dns (107)](dns.md) → `192.168.8 | `artifacto.hubris.network` | `/p/*`, `/static/*`, `/healthz` | `192.168.8.205:3100` | `artifacto-strip-sso` + `artifacto-ratelimit` (50 rps / 100 burst) | `fullchain.crt` / `privkey.key` | | `blog.hubris.network` | whole host | `192.168.8.205:8080` | `blog-ratelimit` (100 rps / 200 burst) | `blog.fullchain.crt` / `blog.privkey.key` | | `trmnl.hubris.network` | whole host | `192.168.8.211:9851` ([trmnl 128](../containers/128-trmnl.md)) | `trmnl-ratelimit` (20 rps / 40 burst) | `trmnl.fullchain.crt` / `trmnl.privkey.key` | +| `house.hubris.network` | whole host | `192.168.8.212:3000` ([house 129](../containers/129-house.md)) | `house-ratelimit` (30 rps / 60 burst) | `house.fullchain.crt` / `house.privkey.key` | `artifacto-strip-sso` blanks inbound `X-Authentik-*` and `X-Artifacto-Gateway` so external clients can't spoof the SSO auto-login header contract. Path split is enforced at the VPS router rule, not by home Caddy. See [Artifacto on apps (105)](../containers/105-apps.md). diff --git a/inventory.yaml b/inventory.yaml index b6d505e..5ef4838 100644 --- a/inventory.yaml +++ b/inventory.yaml @@ -130,6 +130,17 @@ hosts: lan_ip: 192.168.8.211 public_host: trmnl.hubris.network # not yet mesh/SOPS-enrolled — see containers/128-trmnl.md + house: + kind: lxc + pve_id: 129 + host: hubris + os: linux + role: family-planner + lan_ip: 192.168.8.212 + public_host: house.hubris.network + notes: + - Docker host for Yuvomi (family planner). Created 2026-06-26. + - Runs Yuvomi container + WebDAV doc bridge to paperless jellyfin: kind: lxc pve_id: 101 diff --git a/plans/2026-06-25-yuvomi-deployment.md b/plans/2026-06-25-yuvomi-deployment.md new file mode 100644 index 0000000..30e5b86 --- /dev/null +++ b/plans/2026-06-25-yuvomi-deployment.md @@ -0,0 +1,443 @@ +# Yuvomi deployment — `house.hubris.network` + +Deploy [Yuvomi](https://yuvomi.cloud/) (previously Oikos) — a self-hosted +family planner with 14 modules (calendar, tasks, meals, groceries, budget, +documents, notes, etc). Single Docker container (Express.js + SQLCipher +SQLite), 256 MB RAM min. + +**Target hostname:** `house.hubris.network` — publicly reachable via VPS +traefik, LAN reachable via Caddy. + +**Integrations:** +- Authentik SSO (OIDC) +- Google Calendar (tokens exist on trmnl LXC 128) +- Paperless (Yuvomi's Documents module / clarification needed — see Phase 4) + +--- + +## Phase 0 — Clarifications needed + +### 0.1 Paperless connection +Yuvomi's "Documents" module stores documents inside its encrypted SQLite DB or +optionally on WebDAV. There is **no direct Paperless-ngx API connector** in +Yuvomi. Options: + +a) **Keep as-is** — Yuvomi's docs are separate from Paperless, no integration +b) **WebDAV bridge** — Mount Paperless's consumption dir as WebDAV, point + Yuvomi doc storage there (Yuvomi stores newly uploaded docs directly in the + Paperless consume folder) +c) **Custom module** — Write a Yuvomi module that fetches from Paperless API + +Decision needed before Phase 3 config. + +**Decision:** WebDAV bridge (Phase 6.2). + +### 0.2 Deployment target +Two options: + +| Option | Pros | Cons | +|--------|------|------| +| **apps LXC (105)** — Docker already there, 4GB RAM, 2 cores | Zero provisioning, existing compose pattern | Shared with artifacto, MCP, secrets-issuance; Portainer-managed stacks can be tricky | +| **New LXC (~129)** — dedicated, clean | Isolated, no side-effects | Need to create, install Docker, wire into everything | + +**Decision:** New LXC (129). + +--- + +## Phase 1 — Provision new LXC (129) for Yuvomi + +### 1.1 Create the LXC on hubris + +``` +ssh root@192.168.8.77 << 'EOF' +# Check available templates +pveam list local | grep debian + +# Create unprivileged Debian 13 LXC (follows trmnl's unpriv pattern) +pct create 129 local:vztmpl/debian-13-standard_13.7-1_amd64.tar.zst \ + --hostname house \ + --description "Yuvomi family planner — house.hubris.network" \ + --cores 1 \ + --memory 1024 \ + --swap 512 \ + --rootfs local:8 \ + --net0 name=eth0,bridge=vmbr0,ip=dhcp,type=veth \ + --unprivileged 1 \ + --features nesting=1 \ + --onboot 1 \ + --start 1 +EOF +``` + +Resources: 1 core / 1 GiB RAM / 8 GiB rootfs (generous for a single Express.js +container; can downsize later). + +### 1.2 Set static IP and install Docker + +After the LXC boots, find its DHCP lease, then set a static IP: + +``` +# Find actual IP +ssh root@192.168.8.77 'lxc-attach 129 -- ip addr show eth0 | grep inet' + +# Reserve 192.168.8.212 (or whatever is free) via Technitium DHCP, +# or set static IP in PVE config: +ssh root@192.168.8.77 'pct set 129 --net0 name=eth0,bridge=vmbr0,ip=192.168.8.212/24,gw=192.168.8.1,type=veth' +ssh root@192.168.8.77 'lxc-attach 129 -- reboot' +``` + +### 1.3 Install Docker inside the LXC + +``` +ssh root@192.168.8.77 << 'DOCKER' +lxc-attach 129 -- bash -c ' + apt-get update + apt-get install -y ca-certificates curl + install -m 0755 -d /etc/apt/keyrings + curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc + chmod a+r /etc/apt/keyrings/docker.asc + echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null + apt-get update + apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + systemctl enable --now docker + docker --version + docker compose version +' +DOCKER +``` + +### 1.4 Download Yuvomi and start + +``` +ssh root@192.168.8.77 'lxc-attach 129 -- bash -c " +mkdir -p /opt/yuvomi /opt/yuvomi/data /opt/yuvomi/backups /opt/yuvomi/modules +cd /opt/yuvomi +curl -O https://raw.githubusercontent.com/ulsklyc/yuvomi/main/docker-compose.yml +curl -O https://raw.githubusercontent.com/ulsklyc/yuvomi/main/.env.example +cp .env.example .env +"' +``` + +### 1.5 Generate keys and configure .env + +``` +ssh root@192.168.8.77 'lxc-attach 129 -- bash -c " +SESSION_SECRET=\$(openssl rand -hex 32) +DB_KEY=\$(openssl rand -hex 32) +cd /opt/yuvomi +sed -i \"s/SESSION_SECRET=.*/SESSION_SECRET=\$SESSION_SECRET/\" .env +sed -i \"s/DB_ENCRYPTION_KEY=.*/DB_ENCRYPTION_KEY=\$DB_KEY/\" .env +sed -i \"s/OIKOS_HTTP_PORT=3000/OIKOS_HTTP_PORT=3000/\" .env +sed -i \"s/# TZ=.*/TZ=Europe\\/Berlin/\" .env +echo \"SESSION_SECURE=true\" >> .env +echo \"TRUST_PROXY=1\" >> .env +echo \"BASE_URL=https://house.hubris.network\" >> .env +"' +``` + +### 1.6 Start Yuvomi + +``` +ssh root@192.168.8.77 'lxc-attach 129 -- bash -c "cd /opt/yuvomi && docker compose up -d"' +``` + +### 1.7 Verify + +``` +ssh root@192.168.8.77 'lxc-attach 129 -- curl -s http://127.0.0.1:3000/health' +# Expected: 200 OK + +--- + +## Phase 2 + +### 2.1 Caddy — add `house.hubris.network` + +Edit `/etc/caddy/Caddyfile` on LXC 121 (via `dtoro/caddy-conf` repo): + +``` +house.hubris.network { + tls { + dns ionos + } + reverse_proxy 192.168.8.212:3000 +} +``` + +- Commit to `dtoro/caddy-conf` → auto-deploy via webhook +- If not yet deployed, push manually: `cd /etc/caddy && git add Caddyfile && git commit -m 'add house.hubris.network → yuvomi' && git push` + +### 2.2 Verify LAN access + +``` +curl -sI https://house.hubris.network/ +# Expected: 200 or 302 (redirect to /login or the setup wizard) +``` + +### 2.3 DNS — add Technitium record + +Add A record `house.hubris.network → 192.168.8.175` (Caddy) on DNS LXC (107). + +If using the DNS web UI: http://192.168.8.2/ → Zones → hubris.network → Add A record. + +### 2.4 DNS mesh sync + +If mesh DNS (Netbird managed zone) is in use, add the same record there or +verify dns-sync picks it up. + +--- + +## Phase 3 — Public exposure (VPS traefik) + +### 3.1 Add cert sync entry + +On hubris (PVE host), edit `/usr/local/bin/hubris-public-cert-sync.sh`, add: + +```bash +[house.hubris.network]="house.fullchain.crt house.privkey.key" +``` + +Run once: + +``` +systemctl start hubris-public-cert-sync.service +``` + +Verify certs landed on VPS: + +``` +ssh root@100.122.165.149 "ls -la /var/lib/docker/volumes/opt_netbird_traefik_letsencrypt/_data/house.*" +``` + +### 3.2 Add traefik router + +On the VPS, edit `/opt/traefik-dynamic.yaml`: + +```yaml +http: + routers: + house-public: + rule: 'Host(`house.hubris.network`)' + entryPoints: + - websecure + priority: 10 + tls: {} + middlewares: + - house-ratelimit + service: house-public + + middlewares: + house-ratelimit: + rateLimit: + average: 30 + period: 1s + burst: 60 + + services: + house-public: + loadBalancer: + servers: + - url: 'http://192.168.8.212:3000' + +tls: + certificates: + - certFile: /letsencrypt/house.fullchain.crt + keyFile: /letsencrypt/house.privkey.key +``` + +Restart traefik: + +``` +docker restart netbird-traefik +``` + +### 3.3 Verify public access + +From outside the homelab LAN (or with `--resolve`): + +``` +curl -sI --resolve house.hubris.network:443:82.165.190.79 https://house.hubris.network/ +# Expected: 200 or 302 + +echo | openssl s_client -connect 82.165.190.79:443 -servername house.hubris.network 2>&1 | openssl x509 -noout -subject +# Expected: CN=house.hubris.network (not TRAEFIK DEFAULT CERT) +``` + +--- + +## Phase 4 — Authentik SSO (OIDC) + +### 4.1 Create OIDC provider in Authentik + +Via VPS admin UI (`https://auth.hubris.network/if/admin/`): + +- Applications → Providers → Create → OAuth2/OpenID Provider +- Name: `yuvomi` +- Client ID: auto-generated +- Client Secret: auto-generated (save this) +- Redirect URIs: `https://house.hubris.network/oauth2/callback` +- Signing Key: auto-generated +- Subject Mode: Based on User ID (or Based on Username — pick what Yuvomi expects) + +### 4.2 Create application in Authentik + +- Applications → Applications → Create +- Name: `Yuvomi` +- Slug: `yuvomi` +- Provider: select the one created above +- Launch URL: `https://house.hubris.network` + +### 4.3 Set env vars in Yuvomi `.env` + +On apps LXC (105), edit `/opt/yuvomi/.env`: + +``` +OIDC_ISSUER=https://auth.hubris.network/application/o/yuvomi/ +OIDC_CLIENT_ID= +OIDC_CLIENT_SECRET= +# OIDC_TRUST_EMAIL_WITHOUT_VERIFIED_CLAIM=true # if Authentik doesn't send email_verified +``` + +### 4.4 Restart Yuvomi + +``` +pct exec 105 -- bash -c 'cd /opt/yuvomi && docker compose restart' +``` + +### 4.5 Verify SSO flow + +Open `https://house.hubris.network/` — should redirect to Authentik login, +then back to Yuvomi. + +--- + +## Phase 5 — Google Calendar + +### 5.1 Extract tokens from trmnl LXC + +On trmnl (LXC 128), the env file at `/etc/trmnl-plugins/env` contains: + +``` +GOOGLE_CLIENT_ID=119823214387-32f20ed3imesiv7uh5si7p3rou9fros4.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=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 +GOOGLE_REFRESH_TOKEN=1//03CS0rkuf7XVQCgYIARAAGAMSNwF-L9Irr5_b4kLhkx-dtf9EGQ1eJ1OnvxkaV_P1_4TDPwUN2lFb7nsbrZklN7qbjpkHpQyYlBY +``` + +### 5.2 Add Google Account redirect URI + +In the Google Cloud Console (OAuth 2.0 Client IDs), add: + +``` +https://house.hubris.network/auth/google/callback +``` + +to the authorized redirect URIs for the existing client ID. + +### 5.3 Set env vars in Yuvomi `.env` + +``` +GOOGLE_CLIENT_ID=119823214387-32f20ed3imesiv7uh5si7p3rou9fros4.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=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 +``` + +Note: Yuvomi's Google Calendar integration uses the OAuth flow to get its own +refresh token — it doesn't reuse the trmnl refresh token. The first-time setup +in Yuvomi Settings → Calendar → Google Calendar will prompt for authorization. + +### 5.4 Restart and verify + +``` +pct exec 105 -- bash -c 'cd /opt/yuvomi && docker compose restart' +``` + +Then in Yuvomi UI: Settings → Calendar → Connect Google Calendar → authorize. + +--- + +## Phase 6 — Paperless integration (decide approach first) + +### 6.1 If using as standalone documents module (no Paperless bridge) +No action needed. Yuvomi's Documents module works out of the box — docs stored +in encrypted SQLite. + +### 6.2 If using WebDAV bridge to Paperless consumption +- Paperless consumes documents from `/mnt/library/documents/consume/` +- Point Yuvomi's WebDAV document storage at a WebDAV server serving that dir +- Options: run a lightweight WebDAV container on paperless LXC (103), or use + Nextcloud's WebDAV if documents are already in `/mnt/library` + +Set env vars: +``` +DOCUMENT_STORAGE_WEBDAV_ENABLED=true +DOCUMENT_STORAGE_WEBDAV_URL=http://192.168.8.130:8000/... # or WebDAV server +DOCUMENT_STORAGE_WEBDAV_USERNAME=... +DOCUMENT_STORAGE_WEBDAV_PASSWORD=... +DOCUMENT_STORAGE_WEBDAV_ALLOW_PRIVATE_NETWORK=true +``` + +### 6.3 If building a custom module +Write a Yuvomi module (client-side JS + module.json) that reads from +Paperless API at `https://paperless.hubris.network/api/` using a Paperless +API token. See `modules/MODULES.md` in the Yuvomi repo for the module format. + +--- + +## Phase 7 — Backup & maintenance + +### 7.1 Data persistence +Yuvomi stores everything in a single SQLCipher-encrypted SQLite file at +`/opt/yuvomi/data/oikos.db`. This is the only file needed for backup. + +### 7.2 Add to homelab context +- Create `/opt/homelab-context/containers/129-yuvomi.md` (or `.../house.md`) +- Update `inventory.yaml` if using a new LXC +- Add changelog entries to caddy (121) and ingress docs +- Update `plans/index.md` → mark this plan `Done` + +### 7.3 Schedule backup +Add a cron (or existing backup system) for `/opt/yuvomi/data/` if not already +covered by the host-level backup scheme. + +--- + +## Summary of steps + +| Phase | What | Who/Where | +|-------|------|-----------| +| 0 | Clarify Paperless approach + deployment target | dtoro | +| 1 | Docker Compose on apps LXC, start container | Hermes | +| 2 | Caddy block + DNS record for `house.hubris.network` | Hermes | +| 3 | VPS traefik router + cert sync for public exposure | Hermes | +| 4 | Authentik OIDC provider + env vars | Hermes (needs admin UI) | +| 5 | Google Calendar tokens + redirect URI | Hermes + dtoro (Google Cloud Console) | +| 6 | Paperless integration (depends on Phase 0 decision) | Hermes | +| 7 | Documentation, backup, inventory updates | Hermes | + +--- + +## Duration estimate + +| Phase | Time | Notes | +|-------|------|-------| +| Phase 1 | ~15 min | Download, config, startup | +| Phase 2 | ~10 min | Caddy + DNS | +| Phase 3 | ~15 min | VPS traefik + cert sync | +| Phase 4 | ~20 min | Authentik provider setup + env | +| Phase 5 | ~10 min + Google UI | Redirect URI takes 1 min in console | +| Phase 6 | TBD | Depends on chosen approach | +| Phase 7 | ~10 min | Doc + inventory updates | +| **Total** | **~1.5h + Phase 6** | | + +## Rollback + +If anything goes wrong: + +```bash +# Stop and remove container +pct exec 105 -- bash -c 'cd /opt/yuvomi && docker compose down' + +# Remove Caddy block, commit, push — auto-deploys +# Remove VPS traefik router, restart netbird-traefik +# Remove cert sync entry +# Remove DNS record +``` \ No newline at end of file diff --git a/plans/index.md b/plans/index.md index 69c949b..a202ce0 100644 --- a/plans/index.md +++ b/plans/index.md @@ -7,6 +7,8 @@ Pre-flight runbooks for planned changes that haven't happened yet. Once executed | Date | Title | Status | | ---- | ----- | ------ | | 2026-06-24 | [TRMNL plugins LXC (128) + middleware deploy pipeline](2026-06-24-trmnl-plugins-lxc.md) | In Progress | +| 2026-06-25 | [Yuvomi deployment — house.hubris.network](2026-06-25-yuvomi-deployment.md) | Done | +| 2026-06-24 | [TRMNL plugins LXC (128) + middleware deploy pipeline](2026-06-24-trmnl-plugins-lxc.md) | In Progress | | 2026-06-01 | [Slate AX → SODOLA managed switch migration](2026-06-01-slate-ax-to-sodola-migration.md) | Done | ## Conventions