Publish sanitized current homelab architecture
Some checks failed
public-safety / privacy-and-secret-scan (push) Has been cancelled

This commit is contained in:
fizzlepoof
2026-09-08 21:47:41 +00:00
commit cc35523888
13 changed files with 901 additions and 0 deletions

141
docs/architecture.md Normal file
View File

@@ -0,0 +1,141 @@
# Architecture
## Topology
```mermaid
flowchart TB
Internet((Internet))
Edge[Authenticated tunnel gateway]
SSO[Identity and SSO]
Proxy[Internal reverse proxy]
subgraph Home[Segmented home network]
subgraph Primary[Primary application host]
Apps[Household and productivity apps]
Data[Shared databases and caches]
Media[Media, photos, and documents]
Observe[Monitoring and dashboards]
AI[Always-on AI and search]
end
subgraph Storage[Storage and ingestion host]
Pool[Bulk ZFS storage]
Arr[Media automation and download pipeline]
Sync[File synchronization and backups]
Remote[Remote-support relay]
end
subgraph Resilience[Offline and resilience host]
Offline[Offline knowledge and education]
HomeAuto[Home automation VM]
Games[Game-server control plane]
Secondary[Backup DNS and local AI]
Agents[Automation and agent services]
end
Workstation[GPU operator workstation]
EdgeNode[Low-power weather and radio node]
end
Internet --> Edge --> Proxy
Proxy --> SSO
SSO --> Apps
Apps --> Data
Apps --> Pool
Media --> Pool
Arr --> Pool
Observe --> Apps
AI -. optional heavy jobs .-> Workstation
Secondary -. resilient local path .-> AI
Agents --> Apps
Sync --> Workstation
EdgeNode --> Agents
Remote -. private overlay .-> Workstation
```
## Host responsibilities
### Primary application host
The primary host carries the application plane:
- shared PostgreSQL, MariaDB, and Redis
- identity, SSO, ingress routing, and tunnel clients
- media front ends, photo management, and document management
- dashboards, monitoring, metrics, logs, and notifications
- household applications and workflow automation
- light-tier model serving, search, RAG, and vector storage
- self-hosted development and administration tools
The host is intentionally not the only copy of storage, DNS, or offline knowledge.
### Storage and ingestion host
The storage host owns the large-capacity data plane and workloads that benefit from data locality:
- ZFS-backed bulk datasets
- media acquisition, organization, and post-processing
- synchronized document storage with versioning
- backup targets and retained application data
- private remote-support rendezvous and relay
- selected CPU-only inference utilities
- a secondary DNS replica
### Offline and resilience host
The resilience host is designed to remain useful when public services are unavailable:
- offline reference libraries and educational content
- local notes and browser utilities
- local model and vector services
- agent memory and household helper applications
- Home Assistant running in a dedicated virtual machine
- game-server management
- mesh-radio observation
- a secondary DNS replica
### GPU workstation
The workstation provides high-performance GPU capacity for interactive or heavy jobs. Routine background tasks must continue when it is asleep or offline.
### Low-power edge node
The edge node handles always-on weather and mesh-radio functions close to the attached hardware. It reports upstream but is not part of the main application failure domain.
## Request flows
### External application request
```text
client → tunnel gateway → internal reverse proxy → SSO policy → application
```
The tunnel endpoint is the only public routing layer. Application containers do not require direct inbound router exposure.
### Internal application request
```text
trusted client → internal DNS → application or reverse proxy → service
```
### AI request
```text
application → model gateway → always-on local model
↘ optional GPU workstation
```
### Storage request
```text
application host → authenticated network storage mount → storage dataset
```
## Failure-domain rules
1. Losing the GPU workstation must not stop routine automation.
2. Losing public DNS must not be confused with losing the private DNS zone.
3. Losing the primary application host must not destroy bulk datasets or backups.
4. A tunnel or SSO failure must not expose an application directly.
5. The offline host must retain useful local content without WAN access.
6. Changes to storage, networking, identity, and databases require explicit rollback points.

