The whole machine, drawn

Wiring diagram

Every component, every connection between them, and the two separate doors traffic arrives through — with each arrow labelled so it says what it actually carries.

■ Blue
over the tunnel · me only
■ Amber
house WiFi · roommates
■ Green
disk and storage
01

The system

Follow any arrow from top to bottom and you have a complete request. Container addresses are deliberately absent: Docker assigns them in start order and they change whenever the stack is recreated.

My laptop & phone any network, anywhere Roommates & the TV in the house only encrypted tunnel house wifi tailscale0 100.64.0.10 wlp4s0 192.168.1.10 homie — thinkpad t470 sshd on the host Caddy — real HTTPS :443 · :8443 · :8444 · :8445 tailnet · :8446 docs, localhost :22 :443 · :8443 · :8444 · :8445 :8096 — direct, no proxy, plain HTTP Syncthing :8384 admin n8n no host port ollama no host port Jellyfin :8096 — the only shared door plain HTTP, private network one shared network namespace gluetun holds the tunnel qBittorrent no interface :8444 → gluetun:8080 tun0 · WireGuard — the only way out NordVPN exit what the swarm sees school-work internal disk /mnt/t7 — one physical drive Movies · TV the library downloads same drive backups same drive read / write read / write read-only — cannot delete media renames, then files nightly — bin/homie-backup, on a systemd timer
Every arrow was verified by connecting, not inferred from configuration.

Three things the drawing makes obvious

The amber path terminates at one box

Jellyfin is the only thing the house can reach, and that arrow never passes through Caddy. Every other service is on a blue path or on no path at all.

sshd sits outside every container

It connects straight to the disk, bypassing Docker and Caddy — which is why it keeps working when both are broken. That independence is deliberate: it is the way back in.

Two boxes share one drive

The library and its backup are both inside the /mnt/t7 outline — which the drawing shows better than prose can. It is the top entry in the gap list.

The one arrow not drawn

Syncthing’s sync port, :22000, is also open on the house WiFi. It is safe there because every peer must be approved by device ID and it carries no admin access — but it is a second thing listening on the amber interface, so it is worth knowing about rather than discovering.

02

What Caddy actually changes

The clearest way to see the point of a reverse proxy is to draw the same system without one.

without a reverse proxy you four connections, four certificates, four renewal schedules, four chances to get it wrong Jellyfin Syncthing qBittorrent n8n with Caddy you one HTTPS connection Caddy one cert plain HTTP, never leaves the machine Jellyfin Syncthing qBittorrent n8n
The difference is where encryption lives. On the left it is a problem each service solves separately; on the right it is solved once, at the door.

The prediction has been tested twice. Adding the downloader meant one Caddy block and one more port on an existing certificate; adding n8n meant the same again. Neither was a new security decision.

Why SSH is drawn outside

It runs on the host, not in a container, so it needs neither Docker’s port forwarding nor Caddy’s routing. That is the way back in when something else is broken.

Why the TV skips Caddy

Routing it through Caddy would mean installing a certificate on every roommate device. Instead that traffic stays on the house network in plain HTTP, where the WiFi’s own encryption covers it.

Why two boxes have no address

n8n and ollama publish no host port at all — Caddy and n8n reach them by container name. A port that is never published cannot be published to the wrong interface.

Why qBittorrent has no interface

It shares gluetun’s namespace rather than having its own, so the tunnel is the only way out. A dead tunnel means no connection at all, rather than a fallback to the house line.

Why one arrow is read-only

Jellyfin can read the library but not change it, so no bug can delete it. The cost is no subtitle downloads and no metadata sidecars — and it matters more now that backups live on the same drive.

Why the backup arrow is dashed

It is not a live connection. A systemd timer runs bin/homie-backup nightly; the rest of the time that path does not exist.