Architecture¶
Overview¶
The lab has three physical hosts: two Proxmox VE nodes and one Unraid storage and application server. No service ports are published to the internet; remote administration and services are reached through a Tailscale WireGuard mesh. Two AdGuard Home instances provide redundant DNS.
DNS and HTTPS routing are available on the LAN and through the private mesh, with no public port forwarding.
Logical topology¶
flowchart LR
C[Client devices<br/>LAN or Tailscale mesh] --> A[AdGuard Home A<br/>primary DNS]
C --> B[AdGuard Home B<br/>redundant DNS]
A -. resolves name .-> P[Caddy<br/>HTTPS reverse proxy]
B -. resolves name .-> P
C -->|HTTPS| P
P --> N1[Proxmox node 1<br/>LXC / core services]
P --> N2[Proxmox node 2<br/>LXC / test workloads]
P --> U[Unraid<br/>storage / Docker]
PR[Prometheus<br/>collection] --> G[Grafana<br/>dashboards]
R[Recovery scripts<br/>health / restart / notify]
Platform inventory¶
| Platform | Primary role | Workload model |
|---|---|---|
| Proxmox node 1 | Core infrastructure services | LXC-first; VMs as needed |
| Proxmox node 2 | Redundancy and network lab | LXC, OpenWrt test VM, backup testing |
| Unraid server | Storage and applications | Docker containers |
Workload placement rules¶
Proxmox VE
- Use LXC for lightweight Linux services.
- Use a VM when kernel isolation, a full guest OS, or a lab scenario requires it.
- Keep core DNS and reverse-proxy roles independent from storage applications.
Unraid
- Use it for storage and Docker-backed applications.
- Keep persistent application data on managed storage.
- Use ordered startup where dependencies require a network or tunnel first.
Failure-domain intent¶
Redundant DNS reduces the impact of a single service failure. Separating DNS, reverse proxy, compute and storage makes troubleshooting direct: name resolution, routing, host state and application state can each be tested independently.
Secure access and split DNS¶
flowchart LR
L[LAN client] --> D[Local AdGuard Home]
D -.->|"rewrite *.example.net"| P[Caddy]
L -->|HTTPS| P
P --> S[Internal service]
R[Remote client] --> T[Tailscale]
T -->|split DNS: domain queries traverse the mesh| D2[AdGuard Home]
R -->|HTTPS via mesh| P
A LAN client resolves the service name through the local AdGuard Home, which
rewrites *.example.net to Caddy; Caddy terminates HTTPS and proxies to the
internal service. A remote client joins through Tailscale, and split DNS sends
domain queries across the mesh, so the client reaches the same proxy and
service.
Security controls¶
- No public port forwarding.
- Mesh membership required for remote access.
- HTTPS for service interfaces.
- Wildcard certificates issued through DNS-01.
- DNS credentials scoped to the required zone permissions.
- Secrets kept in protected environment or configuration storage, not source.
- Internal endpoints on private address space.
- Administrative interfaces not published to the internet.
Validation sequence¶
- Confirm the client is on the LAN or authenticated to Tailscale.
- Resolve the service FQDN and verify it returns the proxy address.
- Test TCP 443 to Caddy.
- Validate the certificate name and chain.
- If routing fails, test the upstream directly from the proxy host.