69
docs/networking.md Normal file
View File

@@ -0,0 +1,69 @@
# Networking
## Segmentation model
The network uses purpose-specific policy lanes rather than one trusted broadcast domain.
| Lane | Intended occupants | Default posture |
|---|---|---|
| **Management** | Gateway, switches, access points, controllers | Administrative access only |
| **Trusted** | Human-operated laptops, phones, and workstations | May initiate approved internal connections |
| **Servers** | Application, storage, DNS, and automation hosts | Explicit service exposure |
| **IoT** | Appliances and embedded clients | Restricted from internal networks by default |
| **Cameras** | Video and security devices | More restrictive than general IoT |
| **Guest** | Visitors and temporary clients | Internet only |
| **Quarantine** | Legacy or unidentified devices | Minimal DNS, time, and internet access |
| **Lab** | Disposable security and development systems | Default deny toward production |
Exact VLAN identifiers, addressing, SSIDs, and device assignments are intentionally absent from this public repository.
## Policy principles
- Inter-lane access is denied unless a specific workflow requires it.
- Management interfaces are never reachable from guest, IoT, camera, or lab lanes.
- IoT exceptions are limited to named services and destinations.
- Discovery protocols are bridged only when a real use case requires them.
- DNS, DHCP, and time synchronization are treated as explicit dependencies.
- A trusted operator path stays available during every network change.
- Client migrations happen in small batches with rollback after each batch.
## DNS resilience
The lab uses three synchronized internal resolvers:
1. a primary configuration source on the application host
2. one replica on the offline/resilience host
3. one replica on the storage host
The replicas receive configuration on a schedule and are verified from another host. External recursive resolvers may provide public-name fallback, but they cannot replace authoritative answers for the private zone.
## Remote access
Two complementary mechanisms are used:
- **Authenticated application ingress:** tunnel gateway → reverse proxy → SSO → selected service
- **Private administrative overlay:** device-to-device access for operators and private support workflows
Most applications do not expose router-forwarded ports. Protocols that cannot use the HTTP tunnel are handled as narrow, documented exceptions.
## Container networking
Compose projects use named external networks for shared dependencies:
- a data network for databases and caches
- an ingress network for explicitly published applications
- optional service-family networks for AI and observability
Applications join only the networks they need. The reverse proxy does not receive unrestricted control of the container runtime.
## Validation gates
After a network change, verify:
1. gateway and controller access from a trusted client
2. DHCP lease and intended lane placement
3. private and public DNS answers
4. the exact application protocol, not only ping
5. cross-lane allow and deny behavior
6. recovery after client reassociation or host reboot
7. absence of broad temporary allow rules

78
docs/operations.md Normal file
View File

