Network: How Traffic and DNS Work

Single subnet, DHCP on the router, three DNS servers, and one VIP that the internet talks to. Here’s how I have it set up.


One LAN, no VLANs

Everything is on one flat subnet. The router is the gateway and the only DHCP server. Every infrastructure device has a DHCP reservation (MAC → IP) so IPs don’t change. I don’t run VLANs or a managed switch; isolation is host-level (firewall, SSH, nginx allow/deny) rather than L2.


DHCP (router)

The MikroTik hEX runs the DHCP server on the LAN interface. In the DHCP network config I set:

Lease time is short (e.g. 10 minutes) so that if a DNS node fails, clients refresh and pick another quickly. Tradeoff: a bit more DHCP traffic.


DNS: three Pi-holes

I run three Pi-hole instances:

  1. Pi-hole 1 — VM on Host 1 (same host as the Docker VM and nginx primary).
  2. Pi-hole 2 — TrueNAS Scale app on Host 3 (same IP as the NAS, different port).
  3. Pi-hole 3 — VM on Host 2 (same host as Plex and nginx secondary).

They’re independent: same blocklists and similar config, but no automatic sync between them. I use the Pi-hole web UI (over HTTPS via nginx, LAN-only) to manage each. Having three spread across three hosts means one host or VM failure doesn’t kill DNS for the house.


How HTTPS reaches the services

  1. Router — Port forward: external 80 and 443 → internal VIP (the keepalived floating address). The router doesn’t know about “primary” or “secondary” nginx; it always sends traffic to the VIP. keepalived ensures the VIP is on the primary nginx VM, or on the secondary if the primary is down.
  2. nginx (primary or secondary) — Listens on the VIP (and its own fixed IP). One config file: all upstreams (Plex, Bitwarden, Mealie, etc.) and all server_name blocks (e.g. plex.detellem.com, bitwarden.detellem.com). TLS is terminated here; backends are HTTP. One wildcard cert covers all subdomains.
  3. Backends — nginx proxies to the right host:port by Host header. Plex is on Host 2; Bitwarden, Mealie, and the rest are on the Docker VM on Host 1; Pi-hole admin is proxied to each Pi-hole’s IP/port.

So: Internet → router (NAT) → VIP → nginx → backend. No client ever talks directly to the Docker VM or Plex from the internet; only nginx does.


Certificates and domain


Summary

Piece What I use
Subnet Single LAN, no VLANs
DHCP MikroTik hEX, reservations for all infra
DNS Three Pi-holes (Host 1 VM, Host 2 VM, Host 3 app)
Inbound Router forwards 80/443 → VIP; keepalived moves VIP between two nginx VMs
TLS Wildcard Let’s Encrypt; certbot on primary; sync to secondary
DDNS Script on primary nginx, secondary nginx, and one Pi-hole; systemd timer

← Architecture | Back to index | Next: Services →