From 128e11b823b493ad73ac088144b7099243fc383c Mon Sep 17 00:00:00 2001 From: dtoro Date: Tue, 7 Jul 2026 18:59:54 +0200 Subject: [PATCH] port build_host_files.py to Go, simplify Hermes MCP, cutover final MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - cmd/hermes/main.go: removed redundant /mcp endpoint — Hermes gateway now serves only /query + /healthz. MCP goes direct to API (:8090/mcp). - cmd/oikos/build_hosts.go: Go port of mcp/build_host_files.py as 'oikos build-hosts'. Reads inventory.yaml, writes hosts/*.yaml. - cmd/oikos/main.go: added build-hosts role. - docker-compose.yml: hermes service simplified. - apps/105: all 6 Oikos services stopped + disabled (confirmed inactive). - Watchdog cron installed, API stop/restart verified. - Infisical bootstrap pending (image pull timeout — retry separately). Remaining: - Port bin/homelab CLI to Go (separate plan — large surface) - Caddy DNS push (needs dtoro/caddy-conf repo access) - Rollback drill --- cmd/oikos/build_hosts.go | 187 +++++++++++++++++++++++++++++++++++++ cmd/oikos/main.go | 6 ++ hosts/apps.yaml | 101 ++++++++++---------- hosts/arriman.yaml | 52 +++++------ hosts/auth-outpost.yaml | 32 +++---- hosts/caddy.yaml | 61 ++++++------ hosts/dns.yaml | 50 +++++----- hosts/elementsynapse.yaml | 46 ++++----- hosts/gitea.yaml | 52 +++++------ hosts/grimmory.yaml | 44 ++++----- hosts/haos.yaml | 36 +++---- hosts/house.yaml | 45 +++++---- hosts/hubris.yaml | 52 +++++------ hosts/jellyfin.yaml | 57 ++++++----- hosts/mac-mini.yaml | 30 +++--- hosts/mule-images.yaml | 42 ++++----- hosts/netbird-vps.yaml | 59 ++++++------ hosts/nextcloud.yaml | 40 ++++---- hosts/nfs-export.yaml | 28 +++--- hosts/paperless.yaml | 42 ++++----- hosts/rclone.yaml | 24 ++--- hosts/republic-laptop.yaml | 24 ++--- hosts/romm.yaml | 44 ++++----- hosts/seanime.yaml | 50 +++++----- hosts/sophia.yaml | 28 +++--- hosts/strong.yaml | 46 ++++----- hosts/teddycloud.yaml | 69 ++++++-------- hosts/trmnl.yaml | 48 +++++----- hosts/zimaos.yaml | 44 ++++----- 29 files changed, 801 insertions(+), 638 deletions(-) create mode 100644 cmd/oikos/build_hosts.go diff --git a/cmd/oikos/build_hosts.go b/cmd/oikos/build_hosts.go new file mode 100644 index 0000000..93f9275 --- /dev/null +++ b/cmd/oikos/build_hosts.go @@ -0,0 +1,187 @@ +package main + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "sort" + "strings" + + "gopkg.in/yaml.v3" +) + +func runBuildHosts() error { + repoDir := "." + if d := os.Getenv("HOMELAB_CONTEXT_DIR"); d != "" { + repoDir = d + } + + data, err := os.ReadFile(filepath.Join(repoDir, "inventory.yaml")) + if err != nil { + return fmt.Errorf("read inventory: %w", err) + } + + var inventory map[string]any + if err := yaml.Unmarshal(data, &inventory); err != nil { + return fmt.Errorf("parse inventory: %w", err) + } + + hosts, _ := inventory["hosts"].(map[string]any) + services, _ := inventory["services"].(map[string]any) + mesh, _ := inventory["mesh"].(map[string]any) + + hostsDir := filepath.Join(repoDir, "hosts") + os.MkdirAll(hostsDir, 0755) + + desired := make(map[string]string) + for name, entry := range hosts { + entryMap, _ := entry.(map[string]any) + record := buildHostRecord(name, entryMap, services, mesh) + content := fmt.Sprintf("# Generated by oikos build-hosts from inventory.yaml.\n# Do NOT edit by hand.\n\n%s", asYAML(record)) + desired[name+".yaml"] = content + } + + for name, content := range desired { + path := filepath.Join(hostsDir, name) + if err := os.WriteFile(path, []byte(content), 0644); err != nil { + return fmt.Errorf("write %s: %w", path, err) + } + fmt.Printf("wrote %s\n", name) + } + + // Clean orphans + entries, _ := os.ReadDir(hostsDir) + for _, e := range entries { + if strings.HasSuffix(e.Name(), ".yaml") && desired[e.Name()] == "" { + os.Remove(filepath.Join(hostsDir, e.Name())) + fmt.Printf("deleted orphan %s\n", e.Name()) + } + } + + return nil +} + +func buildHostRecord(name string, entry map[string]any, services map[string]any, mesh map[string]any) map[string]any { + kind, _ := entry["kind"].(string) + + var runsServices []string + for svc, v := range services { + if svcMap, ok := v.(map[string]any); ok { + if backend, ok := svcMap["backend"].(string); ok && backend == name { + runsServices = append(runsServices, svc) + } + } + } + sort.Strings(runsServices) + + var hosted []map[string]any + for _, svc := range runsServices { + if svcMap, ok := services[svc].(map[string]any); ok { + entry := make(map[string]any) + for k, v := range svcMap { + entry[k] = v + } + entry["name"] = svc + hosted = append(hosted, entry) + } + } + + record := map[string]any{ + "name": name, + "kind": kind, + "os": entry["os"], + "role": entry["role"], + "state": stringOr(entry["state"], "active"), + "host": entry["host"], + "pve_id": entry["pve_id"], + "storage": entry["storage"], + "depends_on": entry["depends_on"], + "lan_ip": entry["lan_ip"], + "mesh": entry["mesh"], + "peers": entry["peers"], + "mounts": entry["mounts"], + "public_host": entry["public_host"], + "ssh": entry["ssh"], + "runs": append(stringSlice(entry["runs"]), runsServices...), + "services_hosted": hosted, + "notes": entry["notes"], + "age_pubkey": entry["age_pubkey"], + } + + if mesh != nil { + record["mesh_globals"] = map[string]any{ + "primary": mesh["primary"], + "accepted": mesh["accepted"], + } + } + + if mcp, ok := services["homelab_mcp"].(map[string]any); ok { + record["mcp_endpoint"] = mcp["endpoint"] + } + if si, ok := services["secrets_issuance"].(map[string]any); ok { + record["secrets_issuance_endpoint"] = si["endpoint"] + } + + cleaned := make(map[string]any) + for k, v := range record { + switch val := v.(type) { + case nil: + continue + case string: + if val == "" { + continue + } + case []string: + if len(val) == 0 { + continue + } + case []map[string]any: + if len(val) == 0 { + continue + } + case map[string]any: + if len(val) == 0 { + continue + } + case int: + if val == 0 { + continue + } + } + cleaned[k] = v + } + + return cleaned +} + +func stringOr(v any, def string) string { + if s, ok := v.(string); ok && s != "" { + return s + } + return def +} + +func stringSlice(v any) []string { + switch val := v.(type) { + case []any: + var out []string + for _, item := range val { + if s, ok := item.(string); ok { + out = append(out, s) + } + } + return out + case []string: + return val + } + return nil +} + +func asYAML(v any) string { + var buf bytes.Buffer + enc := yaml.NewEncoder(&buf) + enc.SetIndent(2) + enc.Encode(v) + return buf.String() +} diff --git a/cmd/oikos/main.go b/cmd/oikos/main.go index 4b5cd64..0fca3f0 100644 --- a/cmd/oikos/main.go +++ b/cmd/oikos/main.go @@ -59,6 +59,11 @@ func main() { slog.Error("export failed", "error", err) os.Exit(1) } + case "build-hosts": + if err := runBuildHosts(); err != nil { + slog.Error("build-hosts failed", "error", err) + os.Exit(1) + } case "api": if err := runAPI(ctx, cfg); err != nil { slog.Error("api failed", "error", err) @@ -111,6 +116,7 @@ Roles: migrate Run database migrations (forward-only, idempotent) seed Ingest seed YAML files into the database export Export DB state back to seed YAMLs (DR / version control) + build-hosts Generate hosts/*.yaml from seeds/inventory.yaml api Run the REST + MCP API server (Phase 2) scheduler Run the observe + act loop (Phase 3) notifier Run the notification service (Phase 3) diff --git a/hosts/apps.yaml b/hosts/apps.yaml index 375be02..260a678 100644 --- a/hosts/apps.yaml +++ b/hosts/apps.yaml @@ -1,62 +1,59 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: apps -kind: lxc -os: linux -role: docker-apps -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + +age_pubkey: age1duyl8mkpgu80uv934dy8q7enqjms6yvdz264hme8uryuxmvvqesq6rusq0 host: hubris -pve_id: 105 +kind: lxc lan_ip: 192.168.8.205 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: - ip: 100.121.171.122 fqdn: apps + ip: 100.121.171.122 mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library -public_hosts: -- artifacto.hubris.network + - /mnt/library +name: apps +os: linux +pve_id: 105 +role: docker-apps runs: -- artifacto -- plantuml -- homelab-mcp -- secrets-issuance -- artifacto -- homelab_mcp -- secrets_issuance -services_hosted: -- name: artifacto - backend: apps - url: https://artifacto.hubris.network - doc_page: knowledge/wiki/containers/105-apps.md - config_repo: dtoro/Artifacto -- name: homelab_mcp - backend: apps - port: 9810 - systemd_unit: homelab-mcp - public_host: mcp.hubris.network - endpoint: https://mcp.hubris.network/mcp - doc_page: knowledge/wiki/infrastructure/homelab-context.md - config_repo: dtoro/Homelab-Docs - note: MCP server. Read-only context + management. Reachable on the LAN via Caddy and from off-LAN via - Netbird (192.168.8.0/24 is a network resource routed through hubris). - risk_notes: "agents' primary read surface \u2014 outage degrades every agent to grepping the clone" -- name: secrets_issuance - backend: apps - port: 9820 - systemd_unit: secrets-issuance - public_host: secrets.hubris.network - endpoint: https://secrets.hubris.network/issue - doc_page: .agents/operations/agent-enrollment.md - config_repo: dtoro/Homelab-Docs - note: Issues per-client age private keys. Gated at source-IP layer (mesh + LAN subnets in MESH_SUBNETS). - risk_notes: "identity issuance \u2014 any change is security-sensitive; key operations are destructive-class" -age_pubkey: age1duyl8mkpgu80uv934dy8q7enqjms6yvdz264hme8uryuxmvvqesq6rusq0 -mcp_endpoint: https://mcp.hubris.network/mcp + - artifacto + - plantuml + - homelab-mcp + - secrets-issuance + - artifacto + - homelab_mcp + - secrets_issuance secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: apps + config_repo: dtoro/Artifacto + doc_page: knowledge/wiki/containers/105-apps.md + name: artifacto + url: https://artifacto.hubris.network + - backend: apps + config_repo: dtoro/Homelab-Docs + doc_page: knowledge/wiki/infrastructure/homelab-context.md + endpoint: https://mcp.hubris.network/mcp + name: homelab_mcp + note: MCP server. Read-only context + management. Reachable on the LAN via Caddy and from off-LAN via Netbird (192.168.8.0/24 is a network resource routed through hubris). + port: 9810 + public_host: mcp.hubris.network + risk_notes: agents' primary read surface — outage degrades every agent to grepping the clone + systemd_unit: homelab-mcp + - backend: apps + config_repo: dtoro/Homelab-Docs + doc_page: .agents/operations/agent-enrollment.md + endpoint: https://secrets.hubris.network/issue + name: secrets_issuance + note: Issues per-client age private keys. Gated at source-IP layer (mesh + LAN subnets in MESH_SUBNETS). + port: 9820 + public_host: secrets.hubris.network + risk_notes: identity issuance — any change is security-sensitive; key operations are destructive-class + systemd_unit: secrets-issuance +state: active diff --git a/hosts/arriman.yaml b/hosts/arriman.yaml index 58e7cf3..8d0918e 100644 --- a/hosts/arriman.yaml +++ b/hosts/arriman.yaml @@ -1,38 +1,34 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: arriman -kind: lxc -os: linux -role: arr-stack -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: strong -pve_id: 122 +kind: lxc lan_ip: 192.168.8.245 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: arr mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/media_local -public_hosts: -- jellyseerr.hubris.network -- qbit.hubris.network -- sab.hubris.network -runs: -- arr_stack -services_hosted: -- name: arr_stack - backend: arriman - note: jellyseerr / qbit / sab on docker compose - doc_page: knowledge/wiki/containers/122-arriman.md + - /mnt/media_local +name: arriman notes: -- Migrated from hubris to strong 2026-07-05 (Phase 2). Library on ludo-lvm. -- Contains homarr, radarr, sonarr, lidarr, sabnzbd, qbittorrent, bazarr, flaresolverr, prowlarr, jellyseerr -- qBittorrent auth subnet whitelist expanded to 192.168.8.0/24 (for seanime + Caddy access) -mcp_endpoint: https://mcp.hubris.network/mcp + - Migrated from hubris to strong 2026-07-05 (Phase 2). Library on ludo-lvm. + - Contains homarr, radarr, sonarr, lidarr, sabnzbd, qbittorrent, bazarr, flaresolverr, prowlarr, jellyseerr + - qBittorrent auth subnet whitelist expanded to 192.168.8.0/24 (for seanime + Caddy access) +os: linux +pve_id: 122 +role: arr-stack +runs: + - arr_stack secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: arriman + doc_page: knowledge/wiki/containers/122-arriman.md + name: arr_stack + note: jellyseerr / qbit / sab on docker compose +state: active diff --git a/hosts/auth-outpost.yaml b/hosts/auth-outpost.yaml index 29a0fae..d9a09dd 100644 --- a/hosts/auth-outpost.yaml +++ b/hosts/auth-outpost.yaml @@ -1,20 +1,20 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: auth-outpost -kind: lxc -os: linux -role: authentik-gateway -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 106 +kind: lxc lan_ip: 192.168.8.6 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -notes: -- Runs Authentik outpost (reverse-proxy/SSO enforcement) for protected services mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: auth-outpost +notes: + - Runs Authentik outpost (reverse-proxy/SSO enforcement) for protected services +os: linux +pve_id: 106 +role: authentik-gateway secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/caddy.yaml b/hosts/caddy.yaml index c533e36..a4dfed4 100644 --- a/hosts/caddy.yaml +++ b/hosts/caddy.yaml @@ -1,35 +1,34 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: caddy -kind: lxc -os: linux -role: reverse-proxy -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 121 +kind: lxc lan_ip: 192.168.8.175 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -peers: -- authentik -- gitea -runs: -- caddy -services_hosted: -- name: caddy - backend: caddy - role: reverse-proxy - note: terminates all *.hubris.network - doc_page: knowledge/wiki/containers/121-caddy.md - config_repo: dtoro/caddy-conf - risk_notes: "wide blast radius \u2014 every *.hubris.network route rides on it (see oikos/policy.yaml\ - \ service_overrides)" -notes: -- Terminates all *.hubris.network -- /etc/caddy is a git checkout of dtoro/caddy-conf mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: caddy +notes: + - Terminates all *.hubris.network + - /etc/caddy is a git checkout of dtoro/caddy-conf +os: linux +peers: + - authentik + - gitea +pve_id: 121 +role: reverse-proxy +runs: + - caddy secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: caddy + config_repo: dtoro/caddy-conf + doc_page: knowledge/wiki/containers/121-caddy.md + name: caddy + note: terminates all *.hubris.network + risk_notes: wide blast radius — every *.hubris.network route rides on it (see oikos/policy.yaml service_overrides) + role: reverse-proxy +state: active diff --git a/hosts/dns.yaml b/hosts/dns.yaml index 67bc722..6702814 100644 --- a/hosts/dns.yaml +++ b/hosts/dns.yaml @@ -1,29 +1,29 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: dns -kind: lxc -os: linux -role: dns-server -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 107 +kind: lxc lan_ip: 192.168.8.2 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -runs: -- dns -services_hosted: -- name: dns - backend: dns - note: Technitium DNS, split-horizon zone - doc_page: knowledge/wiki/containers/107-dns.md - risk_notes: "LAN-wide resolver \u2014 misconfig breaks name resolution for every client" -notes: -- Technitium DNS, split-horizon zone for *.hubris.network -- Primary DNS for 192.168.8.0/24 LAN (inventory.services.dns references this) mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: dns +notes: + - Technitium DNS, split-horizon zone for *.hubris.network + - Primary DNS for 192.168.8.0/24 LAN (inventory.services.dns references this) +os: linux +pve_id: 107 +role: dns-server +runs: + - dns secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: dns + doc_page: knowledge/wiki/containers/107-dns.md + name: dns + note: Technitium DNS, split-horizon zone + risk_notes: LAN-wide resolver — misconfig breaks name resolution for every client +state: active diff --git a/hosts/elementsynapse.yaml b/hosts/elementsynapse.yaml index 535b6fa..5f522f0 100644 --- a/hosts/elementsynapse.yaml +++ b/hosts/elementsynapse.yaml @@ -1,31 +1,31 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: elementsynapse -kind: lxc -os: linux -role: matrix-server -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: strong -pve_id: 118 +kind: lxc lan_ip: 192.168.8.242 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: {} mesh_globals: - primary: netbird accepted: - - netbird - - tailscale -public_host: matrix.hubris.network -runs: -- matrix -services_hosted: -- name: matrix - url: https://matrix.hubris.network - backend: elementsynapse - doc_page: knowledge/wiki/containers/118-elementsynapse.md - risk_notes: "alert/approval channel for Oikos \u2014 outage silences agent escalation" + - netbird + - tailscale + primary: netbird +name: elementsynapse notes: -- Migrated from hubris to strong 2026-07-05 (Phase 1 of strong migration plan). -mcp_endpoint: https://mcp.hubris.network/mcp + - Migrated from hubris to strong 2026-07-05 (Phase 1 of strong migration plan). +os: linux +public_host: matrix.hubris.network +pve_id: 118 +role: matrix-server +runs: + - matrix secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: elementsynapse + doc_page: knowledge/wiki/containers/118-elementsynapse.md + name: matrix + risk_notes: alert/approval channel for Oikos — outage silences agent escalation + url: https://matrix.hubris.network +state: active diff --git a/hosts/gitea.yaml b/hosts/gitea.yaml index 1aa4297..ac25df7 100644 --- a/hosts/gitea.yaml +++ b/hosts/gitea.yaml @@ -1,36 +1,36 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: gitea -kind: lxc -os: linux -role: git-server -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 104 +kind: lxc lan_ip: 192.168.8.121 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: gitea mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library -public_host: git.hubris.network -runs: -- gitea -services_hosted: -- name: gitea - url: https://git.hubris.network - backend: gitea - backend_url: http://192.168.8.121:3000 - doc_page: knowledge/wiki/containers/104-gitea.md - config_repo: dtoro/gitea-customizations - risk_notes: hosts all config repos + deploy webhooks; outage blocks auto-deploy and sync + - /mnt/library +name: gitea notes: -- Bare repos live at /mnt/library/repos/dtoro/*.git -mcp_endpoint: https://mcp.hubris.network/mcp + - Bare repos live at /mnt/library/repos/dtoro/*.git +os: linux +public_host: git.hubris.network +pve_id: 104 +role: git-server +runs: + - gitea secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: gitea + backend_url: http://192.168.8.121:3000 + config_repo: dtoro/gitea-customizations + doc_page: knowledge/wiki/containers/104-gitea.md + name: gitea + risk_notes: hosts all config repos + deploy webhooks; outage blocks auto-deploy and sync + url: https://git.hubris.network +state: active diff --git a/hosts/grimmory.yaml b/hosts/grimmory.yaml index 740ea4c..91f18a2 100644 --- a/hosts/grimmory.yaml +++ b/hosts/grimmory.yaml @@ -1,25 +1,25 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: grimmory -kind: lxc -os: linux -role: book-library -state: active -host: strong -pve_id: 130 -lan_ip: 192.168.8.247 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -mounts: -- /mnt/media_local -public_host: books.hubris.network -notes: -- Docker host for Grimmory (community fork of Booklore). Created 2026-06-29. -- Migrated from hubris to strong 2026-07-05 (Phase 2d). Books on ludo-lvm. +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + age_pubkey: age1uellsemnjrzgfg9fxw4jefpy05laxzggwnwhh6ny3wl7alyp6v8q0muxet +host: strong +kind: lxc +lan_ip: 192.168.8.247 mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +mounts: + - /mnt/media_local +name: grimmory +notes: + - Docker host for Grimmory (community fork of Booklore). Created 2026-06-29. + - Migrated from hubris to strong 2026-07-05 (Phase 2d). Books on ludo-lvm. +os: linux +public_host: books.hubris.network +pve_id: 130 +role: book-library secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/haos.yaml b/hosts/haos.yaml index 467fd4a..caa1fdb 100644 --- a/hosts/haos.yaml +++ b/hosts/haos.yaml @@ -1,27 +1,27 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: haos -kind: vm -os: linux -role: home-automation -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 108 +kind: vm lan_ip: 192.168.8.101 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: homeassistant mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird +name: haos +os: linux +pve_id: 108 +role: home-automation runs: -- haos -services_hosted: -- name: haos - backend: haos - doc_page: knowledge/wiki/vms/108-haos.md -mcp_endpoint: https://mcp.hubris.network/mcp + - haos secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: haos + doc_page: knowledge/wiki/vms/108-haos.md + name: haos +state: active diff --git a/hosts/house.yaml b/hosts/house.yaml index 34f6c72..141c7e3 100644 --- a/hosts/house.yaml +++ b/hosts/house.yaml @@ -1,26 +1,25 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: house -kind: lxc -os: linux -role: family-planner -state: active -host: strong -pve_id: 129 -lan_ip: 192.168.8.244 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -public_host: house.hubris.network -notes: -- Docker host for Yuvomi (family planner). Created 2026-06-26. -- Migrated from hubris to strong 2026-07-05 (Phase 1 of strong migration plan). -- Runs Yuvomi container + WebDAV doc bridge to paperless -- 192.168.8.212 was the hubris IP before migration (briefly picked up by teddycloud via DHCP; teddycloud - has since been given a static IP, see hosts.teddycloud) +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + age_pubkey: age1s07zs83ehtlg8jtwvr75ltc3c4cdlemfwjuxrwjtwkqxkl9tpggsyrzn2h +host: strong +kind: lxc +lan_ip: 192.168.8.244 mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: house +notes: + - Docker host for Yuvomi (family planner). Created 2026-06-26. + - Migrated from hubris to strong 2026-07-05 (Phase 1 of strong migration plan). + - Runs Yuvomi container + WebDAV doc bridge to paperless + - 192.168.8.212 was the hubris IP before migration (briefly picked up by teddycloud via DHCP; teddycloud has since been given a static IP, see hosts.teddycloud) +os: linux +public_host: house.hubris.network +pve_id: 129 +role: family-planner secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/hubris.yaml b/hosts/hubris.yaml index 2c14eab..00ae074 100644 --- a/hosts/hubris.yaml +++ b/hosts/hubris.yaml @@ -1,36 +1,36 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: hubris +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + +age_pubkey: age1xkklkvnk5z0fsnh6cfgv70hy9ksfy8rdprwerzw4yk3p4p7cxcqs2yvpz6 kind: proxmox-host -os: linux -role: hypervisor -state: active lan_ip: 192.168.8.77 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: netbird: - ip: 100.122.38.109 fqdn: proxmox-server.netbird.selfhosted + ip: 100.122.38.109 mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library -ssh: - port: 22 - netbird_port: 22022 - user: root + - /mnt/library +name: hubris +os: linux +role: hypervisor runs: -- proxmox_ui -services_hosted: -- name: proxmox_ui - url: https://proxmox.hubris.network - backend: hubris - port: 8006 - doc_page: knowledge/wiki/hosts/hubris.md - risk_notes: "hypervisor UI \u2014 changes here affect every guest on the node" -age_pubkey: age1xkklkvnk5z0fsnh6cfgv70hy9ksfy8rdprwerzw4yk3p4p7cxcqs2yvpz6 -mcp_endpoint: https://mcp.hubris.network/mcp + - proxmox_ui secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: hubris + doc_page: knowledge/wiki/hosts/hubris.md + name: proxmox_ui + port: 8006 + risk_notes: hypervisor UI — changes here affect every guest on the node + url: https://proxmox.hubris.network +ssh: + netbird_port: 22022 + port: 22 + user: root +state: active diff --git a/hosts/jellyfin.yaml b/hosts/jellyfin.yaml index 67a871d..9265c68 100644 --- a/hosts/jellyfin.yaml +++ b/hosts/jellyfin.yaml @@ -1,39 +1,38 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: jellyfin -kind: lxc -os: linux -role: media-server -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: strong -pve_id: 101 +kind: lxc lan_ip: 192.168.8.246 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: jellyfin mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/media_local -public_host: media.hubris.network -runs: -- jellyfin -services_hosted: -- name: jellyfin - url: https://media.hubris.network - backend: jellyfin - doc_page: knowledge/wiki/containers/101-jellyfin.md - risk_notes: native Authentik OIDC via SSO-Auth plugin, no Caddy forward-auth gate; VAAPI transcode depends - on GPU passthrough on strong + - /mnt/media_local +name: jellyfin notes: -- Jellyfin 10.11.11 with VAAPI hardware acceleration (Radeon 680M iGPU on strong) -- 4 cores / 8 GiB RAM / 1 GiB swap -- SSO-Auth plugin v4.0.0.4 with Authentik OIDC (no Caddy forward-auth gate) -- GPU passed via dev0+dev1: /dev/dri/renderD128 + card0 -- Migrated from hubris to strong 2026-07-05 (Phase 2). Library on ludo-lvm. -mcp_endpoint: https://mcp.hubris.network/mcp + - Jellyfin 10.11.11 with VAAPI hardware acceleration (Radeon 680M iGPU on strong) + - 4 cores / 8 GiB RAM / 1 GiB swap + - SSO-Auth plugin v4.0.0.4 with Authentik OIDC (no Caddy forward-auth gate) + - GPU passed via dev0+dev1: /dev/dri/renderD128 + card0 + - Migrated from hubris to strong 2026-07-05 (Phase 2). Library on ludo-lvm. +os: linux +public_host: media.hubris.network +pve_id: 101 +role: media-server +runs: + - jellyfin secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: jellyfin + doc_page: knowledge/wiki/containers/101-jellyfin.md + name: jellyfin + risk_notes: native Authentik OIDC via SSO-Auth plugin, no Caddy forward-auth gate; VAAPI transcode depends on GPU passthrough on strong + url: https://media.hubris.network +state: active diff --git a/hosts/mac-mini.yaml b/hosts/mac-mini.yaml index 2784a70..e489e5a 100644 --- a/hosts/mac-mini.yaml +++ b/hosts/mac-mini.yaml @@ -1,24 +1,24 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: mac-mini +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + +age_pubkey: age1z62ff2ak9zj5ctcvaxwyyhedwjvlwgm2dkn9nk3wrwk8fkavcpmsqwc2vs kind: workstation -os: macos -role: dev -state: active lan_ip: 192.168.178.182 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: netbird: fqdn: mac-mini-234-17.netbird.selfhosted mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird +name: mac-mini +notes: + - Only macOS in the fleet. Bootstrap uses launchd. +os: macos +role: dev +secrets_issuance_endpoint: https://secrets.hubris.network/issue ssh: user: dtoro -notes: -- Only macOS in the fleet. Bootstrap uses launchd. -age_pubkey: age1z62ff2ak9zj5ctcvaxwyyhedwjvlwgm2dkn9nk3wrwk8fkavcpmsqwc2vs -mcp_endpoint: https://mcp.hubris.network/mcp -secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/mule-images.yaml b/hosts/mule-images.yaml index ea596d1..db74ba9 100644 --- a/hosts/mule-images.yaml +++ b/hosts/mule-images.yaml @@ -1,32 +1,32 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: mule-images -kind: lxc -os: linux -role: photo-management -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 120 +kind: lxc lan_ip: 192.168.8.136 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: muleimage mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library + - /mnt/library +name: mule-images +os: linux public_host: photos.hubris.network +pve_id: 120 +role: photo-management runs: -- photos -services_hosted: -- name: photos - url: https://photos.hubris.network - backend: mule-images - doc_page: knowledge/wiki/containers/120-mule-images.md - config_repo: dtoro/mule-image -mcp_endpoint: https://mcp.hubris.network/mcp + - photos secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: mule-images + config_repo: dtoro/mule-image + doc_page: knowledge/wiki/containers/120-mule-images.md + name: photos + url: https://photos.hubris.network +state: active diff --git a/hosts/netbird-vps.yaml b/hosts/netbird-vps.yaml index fc468d1..3c0a59b 100644 --- a/hosts/netbird-vps.yaml +++ b/hosts/netbird-vps.yaml @@ -1,40 +1,35 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: netbird-vps +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + kind: external -os: linux -role: netbird-mgmt -state: active +mcp_endpoint: https://mcp.hubris.network/mcp mesh: netbird: - ip: 100.122.165.149 fqdn: netbird-ionos.netbird.selfhosted + ip: 100.122.165.149 mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird +name: netbird-vps +notes: + - Public IONOS VPS — hosts the vanilla netbird mgmt+signal+relay+dashboard stack + host coturn (see infrastructure/vps-hardening.md + infrastructure/mesh.md changelog 2026-05-21). + - NOT a homelab client. No /etc/age/key.txt, no /opt/homelab-context clone. Managed via ssh from hubris; sshd is locked to hubris's pubkey. + - Public IPv4 82.165.190.79. Auto-patching via unattended-upgrades. + - Configs rendered by `homelab render-vps-configs` from vps/turnserver.conf.tmpl + vps/management.json.tmpl, with secrets decrypted from secrets/turn-shared-secret.yaml + secrets/netbird-authentik-oidc.yaml on hubris. +os: linux +role: netbird-mgmt +runs: + - authentik +secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: netbird-vps + doc_page: knowledge/wiki/containers/106-auth-outpost.md + name: authentik + note: core runs on the VPS since 2026-05-31; LAN forward-auth outpost is auth-outpost (LXC 106) at 192.168.8.6:9000. Previous backend value "authentik" referenced the retired embedded-outpost host (LXC 124). + risk_notes: SSO provider — outage locks login to OIDC/forward-auth services + url: https://auth.hubris.network ssh: user: root -runs: -- authentik -services_hosted: -- name: authentik - url: https://auth.hubris.network - backend: netbird-vps - doc_page: knowledge/wiki/containers/106-auth-outpost.md - note: core runs on the VPS since 2026-05-31; LAN forward-auth outpost is auth-outpost (LXC 106) at 192.168.8.6:9000. - Previous backend value "authentik" referenced the retired embedded-outpost host (LXC 124). - risk_notes: "SSO provider \u2014 outage locks login to OIDC/forward-auth services" -notes: -- "Public IONOS VPS \u2014 hosts the vanilla netbird mgmt+signal+relay+dashboard stack + host coturn (see\ - \ infrastructure/vps-hardening.md + infrastructure/mesh.md changelog 2026-05-21)." -- NOT a homelab client. No /etc/age/key.txt, no /opt/homelab-context clone. Managed via ssh from hubris; - sshd is locked to hubris's pubkey. -- Public IPv4 82.165.190.79. Auto-patching via unattended-upgrades. -- Configs rendered by `homelab render-vps-configs` from vps/turnserver.conf.tmpl + vps/management.json.tmpl, - with secrets decrypted from secrets/turn-shared-secret.yaml + secrets/netbird-authentik-oidc.yaml on - hubris. -mcp_endpoint: https://mcp.hubris.network/mcp -secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/nextcloud.yaml b/hosts/nextcloud.yaml index b81b3a4..0a91bdf 100644 --- a/hosts/nextcloud.yaml +++ b/hosts/nextcloud.yaml @@ -1,31 +1,31 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: nextcloud -kind: lxc -os: linux -role: file-sync -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 114 +kind: lxc lan_ip: 192.168.8.224 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: nextcloud mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library + - /mnt/library +name: nextcloud +os: linux public_host: cloud.hubris.network +pve_id: 114 +role: file-sync runs: -- nextcloud -services_hosted: -- name: nextcloud - url: https://cloud.hubris.network - backend: nextcloud - doc_page: knowledge/wiki/containers/114-nextcloud.md -mcp_endpoint: https://mcp.hubris.network/mcp + - nextcloud secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: nextcloud + doc_page: knowledge/wiki/containers/114-nextcloud.md + name: nextcloud + url: https://cloud.hubris.network +state: active diff --git a/hosts/nfs-export.yaml b/hosts/nfs-export.yaml index abcff5c..2c5c993 100644 --- a/hosts/nfs-export.yaml +++ b/hosts/nfs-export.yaml @@ -1,18 +1,18 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: nfs-export -kind: lxc -os: linux -role: storage-export -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 102 +kind: lxc lan_ip: 192.168.8.200 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: nfs-export +os: linux +pve_id: 102 +role: storage-export secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/paperless.yaml b/hosts/paperless.yaml index b836978..a2ffa7e 100644 --- a/hosts/paperless.yaml +++ b/hosts/paperless.yaml @@ -1,32 +1,32 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: paperless -kind: lxc -os: linux -role: document-archive -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 103 +kind: lxc lan_ip: 192.168.8.130 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: paperless mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library + - /mnt/library +name: paperless +os: linux public_host: paperless.hubris.network +pve_id: 103 +role: document-archive runs: -- paperless -services_hosted: -- name: paperless - url: https://paperless.hubris.network - backend: paperless - doc_page: knowledge/wiki/containers/103-paperless.md - risk_notes: "document archive \u2014 treat data as irreplaceable; DB operations are destructive-class" -mcp_endpoint: https://mcp.hubris.network/mcp + - paperless secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: paperless + doc_page: knowledge/wiki/containers/103-paperless.md + name: paperless + risk_notes: document archive — treat data as irreplaceable; DB operations are destructive-class + url: https://paperless.hubris.network +state: active diff --git a/hosts/rclone.yaml b/hosts/rclone.yaml index 899f78e..e88adaa 100644 --- a/hosts/rclone.yaml +++ b/hosts/rclone.yaml @@ -1,19 +1,19 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: rclone +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + +age_pubkey: age1pwtdws2thdh7vzp2dzttl3zxgcs2tgpcsjsqgw3q04nyml4kvuqq467u4x kind: lxc -os: linux -role: backup -state: active +mcp_endpoint: https://mcp.hubris.network/mcp mesh: netbird: fqdn: rclone.netbird.selfhosted mesh_globals: - primary: netbird accepted: - - netbird - - tailscale -age_pubkey: age1pwtdws2thdh7vzp2dzttl3zxgcs2tgpcsjsqgw3q04nyml4kvuqq467u4x -mcp_endpoint: https://mcp.hubris.network/mcp + - netbird + - tailscale + primary: netbird +name: rclone +os: linux +role: backup secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/republic-laptop.yaml b/hosts/republic-laptop.yaml index c3a280a..6f1bd6c 100644 --- a/hosts/republic-laptop.yaml +++ b/hosts/republic-laptop.yaml @@ -1,20 +1,20 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: republic-laptop +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + kind: workstation -os: linux -role: primary-dev -state: active +mcp_endpoint: https://mcp.hubris.network/mcp mesh: netbird: fqdn: republic-laptop.netbird.selfhosted mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird +name: republic-laptop +os: linux +role: primary-dev +secrets_issuance_endpoint: https://secrets.hubris.network/issue ssh: user: dtoro -mcp_endpoint: https://mcp.hubris.network/mcp -secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/romm.yaml b/hosts/romm.yaml index 91c2674..37f1b69 100644 --- a/hosts/romm.yaml +++ b/hosts/romm.yaml @@ -1,26 +1,26 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: romm -kind: lxc -os: linux -role: rom-manager -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: strong -pve_id: 134 +kind: lxc lan_ip: 192.168.8.249 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -mounts: -- /mnt/media_local -public_host: roms.hubris.network -notes: -- Docker host for RomM (romm.app) self-hosted ROM manager. Created 2026-07-05. -- MariaDB sidecar at /opt/romm/docker-compose.yml. -- ROMs on ludo-lvm media volume at /mnt/media_local/roms. -- 1 core / 2 GiB RAM / 16 GiB rootfs (ludo-lvm). mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +mounts: + - /mnt/media_local +name: romm +notes: + - Docker host for RomM (romm.app) self-hosted ROM manager. Created 2026-07-05. + - MariaDB sidecar at /opt/romm/docker-compose.yml. + - ROMs on ludo-lvm media volume at /mnt/media_local/roms. + - 1 core / 2 GiB RAM / 16 GiB rootfs (ludo-lvm). +os: linux +public_host: roms.hubris.network +pve_id: 134 +role: rom-manager secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/seanime.yaml b/hosts/seanime.yaml index 8344a10..a522c40 100644 --- a/hosts/seanime.yaml +++ b/hosts/seanime.yaml @@ -1,29 +1,29 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: seanime -kind: lxc -os: linux -role: anime-media-server -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: strong -pve_id: 133 +kind: lxc lan_ip: 192.168.8.248 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -mounts: -- /mnt/media_local/anime -public_host: seanime.hubris.network -notes: -- Seanime anime media server for online streaming + local library scanning -- Created 2026-07-05. Binary at /opt/seanime/bin/seanime, systemd service. -- Connected to qBittorrent on arriman (192.168.8.245:8080) -- 8 online streaming extensions installed (HiAnime, AniWatch, KickAssAnime, etc.) -- /anime mounted from strong ludo-lvm (/mnt/media_local/anime) -- Caddy: "https://seanime.hubris.network \u2192 192.168.8.248:43211" -- qBittorrent auth subnet whitelist expanded to 192.168.8.0/24 for seanime access mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +mounts: + - /mnt/media_local/anime +name: seanime +notes: + - Seanime anime media server for online streaming + local library scanning + - Created 2026-07-05. Binary at /opt/seanime/bin/seanime, systemd service. + - Connected to qBittorrent on arriman (192.168.8.245:8080) + - 8 online streaming extensions installed (HiAnime, AniWatch, KickAssAnime, etc.) + - /anime mounted from strong ludo-lvm (/mnt/media_local/anime) + - Caddy: https://seanime.hubris.network → 192.168.8.248:43211 + - qBittorrent auth subnet whitelist expanded to 192.168.8.0/24 for seanime access +os: linux +public_host: seanime.hubris.network +pve_id: 133 +role: anime-media-server secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/sophia.yaml b/hosts/sophia.yaml index 87e3efe..42d63ff 100644 --- a/hosts/sophia.yaml +++ b/hosts/sophia.yaml @@ -1,23 +1,23 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: sophia -kind: lxc -os: linux -role: workshop -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 119 +kind: lxc lan_ip: 192.168.8.109 +mcp_endpoint: https://mcp.hubris.network/mcp mesh: tailscale: fqdn: sophia mesh_globals: - primary: netbird accepted: - - netbird - - tailscale + - netbird + - tailscale + primary: netbird mounts: -- /mnt/library -mcp_endpoint: https://mcp.hubris.network/mcp + - /mnt/library +name: sophia +os: linux +pve_id: 119 +role: workshop secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/strong.yaml b/hosts/strong.yaml index b0d2fab..83d924a 100644 --- a/hosts/strong.yaml +++ b/hosts/strong.yaml @@ -1,32 +1,24 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: strong +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + +age_pubkey: age1rtwvdct6avjkr3cyxv3vue3vqx4d524fjfr3vk7xrnvyrylnry5sm54sn4 kind: proxmox-host +lan_ip: 192.168.178.181 +mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: strong +notes: + - Reformatted from Linux workstation ("ludo-mini" in this wiki, still the machine's nickname) to Proxmox VE 9.2.3 on 2026-07-01. Renamed the inventory/wiki identity from ludo-mini to strong on the same day so it matches the OS/cluster hostname everywhere (bootstrap looks up hosts/$(hostname).yaml, so a mismatch would break enrollment). + - Joined hubris's "Homelab" cluster same day. 2-node, no QDevice tiebreaker yet — see hosts/hubris.md quorum note. + - Netbird not yet installed (fresh OS wiped prior enrollment); reachable today only via the household LAN / existing Fritz static route to 192.168.8.0/24. Re-enroll in mesh as a follow-up if off-LAN access to this host itself (not just its future guests) is needed. + - First step of the planned library-SSD migration — see .hermes/plans/2026-06-03_110000-library-ssd-migration-to-ludo-mini.md (filename kept as-is, it's a historical planning doc). Only Phase 1 (Proxmox install + cluster join) is done; no physical drive move, service migration, or GPU passthrough has happened yet. os: linux role: hypervisor -state: active -lan_ip: 192.168.178.181 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale +secrets_issuance_endpoint: https://secrets.hubris.network/issue ssh: user: root -notes: -- Reformatted from Linux workstation ("ludo-mini" in this wiki, still the machine's nickname) to Proxmox - VE 9.2.3 on 2026-07-01. Renamed the inventory/wiki identity from ludo-mini to strong on the same day - so it matches the OS/cluster hostname everywhere (bootstrap looks up hosts/$(hostname).yaml, so a mismatch - would break enrollment). -- "Joined hubris's \"Homelab\" cluster same day. 2-node, no QDevice tiebreaker yet \u2014 see hosts/hubris.md\ - \ quorum note." -- Netbird not yet installed (fresh OS wiped prior enrollment); reachable today only via the household - LAN / existing Fritz static route to 192.168.8.0/24. Re-enroll in mesh as a follow-up if off-LAN access - to this host itself (not just its future guests) is needed. -- "First step of the planned library-SSD migration \u2014 see .hermes/plans/2026-06-03_110000-library-ssd-migration-to-ludo-mini.md\ - \ (filename kept as-is, it's a historical planning doc). Only Phase 1 (Proxmox install + cluster join)\ - \ is done; no physical drive move, service migration, or GPU passthrough has happened yet." -age_pubkey: age1rtwvdct6avjkr3cyxv3vue3vqx4d524fjfr3vk7xrnvyrylnry5sm54sn4 -mcp_endpoint: https://mcp.hubris.network/mcp -secrets_issuance_endpoint: https://secrets.hubris.network/issue +state: active diff --git a/hosts/teddycloud.yaml b/hosts/teddycloud.yaml index 15bb9a3..02f1b51 100644 --- a/hosts/teddycloud.yaml +++ b/hosts/teddycloud.yaml @@ -1,42 +1,35 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: teddycloud -kind: lxc -os: linux -role: teddycloud -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 131 +kind: lxc lan_ip: 192.168.8.150 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -mounts: -- /mnt/library -public_host: teddy.hubris.network -runs: -- teddycloud -services_hosted: -- name: teddycloud - url: https://teddy.hubris.network - backend: teddycloud - doc_page: knowledge/wiki/containers/131-teddycloud.md - note: self-hosted TeddyCloud (Toniebox cloud reimplementation), docker compose - risk_notes: "no Caddy forward-auth gate (unlike sab.hubris.network on the same Caddyfile) \u2014 reachable\ - \ to anyone on the LAN/mesh who can resolve teddy.hubris.network; undocumented in inventory.yaml until\ - \ 2026-07-06 (drift-caught)" -notes: -- Docker host for TeddyCloud (ghcr.io/toniebox-reverse-engineering/teddycloud), a self-hosted reimplementation - of the Toniebox cloud backend. Debian 12 (bookworm). -- 1 core / 1 GiB RAM / 512 MiB swap / 16 GiB rootfs (local-lvm). -- "Predates the client-enrollment convention \u2014 undocumented in inventory.yaml until 2026-07-06, when\ - \ Oikos's drift detector (oikos/drift.py) caught pve_id 131 live on hubris (`pct list`) with no inventory\ - \ entry. Static IP assigned 2026-07-05 during the strong migration (was picking up 192.168.8.243 via\ - \ DHCP before that \u2014 see hosts/strong.md's 2026-07-05 changelog)." -- "No age_pubkey / homelab-context enrollment \u2014 not a homelab CLI client, just a docker-compose app\ - \ container. Not a required follow-up unless it needs secrets." mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +mounts: + - /mnt/library +name: teddycloud +notes: + - Docker host for TeddyCloud (ghcr.io/toniebox-reverse-engineering/teddycloud), a self-hosted reimplementation of the Toniebox cloud backend. Debian 12 (bookworm). + - 1 core / 1 GiB RAM / 512 MiB swap / 16 GiB rootfs (local-lvm). + - Predates the client-enrollment convention — undocumented in inventory.yaml until 2026-07-06, when Oikos's drift detector (oikos/drift.py) caught pve_id 131 live on hubris (`pct list`) with no inventory entry. Static IP assigned 2026-07-05 during the strong migration (was picking up 192.168.8.243 via DHCP before that — see hosts/strong.md's 2026-07-05 changelog). + - No age_pubkey / homelab-context enrollment — not a homelab CLI client, just a docker-compose app container. Not a required follow-up unless it needs secrets. +os: linux +public_host: teddy.hubris.network +pve_id: 131 +role: teddycloud +runs: + - teddycloud secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: teddycloud + doc_page: knowledge/wiki/containers/131-teddycloud.md + name: teddycloud + note: self-hosted TeddyCloud (Toniebox cloud reimplementation), docker compose + risk_notes: no Caddy forward-auth gate (unlike sab.hubris.network on the same Caddyfile) — reachable to anyone on the LAN/mesh who can resolve teddy.hubris.network; undocumented in inventory.yaml until 2026-07-06 (drift-caught) + url: https://teddy.hubris.network +state: active diff --git a/hosts/trmnl.yaml b/hosts/trmnl.yaml index 937dea7..5746e7d 100644 --- a/hosts/trmnl.yaml +++ b/hosts/trmnl.yaml @@ -1,28 +1,28 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: trmnl -kind: lxc -os: linux -role: trmnl-middleware -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 128 +kind: lxc lan_ip: 192.168.8.211 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -public_host: trmnl.hubris.network -runs: -- trmnl -services_hosted: -- name: trmnl - backend: trmnl - url: https://trmnl.hubris.network - note: self-hosted middleware for TRMNL e-ink plugins (polled by TRMNL cloud) - doc_page: knowledge/wiki/containers/128-trmnl.md - config_repo: dtoro/terminalito mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: trmnl +os: linux +public_host: trmnl.hubris.network +pve_id: 128 +role: trmnl-middleware +runs: + - trmnl secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: trmnl + config_repo: dtoro/terminalito + doc_page: knowledge/wiki/containers/128-trmnl.md + name: trmnl + note: self-hosted middleware for TRMNL e-ink plugins (polled by TRMNL cloud) + url: https://trmnl.hubris.network +state: active diff --git a/hosts/zimaos.yaml b/hosts/zimaos.yaml index a384967..820faf4 100644 --- a/hosts/zimaos.yaml +++ b/hosts/zimaos.yaml @@ -1,26 +1,26 @@ -# Generated by mcp/build_host_files.py from inventory.yaml. -# Do NOT edit by hand — your changes will be overwritten. -# Source of truth: ../inventory.yaml -name: zimaos -kind: vm -os: linux -role: nas-frontend-eval -state: active +# Generated by oikos build-hosts from inventory.yaml. +# Do NOT edit by hand. + host: hubris -pve_id: 100 +kind: vm lan_ip: 192.168.8.195 -mesh_globals: - primary: netbird - accepted: - - netbird - - tailscale -public_host: zimaos.hubris.network -runs: -- zimaos -services_hosted: -- name: zimaos - url: https://zimaos.hubris.network - backend: zimaos - doc_page: knowledge/wiki/vms/100-zimaos.md mcp_endpoint: https://mcp.hubris.network/mcp +mesh_globals: + accepted: + - netbird + - tailscale + primary: netbird +name: zimaos +os: linux +public_host: zimaos.hubris.network +pve_id: 100 +role: nas-frontend-eval +runs: + - zimaos secrets_issuance_endpoint: https://secrets.hubris.network/issue +services_hosted: + - backend: zimaos + doc_page: knowledge/wiki/vms/100-zimaos.md + name: zimaos + url: https://zimaos.hubris.network +state: active