@@ -0,0 +1,78 @@
# Operations
## Deployment order
A predictable dependency order reduces partial deployments:
1. storage mounts and host prerequisites
2. shared databases and caches
3. ingress, identity, DNS, and management services
4. observability and notifications
5. application stacks
6. optional AI, media, and edge integrations
## Change workflow
1. **Read first.** Capture current host, service, network, and storage state.
2. **Define scope.** Name the exact stack, files, and expected result.
3. **Create rollback.** Back up configuration and state before mutation.
4. **Validate configuration.** Render Compose, parse structured files, and run syntax checks.
5. **Apply narrowly.** Restart or recreate only the service that consumes the change.
6. **Verify from the consumer side.** A process being `running` is not proof that the workflow works.
7. **Read back external state.** Confirm the controller, API, repository, or database actually retained the change.
8. **Document the result.** Record current truth, rollback location, and deferred work.
## Compose validation
A sanitized example stack is provided under `examples/compose/`.
```bash
cp examples/compose/.env.example examples/compose/.env
# Replace placeholders only in the untracked .env file.
docker compose --env-file examples/compose/.env \
-f examples/compose/docker-compose.yml config
```
Never commit the generated `.env` file.
## Service verification
Use multiple layers of evidence:
- container or service state
- health endpoint
- recent logs
- dependency connectivity
- application-level request
- persistence after restart
- monitoring visibility
For stateful applications, also check a representative database object or file after restart.
## Backup model
- filesystem snapshots protect bulk datasets
- application-aware exports protect databases and stateful services
- encrypted Git stores recoverable configuration secrets
- normal Git stores source, sanitized templates, and operator documentation
- synchronized user files use versioning in addition to storage snapshots
- restore tests are scheduled; backup creation alone is not treated as recovery proof
## Storage and data locality
Large data stays on the storage host. Applications consume it over authenticated mounts where practical. Ingestion workloads remain close to the data when moving them would create avoidable network traffic or fragile cross-host dependencies.
## Monitoring and notifications
Metrics, logs, uptime checks, and push notifications are separate components so one dashboard failure does not erase the underlying evidence. Alerts should be low-volume, actionable, and routed to an operator channel with enough context to diagnose.
## Updating documentation
Documentation is divided into:
- **current state:** what is running and where
- **operating procedure:** how to change and verify it
- **historical evidence:** dated incident or migration records
- **future plan:** proposed work that is not yet live
Dated historical notes should never read like the active backlog. Public documentation describes roles and patterns; exact operational coordinates remain private.

67
docs/security.md Normal file
View File

@@ -0,0 +1,67 @@
# Security
## Public/private boundary
This public repository contains architectural patterns, sanitized examples, and high-level service placement. It is not used for production deployment.
The private operational repository contains exact topology, runtime paths, deployment notes, and rollback artifacts. A separate encrypted repository stores environment files and other secrets.
## Never publish
- credentials, tokens, cookies, private keys, recovery codes, or session material
- real `.env` files
- internal or management addresses
- MAC addresses, serial numbers, client IDs, or tunnel IDs
- real domains, SSIDs, account names, or personal filesystem paths
- physical locations or household records
- raw controller exports, logs, database dumps, or backups
- screenshots containing dashboards, account menus, or browser sessions
## Secret workflow
1. Generate or receive the secret outside chat and version control.
2. Place it only in the runtime environment or secret manager.
3. Sync recoverable copies into an encrypted secrets repository.
4. Confirm Git stores ciphertext rather than plaintext.
5. Scan staged files and outgoing history before push.
6. If exposure occurs, rotate first, then clean current files and rewrite history.
7. Re-clone and scan the rewritten remote before considering remediation complete.
Removing a value from the latest commit does not remove it from Git history.
## Repository controls
The public repository uses two checks:
- `scripts/check-public-safety.py` rejects infrastructure identifiers, private paths, key-like files, and common secret patterns.
- Gitleaks scans complete Git history in CI.
The scanner is deliberately conservative. Placeholder examples should use unmistakable values such as:
```text
CHANGE_ME_DATABASE_PASSWORD
CHANGE_ME_API_TOKEN
https://service.example.net
/home/operator/application
/mnt/storage/application-data
```
## Identity and ingress
- Public application access passes through authenticated ingress.
- SSO policy is applied before protected applications.
- Administrative interfaces stay on private paths.
- Tunnel credentials are isolated from application configuration.
- Direct exposure is reserved for protocols that cannot traverse the authenticated HTTP path and is documented separately.
## Workload isolation
- Untrusted clients and lab systems cannot initiate general access to production lanes.
- Databases are not published to the internet.
- Containers receive only required networks and mounts.
- Runtime control sockets are avoided or proxied with restricted permissions.
- High-risk workloads use separate trust domains rather than relying on process isolation alone.
## Reporting
Do not open a public issue containing a suspected secret. Revoke it first and use a private contact channel for disclosure.

168
docs/services.md Normal file
View File

