10 KiB
Family Home Lab Console — Plan
Adapted from Obsidian notes: FAMILY Enterprise Homelab AI Multimedia Suite, FAMILY S3 Storage Integration & Blueprint, FAMILY DeepSeek Harness (dsh) Home Lab Setup, Home Network Map Overview, Backup System — Borg, Kopia & Restic.
Status: FINAL v3 — approved. Build phase: repo-local code complete (2026-08-24), deployment pending.
1. Goal
A single family console ("landing page") at a local URL where each of the four users (Sam, Jo, Harry, Finn) logs in and gets:
- A personalised dashboard of available AI + media tools
- One-click launch of each tool (inline iframe where possible, else window/new tab)
- Per-user session handling and tool permissions
The console is also the parent interface that the DeepSeek Harness instances hang off (dsh itself is built by another agent — we only define the integration contract here).
2. Where it runs (adapted to my network)
| Concern | Generic blueprint said | Adapted decision |
|---|---|---|
| Host machine | unspecified | .13 nixos-desktop — always-on server, existing Docker host (15.5 GB RAM), already runs Open WebUI/OmniRoute/Langfuse |
| Reverse proxy | dedicated Caddy container in compose stack | Reuse existing Caddy on .35 — it already proxies *.home.lab; no duplicate proxy/ports 80/443 conflict |
| Local DNS | *.lab.audasmedia.com.au (real TLD, always resolves; *.home.lab failed as it's not a registered TLD) |
|
| LLM routing | deploy omniroute container in stack | Reuse existing OmniRoute .13:20128/20129 |
| Object storage | deploy Garage in stack | Fresh Garage deployment in our own stack, data on /mnt/data/family-home-lab/garage/ (new subdir; Takeout landing zone untouched). Old garage-garage-1 test instance retired after data check |
Directory layout (on .13)
/home/sam/Docker/Containers/family-home-lab/ # compose project (matches existing convention)
├── docker-compose.yml
├── .env # secrets (git-ignored)
├── garage/garage.toml
├── portal/ # custom FastAPI app
│ ├── main.py # async web controller
│ ├── auth.py # user login/session handling
│ ├── database.py # PostgreSQL + pgvector
│ ├── tasks.py # background workers (Celery)
│ ├── templates/ # HTMX/Jinja2 frontend
│ └── static/
/mnt/data/family-home-lab/ # heavy data (NOT backed by root drive)
├── garage/garage-data # S3 object data
├── garage-meta/
└── shared-media/
Repo lives here (family_home_lab working dir) with subfolders per tool category:
video/ image/ audio/ docs/ ai/ chat/ — no dsh folder (owned by other agent).
Queue: RabbitMQ container deployed fresh inside this stack (verified none exists on network).
3. Core stack
| Component | Technology | Rationale |
|---|---|---|
| Console portal | FastAPI + Jinja2 + HTMX | lightweight, employable skillset, no SPA build chain needed |
| Auth | per-user accounts (bcrypt password hash), signed HTTP-only session cookies; admin panel for Sam to manage users | simple, self-contained; no external IdP overhead for 4 users |
| Database | pgvector/pgvector:pg16 |
user profiles + preferences now; semantic memory vectors later |
| Task queue | Celery + Redis (downgrade from blueprint's RabbitMQ unless queue UI is wanted) | lighter on 15.5 GB RAM shared with existing services; swap-in RabbitMQ is trivial if wanted for resume value |
| Object storage | Garage v1.x S3-compatible | pure OSS Rust S3; buckets per user + shared-media; boto3 from portal |
| Proxy/DNS | existing Caddy (.35) + Pi-hole records | consistent with rest of network |
URLs (final — public domain, no local DNS needed)
All domains resolve via public DNS lab.audasmedia.com.au → 144.6.86.11 → router → .35 Caddy → internal hosts.
| Domain | Target | Tool |
|---|---|---|
console.lab.audasmedia.com.au |
.35 → .13:8500 |
The family console (this project) |
photo.lab.audasmedia.com.au |
.13 photopea container | Image editing |
video.lab.audasmedia.com.au |
.13 video editor container | Video editing |
audio.lab.audasmedia.com.au |
.13 audio container | Audio editing |
s3.lab.audasmedia.com.au |
.13 Garage API | S3 endpoint (internal/API use) |
| dsh instances | dsh-<user>.lab.audasmedia.com.au |
Built by other agent — see §6 |
4. Tool catalogue (phase 1)
Each tool = its own subfolder here, own URL, dockerised with WebUI, mounted against Garage buckets or bind-mounted media dirs.
- Image: Photopea (self-hosted)
- Video: KdenLive via LinuxServer webtop/KasmVNC image ⚠️ verify current image name — LSIO deprecated some standalone rdesktop apps
- Audio: Audacity via LinuxServer webtop image (Zrythm optional phase 2)
- AI chat: OmniRoute dashboard (
.13:20128,omniroute.home.lab) linked/inlined.Open WebUI— dropped; dsh instances will replace it. - Docs / Chat: future phases (dsh per-user instances are the chat layer)
5. S3 storage integration (final)
- Fresh Garage v1.x container in our stack.
data_dir = /mnt/data/family-home-lab/garage-data,metadata_dir = /mnt/data/family-home-lab/garage-meta. Ports 3900 (S3 API) / 3902 (web) — old test instance stopped first to free them. - Buckets:
sam,jo,harry,finn,shared-media. - Portal uploads/downloads via boto3 (S3v4 signatures); tools either bind-mount or use rclone/s3fs mounts where they can't talk S3 natively.
- Backups: add
/mnt/data/family-home-lab/to .13's existing Borg job source list → covered by rsync→.35→.23 chain. /mnt/data's existing Takeout dirs (01_keep/02_review/03_delete/takeout/.thumbs) are never touched.
6. DeepSeek Harness integration contract (NOT building dsh)
Update the dsh Obsidian note to require:
- Each dsh instance reachable at
dsh-<user>.home.labvia .35 Caddy (subdomains, not subpaths — avoids WebSocket/path issues). - Console links to the correct instance after login; optionally auto-auth via one-time token passed in query param (to be designed with the dsh agent).
- dsh containers must be iframe-friendly (correct CSP/X-Frame-Options headers set by Caddy) if embedded inline in the console.
- Session handling stays inside dsh; the console only handles entry-point routing.
7. Deployment
- Stop/retire old
garage-garage-1test instance (afterdusanity check of its volume) ✅ done - Apply Caddyfile entries on .35 from
deploy/caddy/Caddyfile.snippet(tracked via filechanges extension) docker compose up -dfrom/home/sam/Docker/Containers/family-home-lab/on .13- Create Garage buckets + access keys; first-run admin setup creates Sam's admin account, then Jo/Harry/Finn
- Add
/mnt/data/family-home-lab/to Borg backup source list on .13
DNS note: public domain
*.lab.audasmedia.com.auis used — no Pi-hole local records required.*.home.labdomains are deprecated (not a registered TLD; resolution unreliable).
8. Resolved decisions
- Queue: RabbitMQ (own container in our stack; verified no conflict — Mosquitto :1883 was the false memory)
- Video/audio editors: browser-streamed desktop containers ✓
- Portal port: 8500 on .13 ✓
- Auth: username + password (bcrypt), signed session cookies, all four users ✓
- Phase-1 tools: Photopea, video editor, audio editor, OmniRoute link ✓ (Open WebUI dropped — dsh replaces)
- Storage: fresh Garage on
/mnt/data/family-home-lab/; old test instance retired afterducheck ✓ - Compose location:
/home/sam/Docker/Containers/family-home-lab/✓ - Frontend: FastAPI + Jinja2 + HTMX, server-rendered, no SPA build chain ✓
9. Verified facts (live checks)
- .13 containers include: omniroute (:20128/29), garage (:3900/3902), n8n, airflow, langfuse, litellm (:4000), mosquitto (:1883), pihole (:53/:8080), pocketbase (:8090), prefect (:4200), minio (:9010/:9090), postgres (:5432/:5433/:5434). No RabbitMQ. Port 8500 free ✓.
10. Build status (repo-local, 2026-08-24)
| Item | State |
|---|---|
portal/ FastAPI app (main/auth/db/tasks/tools/config) |
✅ written & compiles |
Templates + tokens.css/app.css (9 pages, HTMX polling) |
✅ written, all render |
docker-compose.yml (portal/db/redis/rabbitmq/garage/worker) |
✅ written, config -q valid |
| Tool containers (photo/video/audio) | ✅ media tools LIVE: photo/video/audio.lab.audasmedia.com.au (Photopea/KdenLive/Audacity) |
garage/garage.toml + .env.example |
✅ written + applied live |
| First-run admin bootstrap (env) | ✅ implemented + verified |
| Local smoke test (login→dashboard→admin→add-user) | ✅ passed — caught+fixed 2 bugs (session_scope, non-fatal broker call) |
| Deploy to .13 + Garage buckets/keys | ✅ core stack live on console.lab.audasmedia.com.au |
| Caddy rules on .35 | ✅ console + photo/video/audio + dsh-sam/jo/harry/finn applied & reloaded |
| DeepSeek Harness | ✅ built here (dsh/) + 4 instances live: dsh-{user}.lab.audasmedia.com.au → .13:3081-3084 (auto/best-chat via OmniRoute) |
| Tool page workspace files | ✅ /tool/{id} lists user's S3 bucket + shared-media |
| Borg backup path on .13 | ⏳ needs sudo edit to backup.nix (snippet provided) |
Deployed 2026-08-24: console live + media tools live. Buckets sam, jo-media, harry, finn, shared-media (S3 needs ≥3-char names → jo→jo-media). Media host ports reassigned: video 8083 (8081=taken by airflow), audio 8084 (3000=taken by a NixOS service); photopea 8487. Images: shtse8/photopea:1.0, lscr.io/linuxserver/kdenlive, lscr.io/linuxserver/audacity. OmniRoute console link uses proper URL omniroute.lab.audasmedia.com.au.
Audio / GPU follow-ups (2026-08-25)
- Zrythm DAW: install NATIVELY on NixOS via
pkgs.zrythm(no docker/webtop — no apt/AppImage). Access via RustDesk (RustDesk server already runs on .35: hbbs/hbbr). DAW audio latency over remote is ok for composing, not live multitrack recording. - AMD RX 6600 being added to .13: configure
amdgpudriver in NixOS so containers/ML can use it (MuScriptor/Basic Pitch/vision speedup). Currently .13 has no working NVIDIA/AMD driver or container runtime (nvidia-smi fails; docker only has runc).