HOME LAB / ENGINEERING NOTES
Architecture without
the secrets.
This is a practical description of how I organise my home environment: what each layer does, why it exists and how the pieces connect. Private addresses have been replaced with 172.16.1.0/24; credentials, keys, tokens and sensitive hostnames are illustrative.
An evolving personal project. These are patterns and examples, not a production configuration dump.
Environment map
The router controls traffic, the NAS keeps low-power services and data online around the clock, and the PC supplies GPU compute. Gaming or restarting the PC therefore does not interrupt passwords, music, monitoring or the website.
Internet → MikroTik 172.16.1.1 → NAS 172.16.1.12
└────→ PC 172.16.1.34
Router: DHCP / DNS / NAT / WireGuard
NAS: Caddy / Homepage / Vaultwarden / Navidrome / Grafana
PC: Ollama / Open WebUI / agent tools / ComfyUINetwork, DNS and WireGuard
I keep DHCP, local DNS, NAT and WireGuard on the router. I start changes with a configuration export and read-only checks of DHCP leases, firewall/NAT rules and active services. WireGuard provides phone access to private services; input rules handle the tunnel while forward rules separately allow DNS, LAN access and optional full-tunnel Internet access.
/ip dhcp-server lease print detail without-paging
/ip dns static print detail without-paging
/ip firewall filter print stats
/ip firewall nat print detail without-pagingA successful VPN handshake or ping is only part of the path. It does not prove that the right HTTP host, TLS certificate or reverse proxy is serving the application.
NAS and persistent containers
The NAS runs services that need continuity rather than GPU power. Each Compose project has its own configuration and persistent data directory. Containers are replaceable; application data is not.
| Service | Purpose | Design choice |
|---|---|---|
| Homepage | Service and status portal. | YAML, private LAN. |
| Vaultwarden | Bitwarden-compatible password vault. | Persistent volume, HTTPS. |
| Navidrome | Personal music library. | Music mounted read-only; data separate. |
| Uptime Kuma / MySpeed | Availability and connection history. | Persistent state and Homepage widgets. |
| Grafana / Loki / Alloy | Logs and trends. | Persistent Loki data and provisioned dashboards. |
| Caddy | TLS and reverse proxy. | Certificate state outside container filesystem. |
services:
example-service:
image: example/service:YOUR_VERSION
restart: unless-stopped
ports: ["172.16.1.12:YOUR_PORT:8080"]
volumes: ["./data:/app/data"]
environment: { APP_TOKEN: "YOUR_TOKEN" }Small public surface: Caddy and HTTPS
Only the static portfolio and music service are public. Caddy is the single HTTP/HTTPS entry point: it terminates TLS, applies headers and proxies only the required service. Chat, Grafana, DSM and administration stay in LAN/VPN.
home.example.net { root * /srv/homepage; encode gzip; file_server }
music.example.net { reverse_proxy navidrome:4533 }Monitoring and logs
Uptime Kuma checks connectivity and devices, MySpeed records throughput, and Grafana presents both rate charts and top recurring messages. Router syslog is received by Alloy on separate severity ports, labelled, stored in Loki and queried with LogQL. It is intentionally lighter than a full ELK deployment, but enough to distinguish one-off failures from a trend.
remote=172.16.1.12 remote-port=1514 # other
remote=172.16.1.12 remote-port=1515 # error
remote=172.16.1.12 remote-port=1516 # criticalPC, Docker and local AI
The main agent runs on the PC with GPU. Open WebUI is containerised; Ollama runs on Windows and is reached through host.docker.internal. Search, Google bridge, SSH operator and memory components communicate on an internal Docker network.
OLLAMA_BASE_URLS=http://host.docker.internal:11434
WEBUI_SECRET_KEY=YOUR_RANDOM_SECRET
OBSERVER_TOKEN=YOUR_LONG_RANDOM_TOKENBefore image generation, the tool asks Ollama to unload the language model so ComfyUI gets priority on the GPU. This is resource coordination, not a guarantee that all VRAM is available to one process.
Agent tools, not magic
The model selects a tool, receives a structured result and explains it. Web search goes through SearXNG; PC Observer exposes selected read-only Windows data; SSH Operator uses configured keys and audit logs; the Google bridge uses OAuth; ComfyUI receives image workflows. Sending email remains a reviewed draft first.
mail_send: require_explicit_approval
calendar_create: allowed_after_event_summary
pc_observer: read_only
SSH_PRIVATE_KEY_PATH=/run/secrets/YOUR_SSH_KEYTool access is not the same as model understanding. I test the full path: request, function call, result, source date and final response. Instructions inside webpages and email are treated as content, never as commands.
Build order
- Network foundations: router, DHCP, DNS, NAT and WireGuard.
- Persistent services: portal, monitoring, password vault, music and HTTPS.
- Observability: measurements, device checks, Loki and Grafana.
- PC AI: Docker Desktop, Ollama, Open WebUI and GPU management.
- Agent integrations: search, PC read-only data, SSH, Gmail, Calendar and ComfyUI.
- Public documentation: static website, Caddy and privacy information.
It is a logical order rather than a universal recipe: stable addressing, backup, access and monitoring come before convenience and agent autonomy.
What stays private
- Real IPs, device names, WireGuard/SSH keys, OAuth tokens and passwords.
- DSM, Grafana, Home AI and password administration interfaces.
- Application data, model folders, vault data and configuration backups.
- State-changing operations: email requires approval and SSH has separate privileges and audit.