@@ -0,0 +1,168 @@
# Current Service Placement
This is a public-safe service inventory verified against the live hosts during the September 2026 refresh. Versions, ports, addresses, domains, device IDs, and internal paths are intentionally omitted.
## Primary application host
### Core platform
- TrueNAS SCALE
- Docker application runtime
- shared PostgreSQL, MariaDB, and Redis
- Traefik internal reverse proxy
- Newt tunnel connector
- Tailscale private-overlay connector
- Authentik identity and SSO
- Authelia retained for limited legacy migration paths
- Headscale and Headplane pilot control plane
- Gitea source hosting
- Dockhand and Homepage administration interfaces
### AI and search
- Ollama always-on model serving
- LiteLLM model gateway
- Open WebUI
- Qdrant vector database
- SearXNG metasearch
- Firecrawl API, browser worker, queue, and supporting data services
- a VPN-isolated search egress path
### Media and libraries
- Plex
- Tautulli
- Audiobookshelf
- Calibre Web Automated
- Seerr
- Immich application and machine-learning services
- RomM
- GameVault
- Dispatcharr
Large libraries remain on the storage host and are mounted by the application host.
### Productivity and household applications
- Paperless-ngx with document conversion and extraction sidecars
- Karakeep with browser and search sidecars
- n8n
- KitchenOwl
- Donetick and a dashboard bridge
- Shlink and its web client
- Qui
- Scholarsome
- Doris Barbell
- Kima Hub
### Monitoring and notification
- Grafana
- Prometheus
- Loki
- Promtail
- cAdvisor
- node exporter
- Netdata
- Uptime Kuma
- Gotify
### Radio visibility
- MeshMonitor
- local map-tile service
## Storage and ingestion host
### Data plane
- ZFS-backed bulk storage
- application-data and media datasets
- snapshot and backup targets
- synchronized school/document storage
### Media ingestion
- Sonarr, including a separate anime workflow
- Radarr
- Lidarr
- Readarr variants
- Prowlarr
- Bazarr
- qBittorrent through a VPN gateway
- qbit_manage
- Unpackerr
- Autobrr
- Notifiarr
- Shelfmark
### Supporting services
- Syncthing hub
- RustDesk rendezvous and relay
- CPU text reranker
- secondary Technitium DNS replica
- Netdata
- Hawser
- Newt connector
## Offline and resilience host
### Offline knowledge platform
- Project N.O.M.A.D. administration layer
- Kiwix
- two Kolibri generations for retained content compatibility
- CyberChef
- Flatnotes
- MeshCore Web
- local Ollama and Qdrant
Project N.O.M.A.D.-managed containers are treated as an appliance layer and are not manually rebuilt by general maintenance automation.
### Local agents and household tools
- Honcho API, deriver, PostgreSQL/Vector database, and Redis
- Doris Schoolhouse
- Doris Kitchen
- CPU Whisper service
- LocalSend trusted intake
- Hawser
- node exporter
### Resilience and hardware-adjacent services
- Home Assistant OS in a KVM virtual machine with a dedicated Zigbee radio
- secondary Technitium DNS replica
- MeshCore companion observer as a system service
- Pelican/Wings game-server management
- Newt tunnel connector
## GPU operator workstation
- CachyOS desktop
- high-performance NVIDIA GPU compute
- optional heavy Ollama and speech workloads
- Docker runtime
- printing service
- private-overlay access
- file-synchronization client
- 3D-printing and slicing applications
The workstation is intentionally opportunistic capacity. Background services must continue when it is asleep or offline.
## Low-power edge node
- weather collection and dispatch
- mesh-radio/repeater support
- wired server-lane placement
- low-power always-on operation
## Placement rules
1. Shared applications and databases prefer the primary application host.
2. Large data and media ingestion stay close to bulk storage.
3. Offline knowledge and resilience services remain independent of the primary host.
4. Heavy GPU work may use the workstation, but routine automation cannot require it.
5. Hardware-adjacent radio and weather services stay on low-power edge nodes.
6. DNS, file synchronization, and remote support span hosts to avoid a single failure domain.