# RUNBOOK — provisioning the OS / Docker-data / user-data storage split How the controller guest's **OS rootfs**, **Docker data**, and **SSD user-data** are carved onto three separate `local-lvm` volumes, and how to size them per node/customer. Grounded by the storage-split spike (`REPORT-storage-split-spike.md`). Defaults target a ~512 GB SSD: **32 GB OS rootfs + 200 GB Docker-data + 50 GB user-data**, rest of the thin pool free for other guests. ## The design (locked) Three thin volumes are baked into the golden and grown at provision: | mp slot | Mount | Holds | Golden default | Provision grow knob | |---------|-------|-------|----------------|---------------------| | rootfs | `/` | OS only | `OS_SIZE_GB=32` | `-rootfs-grow` | | `mp0` | `/var/lib/docker` | ALL Docker images + overlay + named volumes | `GOLDEN_DOCKER_GB=16` | `-datavol-grow` | | `mp1` | `/mnt/sys_drive` | SSD user-data (the controller's `system_data_path`; `/felhom-data` = SSD-only app data + DBs) | `GOLDEN_SYSDATA_GB=8` | `-sysdata-grow` | - **Split for resilience, not backup size.** An isolated OS rootfs stays bootable + agent-recoverable if the Docker volume fills. All three volumes ride into PBS regardless (so the backup size is unchanged) — the win is independent sizing/growth and a smaller, faster-to-restore OS rootfs. - **One Docker daemon, one data-root, one volume** at `/var/lib/docker` for ALL images + overlay (controller, traefik, cloudflared, filebrowser, and customer apps). Infra is NOT relocated to the OS partition — infra/user separation under one daemon isn't cleanly possible and isn't needed. Infra is protected by the controller's **prevention layer** (reserved buffer + deploy gate + disk alerts + baked log rotation), not by placement. - **`/mnt/sys_drive` is a static CT volume, NOT an enrolled drive.** It never enrolls, ejects, or decommissions — it is part of the golden's baked layout. The controller auto-discovers `/felhom-data` and, via `system.IsMountPoint`, **warns when `/mnt/sys_drive` is not its own mount** (`selftest.go`). Making `mp1` a real mount clears that warning with **zero controller change**; the controller is untouched by this slice. The `mp` mounted under the guest's `/mnt` propagates into the controller container through the existing `-v /mnt:/mnt:rslave` bind (the same path enrolled drives use). - **`backup=1` on the Docker-data AND user-data volumes is non-negotiable.** Extra LXC mountpoints default to `backup=0` = EXCLUDED from vzdump/PBS (spike B3). Without it, named-volume DBs / SSD app data fall out of the snapshot AND (for mp0) the baked images are excluded from the golden archive. ## Golden build (per controller-image baseline) `configs/build-golden.sh` builds the template guest with the split baked in: ``` # defaults shown; override via env OS_SIZE_GB=32 GOLDEN_DOCKER_GB=16 GOLDEN_SYSDATA_GB=8 \ ./build-golden.sh