I — run pre-flights QEMU guest agent before queueing VM execution classifyAndGate now checks vm: targets for qemu_guest_agent attribute. If not_running/missing, returns immediate error instead of queuing forever. II — policy.yaml: documented host-mutation classifier rule Added comment clarifying that host-level package/kernel mutations (apt-get install, dpkg, systemctl enable) always classify as config_mutation and thus need operator approval. III — health attribute read-only in update_entity_attributes Strips scheduler-owned keys (health, last_check_at, last_check) from attribute updates with a clear message directing agents to get_health_summary / list_checks instead. IV — Recorded discovered dependency edges vm:zimaos → depends-on → lxc:nfs-export (NFS /media/library mount) vm:zimaos → depends-on → host:strong (NFS /media/ludo-library mount) Also updated the run tool description to mention both guardrails.
651 lines
44 KiB
YAML
651 lines
44 KiB
YAML
# Oikos inventory seed — entity instances + relationships.
|
|
#
|
|
# Translated from the legacy /inventory.yaml (2026-07-07). Bootstraps the
|
|
# entities/relationships tables (migration 002); after ingest the DB is
|
|
# authoritative and this file is regenerated by `GET /api/v1/export`.
|
|
#
|
|
# Slug conventions: <prefix>:<name> —
|
|
# host: (proxmox-host, standalone-server) · ws: (workstation) · lxc: · vm:
|
|
# service: · ingress: · repo: (config-repo) · pool: · volume: · mesh: · lan:
|
|
# zone: (dns-zone) · idp: · person: · agent: · cluster: · backup:
|
|
#
|
|
# `state:` omitted = the type's lifecycle default (active).
|
|
# Mount details (mount_point) are attributes on `mounts` edges.
|
|
# Known thin spots are marked # THIN: backfill later.
|
|
|
|
version: 1
|
|
|
|
entities:
|
|
|
|
# ─── Sites, networks ───────────────────────────────────────────────
|
|
- {slug: "site:home", type: site, name: home}
|
|
- {slug: "site:ionos-dc", type: site, name: ionos-dc,
|
|
attributes: {address: IONOS datacenter (VPS)}}
|
|
- slug: "lan:lab"
|
|
type: lan
|
|
name: lab
|
|
attributes: {subnet: 192.168.8.0/24}
|
|
- slug: "lan:household"
|
|
type: lan
|
|
name: household
|
|
attributes: {subnet: 192.168.178.0/24} # Fritz LAN; static route to lab subnet
|
|
- slug: "mesh:netbird"
|
|
type: mesh
|
|
name: netbird
|
|
attributes:
|
|
provider: netbird
|
|
subnet: 100.122.0.0/16
|
|
domain: netbird.selfhosted
|
|
- slug: "mesh:tailscale"
|
|
type: mesh
|
|
name: tailscale
|
|
state: deprecated # migration to netbird in progress (infrastructure/mesh.md)
|
|
attributes: {provider: tailscale}
|
|
- slug: "zone:hubris.network"
|
|
type: dns-zone
|
|
name: hubris.network
|
|
attributes: {zone: hubris.network, authority: "Technitium (LXC 107), split-horizon"}
|
|
- slug: "zone:netbird.selfhosted"
|
|
type: dns-zone
|
|
name: netbird.selfhosted
|
|
attributes: {zone: netbird.selfhosted, authority: netbird-mgmt}
|
|
|
|
# ─── Machines ──────────────────────────────────────────────────────
|
|
- slug: "cluster:homelab"
|
|
type: cluster
|
|
name: Homelab
|
|
attributes: {quorum: "2-node, no QDevice tiebreaker yet"}
|
|
- slug: "host:hubris"
|
|
type: proxmox-host
|
|
name: hubris
|
|
attributes:
|
|
os: linux
|
|
lan_ip: 192.168.8.77
|
|
mesh: {netbird: {ip: 100.122.38.109, fqdn: proxmox-server.netbird.selfhosted}}
|
|
ssh: {port: 22, netbird_port: 22022, user: root}
|
|
age_pubkey: age1xkklkvnk5z0fsnh6cfgv70hy9ksfy8rdprwerzw4yk3p4p7cxcqs2yvpz6
|
|
- slug: "host:strong"
|
|
type: proxmox-host
|
|
name: strong
|
|
attributes:
|
|
os: linux
|
|
lan_ip: 192.168.178.181
|
|
ssh: {user: root}
|
|
age_pubkey: age1rtwvdct6avjkr3cyxv3vue3vqx4d524fjfr3vk7xrnvyrylnry5sm54sn4
|
|
note: >-
|
|
PVE 9.2.3 since 2026-07-01 (formerly workstation ludo-mini). Joined
|
|
Homelab cluster same day. Not yet netbird-enrolled — reachable via
|
|
household LAN / Fritz static route only.
|
|
- slug: "host:netbird-vps"
|
|
type: standalone-server
|
|
name: netbird-vps
|
|
attributes:
|
|
os: linux
|
|
provider: ionos
|
|
control_level: partial # managed via ssh from hubris; not a homelab client
|
|
public_ipv4: 82.165.190.79
|
|
mesh: {netbird: {ip: 100.122.165.149, fqdn: netbird-ionos.netbird.selfhosted}}
|
|
ssh: {user: root}
|
|
note: netbird mgmt+signal+relay+dashboard + coturn; sshd locked to hubris pubkey
|
|
monitoring: [http] # public HTTPS probe via https://mcp.hubris.network
|
|
# (2026-08-05: was `none` — the VPS went silent for
|
|
# 7 days because nothing probed it. The standalone-server
|
|
# type inherits [ping,resource,updates] from machine, but
|
|
# SSH/ICMP don't reach it from the lab; an HTTP probe on
|
|
# the public endpoint is the reachable liveness signal).
|
|
- slug: "ws:mac-mini"
|
|
type: workstation
|
|
name: mac-mini
|
|
attributes:
|
|
os: macos
|
|
user: dtoro
|
|
lan_ip: 192.168.178.182
|
|
mesh: {netbird: {fqdn: mac-mini-234-17.netbird.selfhosted}}
|
|
age_pubkey: age169104ee1a9e1577d493820830560197f0adf56bf8f1c369d57c152c03f9437ae
|
|
note: only macOS in fleet; Oikos Docker host. Enrolled 2026-07-08.
|
|
enrolled_at: "2026-07-08T09:49:03Z"
|
|
mesh_ip: 192.168.178.182
|
|
hostname: mac-mini
|
|
- slug: "ws:republic-laptop"
|
|
type: workstation
|
|
name: republic-laptop
|
|
attributes:
|
|
os: linux
|
|
user: dtoro
|
|
mesh: {netbird: {fqdn: republic-laptop.netbird.selfhosted}}
|
|
|
|
# ─── LXCs ──────────────────────────────────────────────────────────
|
|
- {slug: "lxc:jellyfin", type: lxc, name: jellyfin,
|
|
attributes: {pve_id: 101, role: media-server, lan_ip: 192.168.8.246,
|
|
public_host: media.hubris.network,
|
|
note: "VAAPI transcode via Radeon 680M passthrough; migrated hubris→strong 2026-07-05"}}
|
|
- {slug: "lxc:nfs-export", type: lxc, name: nfs-export,
|
|
attributes: {pve_id: 102, role: storage-export, lan_ip: 192.168.8.200}}
|
|
- {slug: "lxc:paperless", type: lxc, name: paperless,
|
|
attributes: {pve_id: 103, role: document-archive, lan_ip: 192.168.8.130,
|
|
public_host: paperless.hubris.network}}
|
|
- {slug: "lxc:gitea", type: lxc, name: gitea,
|
|
attributes: {pve_id: 104, role: git-server, lan_ip: 192.168.8.121,
|
|
public_host: git.hubris.network,
|
|
note: "bare repos at /mnt/library/repos/dtoro/*.git"}}
|
|
- {slug: "lxc:apps", type: lxc, name: apps,
|
|
attributes: {pve_id: 105, role: docker-apps, lan_ip: 192.168.8.205,
|
|
age_pubkey: age1duyl8mkpgu80uv934dy8q7enqjms6yvdz264hme8uryuxmvvqesq6rusq0,
|
|
note: "legacy Oikos host; fallback during cutover (plan A6)"}}
|
|
- {slug: "lxc:auth-outpost", type: lxc, name: auth-outpost,
|
|
attributes: {pve_id: 106, role: authentik-gateway, lan_ip: 192.168.8.6}}
|
|
- {slug: "lxc:dns", type: lxc, name: dns,
|
|
attributes: {pve_id: 107, role: dns-server, lan_ip: 192.168.8.2}}
|
|
- {slug: "lxc:nextcloud", type: lxc, name: nextcloud,
|
|
attributes: {pve_id: 114, role: file-sync, lan_ip: 192.168.8.224,
|
|
public_host: cloud.hubris.network}}
|
|
- {slug: "lxc:elementsynapse", type: lxc, name: elementsynapse,
|
|
attributes: {pve_id: 118, role: matrix-server, lan_ip: 192.168.8.242,
|
|
public_host: matrix.hubris.network,
|
|
note: "migrated hubris→strong 2026-07-05"}}
|
|
- {slug: "lxc:sophia", type: lxc, name: sophia,
|
|
attributes: {pve_id: 119, role: workshop, lan_ip: 192.168.8.109}}
|
|
- {slug: "lxc:mule-images", type: lxc, name: mule-images,
|
|
attributes: {pve_id: 120, role: photo-management, lan_ip: 192.168.8.136,
|
|
public_host: photos.hubris.network}}
|
|
- {slug: "lxc:caddy", type: lxc, name: caddy,
|
|
attributes: {pve_id: 121, role: reverse-proxy, lan_ip: 192.168.8.175,
|
|
note: "terminates all *.hubris.network; /etc/caddy is a checkout of dtoro/caddy-conf"}}
|
|
- {slug: "lxc:arriman", type: lxc, name: arriman,
|
|
attributes: {pve_id: 122, role: arr-stack, lan_ip: 192.168.8.245,
|
|
public_hosts: [jellyseerr.hubris.network, qbit.hubris.network, sab.hubris.network],
|
|
note: "homarr/radarr/sonarr/lidarr/sab/qbit/bazarr/flaresolverr/prowlarr/jellyseerr; migrated to strong 2026-07-05"}}
|
|
- {slug: "lxc:trmnl", type: lxc, name: trmnl,
|
|
attributes: {pve_id: 128, role: trmnl-middleware, lan_ip: 192.168.8.211,
|
|
public_host: trmnl.hubris.network,
|
|
note: "not yet mesh/SOPS-enrolled"}}
|
|
- {slug: "lxc:house", type: lxc, name: house,
|
|
attributes: {pve_id: 129, role: family-planner, lan_ip: 192.168.8.244,
|
|
public_host: house.hubris.network,
|
|
age_pubkey: age1s07zs83ehtlg8jtwvr75ltc3c4cdlemfwjuxrwjtwkqxkl9tpggsyrzn2h,
|
|
note: "Yuvomi + WebDAV bridge to paperless; migrated to strong 2026-07-05"}}
|
|
- {slug: "lxc:grimmory", type: lxc, name: grimmory,
|
|
attributes: {pve_id: 130, role: book-library, lan_ip: 192.168.8.247,
|
|
public_host: books.hubris.network,
|
|
age_pubkey: age1uellsemnjrzgfg9fxw4jefpy05laxzggwnwhh6ny3wl7alyp6v8q0muxet}}
|
|
- {slug: "lxc:teddycloud", type: lxc, name: teddycloud,
|
|
attributes: {pve_id: 131, role: teddycloud, lan_ip: 192.168.8.150,
|
|
public_host: teddy.hubris.network,
|
|
note: "drift-caught 2026-07-06; no forward-auth gate on route; not a homelab client"}}
|
|
- {slug: "lxc:rclone", type: lxc, name: rclone,
|
|
attributes: {pve_id: 132, role: backup,
|
|
mesh: {netbird: {fqdn: rclone.netbird.selfhosted}},
|
|
age_pubkey: age1pwtdws2thdh7vzp2dzttl3zxgcs2tgpcsjsqgw3q04nyml4kvuqq467u4x}}
|
|
# verified live on hubris 2026-07-07 (pct list via MCP)
|
|
- {slug: "lxc:seanime", type: lxc, name: seanime,
|
|
attributes: {pve_id: 133, role: anime-media-server, lan_ip: 192.168.8.248,
|
|
public_host: seanime.hubris.network,
|
|
note: "systemd service at /opt/seanime; uses qbittorrent on arriman"}}
|
|
- {slug: "lxc:romm", type: lxc, name: romm,
|
|
attributes: {pve_id: 134, role: rom-manager, lan_ip: 192.168.8.249,
|
|
public_host: roms.hubris.network,
|
|
note: "docker compose + MariaDB sidecar at /opt/romm"}}
|
|
|
|
# ─── VMs ───────────────────────────────────────────────────────────
|
|
- {slug: "vm:zimaos", type: vm, name: zimaos,
|
|
attributes: {pve_id: 100, role: nas-frontend-eval, lan_ip: 192.168.8.195,
|
|
public_host: zimaos.hubris.network}}
|
|
- {slug: "vm:haos", type: vm, name: haos,
|
|
attributes: {pve_id: 108, role: home-automation, lan_ip: 192.168.8.101}}
|
|
|
|
# ─── Storage ───────────────────────────────────────────────────────
|
|
- {slug: "pool:local-lvm-hubris", type: storage-pool, name: local-lvm (hubris),
|
|
attributes: {type: lvm}}
|
|
- {slug: "pool:library-hubris", type: storage-pool, name: library (hubris),
|
|
attributes: {type: lvmthin, capacity_gb: 3700}}
|
|
# 2nd Samsung 990 EVO Plus NVMe; backs /mnt/library ext4 via
|
|
# /dev/mapper/library-library (knowledge/wiki/hosts/hubris.md)
|
|
- {slug: "pool:ludo-lvm", type: storage-pool, name: ludo-lvm (strong),
|
|
attributes: {type: lvm}}
|
|
- {slug: "volume:library", type: volume, name: library,
|
|
attributes: {path: /mnt/library, size_gb: 3700}}
|
|
- {slug: "volume:media-local", type: volume, name: media-local,
|
|
attributes: {path: /mnt/media_local}}
|
|
- {slug: "backup:proton-drive", type: backup-target, name: proton-drive,
|
|
attributes: {provider: proton, encrypted: true,
|
|
path: /mnt/backup,
|
|
note: "rclone stages here before pushing to Proton; freshness is checked on lxc:rclone via the backs-up-to edge"}}
|
|
# The pre-deploy pg_dump written by scripts/deploy.sh on every push to main.
|
|
# It was the lab's only untracked backup: its failure path is `|| echo
|
|
# WARNING` inside the deploy script, so a broken dump was invisible until a
|
|
# rollback needed it.
|
|
- {slug: "backup:oikos-predeploy", type: backup-target, name: oikos-predeploy,
|
|
attributes: {provider: local, encrypted: false,
|
|
path: /opt/oikos/backups,
|
|
note: "pre-deploy pg_dump on the mac-mini; one per deployed SHA"}}
|
|
|
|
# ─── Services ──────────────────────────────────────────────────────
|
|
- {slug: "service:proxmox-ui", type: service, name: proxmox_ui,
|
|
attributes: {url: "https://proxmox.hubris.network", port: 8006,
|
|
doc_page: knowledge/wiki/hosts/hubris.md,
|
|
risk_notes: "hypervisor UI — changes affect every guest on the node"}}
|
|
- {slug: "service:gitea", type: service, name: gitea,
|
|
attributes: {url: "https://git.hubris.network", port: 3000,
|
|
doc_page: knowledge/wiki/containers/104-gitea.md,
|
|
risk_notes: "hosts all config repos + deploy webhooks; outage blocks auto-deploy and sync"}}
|
|
- {slug: "service:caddy", type: service, name: caddy,
|
|
attributes: {doc_page: knowledge/wiki/containers/121-caddy.md,
|
|
risk_notes: "wide blast radius — every *.hubris.network route rides on it"}}
|
|
- {slug: "service:authentik", type: service, name: authentik,
|
|
attributes: {url: "https://auth.hubris.network",
|
|
doc_page: knowledge/wiki/containers/106-auth-outpost.md,
|
|
note: "core on VPS since 2026-05-31; LAN outpost = auth-outpost (LXC 106) 192.168.8.6:9000",
|
|
risk_notes: "SSO provider — outage locks login to OIDC/forward-auth services"}}
|
|
- {slug: "service:dns", type: service, name: dns,
|
|
attributes: {doc_page: knowledge/wiki/containers/107-dns.md,
|
|
risk_notes: "LAN-wide resolver — misconfig breaks name resolution for every client"}}
|
|
- {slug: "service:jellyfin", type: service, name: jellyfin,
|
|
attributes: {url: "https://media.hubris.network",
|
|
doc_page: knowledge/wiki/containers/101-jellyfin.md,
|
|
risk_notes: "native Authentik OIDC (no forward-auth gate); VAAPI depends on GPU passthrough on strong"}}
|
|
- {slug: "service:nextcloud", type: service, name: nextcloud,
|
|
attributes: {url: "https://cloud.hubris.network",
|
|
doc_page: knowledge/wiki/containers/114-nextcloud.md}}
|
|
- {slug: "service:paperless", type: service, name: paperless,
|
|
attributes: {url: "https://paperless.hubris.network",
|
|
doc_page: knowledge/wiki/containers/103-paperless.md,
|
|
risk_notes: "document archive — data irreplaceable; DB operations are destructive-class"}}
|
|
- {slug: "service:matrix", type: service, name: matrix,
|
|
attributes: {url: "https://matrix.hubris.network",
|
|
doc_page: knowledge/wiki/containers/118-elementsynapse.md,
|
|
risk_notes: "alert/approval channel for Oikos — outage silences agent escalation"}}
|
|
- {slug: "service:photos", type: service, name: photos,
|
|
attributes: {url: "https://photos.hubris.network",
|
|
doc_page: knowledge/wiki/containers/120-mule-images.md}}
|
|
- {slug: "service:arr-stack", type: service, name: arr_stack,
|
|
attributes: {doc_page: knowledge/wiki/containers/122-arriman.md,
|
|
note: "jellyseerr / qbit / sab on docker compose"}}
|
|
- {slug: "service:artifacto", type: service, name: artifacto,
|
|
attributes: {url: "https://artifacto.hubris.network",
|
|
doc_page: knowledge/wiki/containers/105-apps.md}}
|
|
- {slug: "service:trmnl", type: service, name: trmnl,
|
|
attributes: {url: "https://trmnl.hubris.network",
|
|
doc_page: knowledge/wiki/containers/128-trmnl.md,
|
|
note: "TRMNL e-ink plugin middleware (polled by TRMNL cloud)"}}
|
|
- {slug: "service:zimaos", type: service, name: zimaos,
|
|
attributes: {url: "https://zimaos.hubris.network",
|
|
doc_page: knowledge/wiki/vms/100-zimaos.md}}
|
|
- {slug: "service:haos", type: service, name: haos,
|
|
attributes: {doc_page: knowledge/wiki/vms/108-haos.md,
|
|
monitoring: none}} # redundant: vm:haos covers liveness via vm-status; haos blocks SSH so a process check can't reach it
|
|
- {slug: "service:teddycloud", type: service, name: teddycloud,
|
|
attributes: {url: "https://teddy.hubris.network",
|
|
doc_page: knowledge/wiki/containers/131-teddycloud.md,
|
|
risk_notes: "no forward-auth gate — reachable by anyone on LAN/mesh"}}
|
|
# The Go control plane itself: api/scheduler/notifier/web on the mac-mini,
|
|
# and what mcp.hubris.network fronts since the cutover. It existed in the
|
|
# database (created outside the seed) but was never declared here, so a
|
|
# fresh seed could not resolve the routes-to edge below.
|
|
- {slug: "service:oikos", type: service, name: oikos,
|
|
attributes: {url: "https://oikos.hubris.network",
|
|
host: "ws:mac-mini",
|
|
ports: {api: 8090, web: 8091, nomos_gateway: 8092},
|
|
note: "homelab automation platform — api/scheduler/notifier/web on mac-mini docker compose (project name oikos)"}}
|
|
- {slug: "service:homelab-mcp", type: service, name: homelab_mcp,
|
|
attributes: {port: 9810, systemd_unit: homelab-mcp,
|
|
endpoint: "https://mcp.hubris.network/mcp",
|
|
doc_page: knowledge/wiki/infrastructure/homelab-context.md,
|
|
risk_notes: "agents' primary read surface — outage degrades every agent to grepping the clone"}}
|
|
- {slug: "service:secrets-issuance", type: service, name: secrets_issuance,
|
|
attributes: {port: 9820, systemd_unit: secrets-issuance,
|
|
endpoint: "https://secrets.hubris.network/issue",
|
|
doc_page: .agents/operations/agent-enrollment.md,
|
|
risk_notes: "identity issuance — security-sensitive; key operations are destructive-class"}}
|
|
# Services derived from hosts.public_host (no legacy services entry):
|
|
- {slug: "service:house", type: service, name: house,
|
|
attributes: {url: "https://house.hubris.network", note: "Yuvomi family planner (derived)"}}
|
|
- {slug: "service:grimmory", type: service, name: grimmory,
|
|
attributes: {url: "https://books.hubris.network", note: derived}}
|
|
- {slug: "service:seanime", type: service, name: seanime,
|
|
attributes: {url: "https://seanime.hubris.network", port: 43211, note: derived}}
|
|
- {slug: "service:romm", type: service, name: romm,
|
|
attributes: {url: "https://roms.hubris.network", note: derived}}
|
|
- {slug: "service:jellyseerr", type: service, name: jellyseerr,
|
|
attributes: {url: "https://jellyseerr.hubris.network", note: derived (arriman)}}
|
|
- {slug: "service:qbit", type: service, name: qbit,
|
|
attributes: {url: "https://qbit.hubris.network", note: derived (arriman)}}
|
|
- {slug: "service:sab", type: service, name: sab,
|
|
attributes: {url: "https://sab.hubris.network", note: "derived (arriman); forward-auth gated"}}
|
|
|
|
# ─── Config repos ──────────────────────────────────────────────────
|
|
- {slug: "repo:caddy-conf", type: config-repo, name: dtoro/caddy-conf}
|
|
- {slug: "repo:gitea-customizations", type: config-repo, name: dtoro/gitea-customizations}
|
|
- {slug: "repo:mule-image", type: config-repo, name: dtoro/mule-image}
|
|
- {slug: "repo:artifacto", type: config-repo, name: dtoro/Artifacto}
|
|
- {slug: "repo:terminalito", type: config-repo, name: dtoro/terminalito}
|
|
- {slug: "repo:homelab-docs", type: config-repo, name: dtoro/oikos}
|
|
|
|
# ─── Ingress routes (Caddy, *.hubris.network) ──────────────────────
|
|
- {slug: "ingress:proxmox.hubris.network", type: ingress-route, name: proxmox.hubris.network}
|
|
- {slug: "ingress:git.hubris.network", type: ingress-route, name: git.hubris.network}
|
|
- {slug: "ingress:auth.hubris.network", type: ingress-route, name: auth.hubris.network}
|
|
- {slug: "ingress:media.hubris.network", type: ingress-route, name: media.hubris.network}
|
|
- {slug: "ingress:cloud.hubris.network", type: ingress-route, name: cloud.hubris.network}
|
|
- {slug: "ingress:paperless.hubris.network", type: ingress-route, name: paperless.hubris.network,
|
|
attributes: {forward_auth: true}}
|
|
- {slug: "ingress:matrix.hubris.network", type: ingress-route, name: matrix.hubris.network}
|
|
- {slug: "ingress:photos.hubris.network", type: ingress-route, name: photos.hubris.network}
|
|
- {slug: "ingress:artifacto.hubris.network", type: ingress-route, name: artifacto.hubris.network}
|
|
- {slug: "ingress:trmnl.hubris.network", type: ingress-route, name: trmnl.hubris.network}
|
|
- {slug: "ingress:zimaos.hubris.network", type: ingress-route, name: zimaos.hubris.network}
|
|
- {slug: "ingress:teddy.hubris.network", type: ingress-route, name: teddy.hubris.network,
|
|
attributes: {forward_auth: false}}
|
|
- {slug: "ingress:mcp.hubris.network", type: ingress-route, name: mcp.hubris.network}
|
|
- {slug: "ingress:secrets.hubris.network", type: ingress-route, name: secrets.hubris.network}
|
|
- {slug: "ingress:house.hubris.network", type: ingress-route, name: house.hubris.network}
|
|
- {slug: "ingress:books.hubris.network", type: ingress-route, name: books.hubris.network}
|
|
- {slug: "ingress:seanime.hubris.network", type: ingress-route, name: seanime.hubris.network}
|
|
- {slug: "ingress:roms.hubris.network", type: ingress-route, name: roms.hubris.network}
|
|
- {slug: "ingress:jellyseerr.hubris.network", type: ingress-route, name: jellyseerr.hubris.network}
|
|
- {slug: "ingress:qbit.hubris.network", type: ingress-route, name: qbit.hubris.network}
|
|
- {slug: "ingress:sab.hubris.network", type: ingress-route, name: sab.hubris.network,
|
|
attributes: {forward_auth: true}}
|
|
|
|
# ─── TLS certificates (Caddy-managed, *.hubris.network) ───────────
|
|
# Each cert's expiry is probed by dialing Caddy's lab IP (`dial`) with SNI
|
|
# set to the hostname — the scheduler container has no mesh/split-horizon
|
|
# DNS, so it can't resolve *.hubris.network, but it CAN reach Caddy on the
|
|
# lab LAN.
|
|
- {slug: "cert:proxmox.hubris.network", type: certificate, name: proxmox.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:git.hubris.network", type: certificate, name: git.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:auth.hubris.network", type: certificate, name: auth.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:media.hubris.network", type: certificate, name: media.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:cloud.hubris.network", type: certificate, name: cloud.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:paperless.hubris.network", type: certificate, name: paperless.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:matrix.hubris.network", type: certificate, name: matrix.hubris.network}
|
|
- {slug: "cert:photos.hubris.network", type: certificate, name: photos.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:artifacto.hubris.network", type: certificate, name: artifacto.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:trmnl.hubris.network", type: certificate, name: trmnl.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:zimaos.hubris.network", type: certificate, name: zimaos.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:teddy.hubris.network", type: certificate, name: teddy.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:mcp.hubris.network", type: certificate, name: mcp.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:house.hubris.network", type: certificate, name: house.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:books.hubris.network", type: certificate, name: books.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:seanime.hubris.network", type: certificate, name: seanime.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:roms.hubris.network", type: certificate, name: roms.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:jellyseerr.hubris.network", type: certificate, name: jellyseerr.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:qbit.hubris.network", type: certificate, name: qbit.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
- {slug: "cert:sab.hubris.network", type: certificate, name: sab.hubris.network, attributes: {dial: "192.168.8.175"}}
|
|
|
|
# ─── Governance ────────────────────────────────────────────────────
|
|
- {slug: "person:dtoro", type: person, name: dtoro,
|
|
attributes: {matrix_id: "@dtoro:avispero"}}
|
|
- {slug: "idp:authentik", type: identity-provider, name: authentik,
|
|
attributes: {issuer: "https://auth.hubris.network", auth_mode: both}}
|
|
- {slug: "agent:nomos", type: agent, name: nomos,
|
|
state: active,
|
|
attributes: {gateway_port: 8092, session_mode: smart_approve, note: "Phase 4 — Docker gateway mode"}}
|
|
- {slug: "agent:oikos", type: agent, name: oikos,
|
|
state: planned,
|
|
attributes: {note: "the OS control loop itself (scheduler/actuator) as an actor"}}
|
|
|
|
# ─── Archaeology (state: destroyed — kept for "what happened to X?") ─
|
|
- {slug: "lxc:claudio-bot", type: lxc, name: claudio-bot, state: destroyed,
|
|
attributes: {pve_id: 123, destroyed: "2026-06-04", reason: "replaced by Nomos Agent on mac-mini"}}
|
|
- {slug: "lxc:plato", type: lxc, name: plato, state: destroyed,
|
|
attributes: {pve_id: 126, destroyed: "2026-06-28", reason: "notes workspace decommissioned; data at /mnt/library/documents/plato"}}
|
|
- {slug: "lxc:mule-photos-new", type: lxc, name: mule-photos-new, state: destroyed,
|
|
attributes: {pve_id: 127, destroyed: "2026-05-22", reason: "PhotoPrism test stack promoted to LXC 120"}}
|
|
- {slug: "lxc:heaper", type: lxc, name: heaper, state: destroyed,
|
|
attributes: {pve_id: 116, destroyed: "2026-05-14", reason: "decommissioned; data at /mnt/library/heaper"}}
|
|
- {slug: "lxc:syncthing", type: lxc, name: syncthing, state: destroyed,
|
|
attributes: {pve_id: 109, destroyed: "2026-05-14", reason: "decommissioned; library subtree was empty"}}
|
|
- {slug: "lxc:seafile", type: lxc, name: seafile, state: destroyed,
|
|
attributes: {pve_id: 125, destroyed: "2026-05-13", reason: "Seafile Pro evaluation rejected"}}
|
|
- {slug: "lxc:arr-yunohost", type: lxc, name: arr-yunohost, state: destroyed,
|
|
attributes: {pve_id: 100, destroyed: "2026-04-28", reason: "migrated to docker stack on arriman (LXC 122)"}}
|
|
- {slug: "lxc:flaresolverr", type: lxc, name: flaresolverr, state: destroyed,
|
|
attributes: {pve_id: 106, destroyed: "2026-04-28", reason: "folded into the arriman docker compose"}}
|
|
- {slug: "lxc:marimo", type: lxc, name: marimo, state: destroyed,
|
|
attributes: {pve_id: 107, destroyed: "2026-04-28", reason: decommissioned}}
|
|
- {slug: "lxc:photoprism", type: lxc, name: photoprism, state: destroyed,
|
|
attributes: {pve_id: 110, destroyed: "2026-04-28", reason: "replaced by mule-images (LXC 120)"}}
|
|
- {slug: "lxc:karakeep", type: lxc, name: karakeep, state: destroyed,
|
|
attributes: {pve_id: 111, destroyed: "2026-04-28", reason: decommissioned}}
|
|
- {slug: "lxc:immich", type: lxc, name: immich, state: destroyed,
|
|
attributes: {pve_id: 112, destroyed: "2026-04-28", reason: "replaced by mule-images (LXC 120)"}}
|
|
- {slug: "lxc:reticulum", type: lxc, name: reticulum, state: destroyed,
|
|
attributes: {pve_id: 115, destroyed: "2026-04-28", reason: decommissioned}}
|
|
|
|
relationships:
|
|
|
|
# ─── Cluster membership ────────────────────────────────────────────
|
|
- {source: "host:hubris", target: "cluster:homelab", type: member-of}
|
|
- {source: "host:strong", target: "cluster:homelab", type: member-of}
|
|
|
|
# ─── Location ──────────────────────────────────────────────────────
|
|
- {source: "host:hubris", target: "site:home", type: located-at}
|
|
- {source: "host:strong", target: "site:home", type: located-at}
|
|
- {source: "ws:mac-mini", target: "site:home", type: located-at}
|
|
- {source: "host:netbird-vps", target: "site:ionos-dc", type: located-at}
|
|
|
|
# ─── Hosting (machine → guest) ─────────────────────────────────────
|
|
- {source: "host:hubris", target: "lxc:nfs-export", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:paperless", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:gitea", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:apps", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:auth-outpost", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:dns", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:nextcloud", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:sophia", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:mule-images", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:caddy", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:trmnl", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:teddycloud", type: hosts}
|
|
- {source: "host:hubris", target: "vm:zimaos", type: hosts}
|
|
- {source: "host:hubris", target: "vm:haos", type: hosts}
|
|
- {source: "host:strong", target: "lxc:jellyfin", type: hosts}
|
|
- {source: "host:strong", target: "lxc:elementsynapse", type: hosts}
|
|
- {source: "host:strong", target: "lxc:arriman", type: hosts}
|
|
- {source: "host:strong", target: "lxc:house", type: hosts}
|
|
- {source: "host:strong", target: "lxc:grimmory", type: hosts}
|
|
- {source: "host:strong", target: "lxc:seanime", type: hosts}
|
|
- {source: "host:strong", target: "lxc:romm", type: hosts}
|
|
- {source: "host:hubris", target: "lxc:rclone", type: hosts}
|
|
|
|
# ─── Service provision (compute → service) ─────────────────────────
|
|
- {source: "host:hubris", target: "service:proxmox-ui", type: provides}
|
|
- {source: "lxc:gitea", target: "service:gitea", type: provides}
|
|
- {source: "lxc:caddy", target: "service:caddy", type: provides}
|
|
- {source: "host:netbird-vps", target: "service:authentik", type: provides}
|
|
- {source: "lxc:dns", target: "service:dns", type: provides}
|
|
- {source: "lxc:jellyfin", target: "service:jellyfin", type: provides}
|
|
- {source: "lxc:nextcloud", target: "service:nextcloud", type: provides}
|
|
- {source: "lxc:paperless", target: "service:paperless", type: provides}
|
|
- {source: "lxc:elementsynapse", target: "service:matrix", type: provides}
|
|
- {source: "lxc:mule-images", target: "service:photos", type: provides}
|
|
- {source: "lxc:arriman", target: "service:arr-stack", type: provides}
|
|
- {source: "lxc:arriman", target: "service:jellyseerr", type: provides}
|
|
- {source: "lxc:arriman", target: "service:qbit", type: provides}
|
|
- {source: "lxc:arriman", target: "service:sab", type: provides}
|
|
- {source: "lxc:apps", target: "service:artifacto", type: provides}
|
|
- {source: "lxc:apps", target: "service:homelab-mcp", type: provides}
|
|
- {source: "lxc:apps", target: "service:secrets-issuance", type: provides}
|
|
- {source: "lxc:trmnl", target: "service:trmnl", type: provides}
|
|
- {source: "vm:zimaos", target: "service:zimaos", type: provides}
|
|
- {source: "vm:haos", target: "service:haos", type: provides}
|
|
- {source: "lxc:teddycloud", target: "service:teddycloud", type: provides}
|
|
- {source: "lxc:house", target: "service:house", type: provides}
|
|
- {source: "lxc:grimmory", target: "service:grimmory", type: provides}
|
|
- {source: "lxc:seanime", target: "service:seanime", type: provides}
|
|
- {source: "lxc:romm", target: "service:romm", type: provides}
|
|
|
|
# ─── Ingress → service ─────────────────────────────────────────────
|
|
- {source: "ingress:proxmox.hubris.network", target: "service:proxmox-ui", type: routes-to}
|
|
- {source: "ingress:git.hubris.network", target: "service:gitea", type: routes-to}
|
|
- {source: "ingress:auth.hubris.network", target: "service:authentik", type: routes-to}
|
|
- {source: "ingress:media.hubris.network", target: "service:jellyfin", type: routes-to}
|
|
- {source: "ingress:cloud.hubris.network", target: "service:nextcloud", type: routes-to}
|
|
- {source: "ingress:paperless.hubris.network", target: "service:paperless", type: routes-to}
|
|
- {source: "ingress:matrix.hubris.network", target: "service:matrix", type: routes-to}
|
|
- {source: "ingress:photos.hubris.network", target: "service:photos", type: routes-to}
|
|
- {source: "ingress:artifacto.hubris.network", target: "service:artifacto", type: routes-to}
|
|
- {source: "ingress:trmnl.hubris.network", target: "service:trmnl", type: routes-to}
|
|
- {source: "ingress:zimaos.hubris.network", target: "service:zimaos", type: routes-to}
|
|
- {source: "ingress:teddy.hubris.network", target: "service:teddycloud", type: routes-to}
|
|
# Re-pointed from service:homelab-mcp, which is deprecated — the Python MCP
|
|
# server on apps/105 was stopped at the Go cutover and mcp.hubris.network now
|
|
# fronts the Go api. Nomos recorded this correctly on 2026-07-12; the seed
|
|
# was the stale one, and re-asserting the old edge alongside it is what made
|
|
# ingress:mcp a cardinality violation.
|
|
- {source: "ws:mac-mini", target: "service:oikos", type: provides}
|
|
- {source: "ingress:mcp.hubris.network", target: "service:oikos", type: routes-to}
|
|
# Every public hostname is terminated by caddy. Without these the
|
|
# reverse proxy — the single widest point of failure in the lab —
|
|
# had a blast radius of one.
|
|
- {source: "ingress:proxmox.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:git.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:auth.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:media.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:cloud.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:paperless.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:matrix.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:photos.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:artifacto.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:trmnl.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:zimaos.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:teddy.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:mcp.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:secrets.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:house.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:books.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:seanime.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:roms.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:jellyseerr.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:qbit.hubris.network", target: "service:caddy", type: served-by}
|
|
- {source: "ingress:sab.hubris.network", target: "service:caddy", type: served-by}
|
|
# Each public route is served with its TLS certificate.
|
|
- {source: "ingress:proxmox.hubris.network", target: "cert:proxmox.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:git.hubris.network", target: "cert:git.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:auth.hubris.network", target: "cert:auth.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:media.hubris.network", target: "cert:media.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:cloud.hubris.network", target: "cert:cloud.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:paperless.hubris.network", target: "cert:paperless.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:matrix.hubris.network", target: "cert:matrix.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:photos.hubris.network", target: "cert:photos.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:artifacto.hubris.network", target: "cert:artifacto.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:trmnl.hubris.network", target: "cert:trmnl.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:zimaos.hubris.network", target: "cert:zimaos.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:teddy.hubris.network", target: "cert:teddy.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:mcp.hubris.network", target: "cert:mcp.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:house.hubris.network", target: "cert:house.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:books.hubris.network", target: "cert:books.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:seanime.hubris.network", target: "cert:seanime.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:roms.hubris.network", target: "cert:roms.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:jellyseerr.hubris.network", target: "cert:jellyseerr.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:qbit.hubris.network", target: "cert:qbit.hubris.network", type: uses-certificate}
|
|
- {source: "ingress:sab.hubris.network", target: "cert:sab.hubris.network", type: uses-certificate}
|
|
|
|
- {source: "ingress:secrets.hubris.network", target: "service:secrets-issuance", type: routes-to}
|
|
- {source: "ingress:house.hubris.network", target: "service:house", type: routes-to}
|
|
- {source: "ingress:books.hubris.network", target: "service:grimmory", type: routes-to}
|
|
- {source: "ingress:seanime.hubris.network", target: "service:seanime", type: routes-to}
|
|
- {source: "ingress:roms.hubris.network", target: "service:romm", type: routes-to}
|
|
- {source: "ingress:jellyseerr.hubris.network", target: "service:jellyseerr", type: routes-to}
|
|
- {source: "ingress:qbit.hubris.network", target: "service:qbit", type: routes-to}
|
|
- {source: "ingress:sab.hubris.network", target: "service:sab", type: routes-to}
|
|
|
|
# ─── Auth edges ────────────────────────────────────────────────────
|
|
- {source: "ingress:paperless.hubris.network", target: "idp:authentik", type: secured-by}
|
|
- {source: "ingress:sab.hubris.network", target: "idp:authentik", type: secured-by}
|
|
- {source: "service:jellyfin", target: "idp:authentik", type: authenticates-via}
|
|
- {source: "idp:authentik", target: "person:dtoro", type: authenticates}
|
|
|
|
# ─── Config repos ──────────────────────────────────────────────────
|
|
- {source: "service:caddy", target: "repo:caddy-conf", type: configured-by}
|
|
- {source: "service:gitea", target: "repo:gitea-customizations", type: configured-by}
|
|
- {source: "service:photos", target: "repo:mule-image", type: configured-by}
|
|
- {source: "service:artifacto", target: "repo:artifacto", type: configured-by}
|
|
- {source: "service:trmnl", target: "repo:terminalito", type: configured-by}
|
|
- {source: "service:homelab-mcp", target: "repo:homelab-docs", type: configured-by}
|
|
- {source: "service:secrets-issuance", target: "repo:homelab-docs", type: configured-by}
|
|
|
|
# ─── Service dependencies (blast-radius edges; grow over time) ─────
|
|
- {source: "service:paperless", target: "service:authentik", type: depends-on}
|
|
- {source: "service:homelab-mcp", target: "service:gitea", type: depends-on}
|
|
- {source: "service:jellyseerr", target: "service:jellyfin", type: depends-on}
|
|
- {source: "service:seanime", target: "service:qbit", type: depends-on}
|
|
- {source: "service:house", target: "service:paperless", type: depends-on}
|
|
- {source: "service:sab", target: "service:authentik", type: depends-on}
|
|
|
|
# ─── Network membership ────────────────────────────────────────────
|
|
- {source: "host:hubris", target: "lan:lab", type: connects-via}
|
|
- {source: "host:hubris", target: "mesh:netbird", type: connects-via}
|
|
- {source: "host:strong", target: "lan:household", type: connects-via}
|
|
- {source: "ws:mac-mini", target: "lan:household", type: connects-via}
|
|
- {source: "ws:mac-mini", target: "mesh:netbird", type: connects-via}
|
|
- {source: "ws:republic-laptop", target: "mesh:netbird", type: connects-via}
|
|
- {source: "host:netbird-vps", target: "mesh:netbird", type: connects-via}
|
|
- {source: "lxc:rclone", target: "mesh:netbird", type: connects-via}
|
|
- {source: "lxc:jellyfin", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:nfs-export", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:paperless", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:gitea", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:apps", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:apps", target: "mesh:tailscale", type: connects-via}
|
|
- {source: "lxc:auth-outpost", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:dns", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:nextcloud", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:elementsynapse", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:sophia", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:mule-images", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:caddy", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:arriman", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:trmnl", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:house", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:grimmory", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:teddycloud", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:seanime", target: "lan:lab", type: connects-via}
|
|
- {source: "lxc:romm", target: "lan:lab", type: connects-via}
|
|
- {source: "vm:zimaos", target: "lan:lab", type: connects-via}
|
|
- {source: "vm:haos", target: "lan:lab", type: connects-via}
|
|
|
|
# ─── Storage ───────────────────────────────────────────────────────
|
|
- {source: "pool:ludo-lvm", target: "volume:media-local", type: contains}
|
|
- {source: "pool:library-hubris", target: "volume:library", type: contains}
|
|
- {source: "host:hubris", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:jellyfin", target: "volume:media-local", type: mounts,
|
|
attributes: {mount_point: /mnt/media_local}}
|
|
- {source: "lxc:paperless", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:gitea", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:apps", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:nextcloud", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:sophia", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:mule-images", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:arriman", target: "volume:media-local", type: mounts,
|
|
attributes: {mount_point: /mnt/media_local}}
|
|
- {source: "lxc:grimmory", target: "volume:media-local", type: mounts,
|
|
attributes: {mount_point: /mnt/media_local}}
|
|
- {source: "lxc:teddycloud", target: "volume:library", type: mounts,
|
|
attributes: {mount_point: /mnt/library}}
|
|
- {source: "lxc:seanime", target: "volume:media-local", type: mounts,
|
|
attributes: {mount_point: /mnt/media_local/anime}}
|
|
- {source: "lxc:romm", target: "volume:media-local", type: mounts,
|
|
attributes: {mount_point: /mnt/media_local}}
|
|
- {source: "lxc:jellyfin", target: "pool:ludo-lvm", type: stores-on}
|
|
- {source: "lxc:arriman", target: "pool:ludo-lvm", type: stores-on}
|
|
- {source: "lxc:grimmory", target: "pool:ludo-lvm", type: stores-on}
|
|
- {source: "lxc:romm", target: "pool:ludo-lvm", type: stores-on}
|
|
- {source: "lxc:teddycloud", target: "pool:local-lvm-hubris", type: stores-on}
|
|
- {source: "lxc:rclone", target: "backup:proton-drive", type: backs-up-to}
|
|
# The mac-mini writes the pre-deploy dumps, so it is also where the freshness
|
|
# check runs — checkdefaults resolves a backup-target's host by walking this
|
|
# edge backwards.
|
|
- {source: "ws:mac-mini", target: "backup:oikos-predeploy", type: backs-up-to}
|
|
|
|
# ─── Governance ────────────────────────────────────────────────────
|
|
- {source: "person:dtoro", target: "agent:nomos", type: owns}
|
|
- {source: "person:dtoro", target: "agent:oikos", type: owns}
|