Routing and Access

This page explains how names resolve and how requests reach services. See Inventory and Services for the authoritative addresses and ports.

Components

LAN: 10.0.0.0/24
 
                         Tailscale tailnet
                                |
                                v
                    Lumbridge / Infra VM
                    10.0.0.112
                    - Tailscale subnet router
                    - Tailscale exit node
                    - AdGuard Home DNS
                         |
                         | DNS rewrites
                         v
  +----------------------+-----------------------+
  |                      |                       |
  v                      v                       v
Falador               Varrock                Ardougne
TrueNAS               GPU VM                 Services VM
10.0.0.234            10.0.0.111             10.0.0.113
                      Jupyter :8888          Caddy :80/:443
                                             Docker services

AdGuard answers internal tuerolab.ca names. Caddy terminates HTTPS on Ardougne and either proxies to a Docker container or reaches a service on another VM by its fixed LAN IP.

DNS Status

AdGuard listens at 10.0.0.112:53 and has rewrites for hosts and Caddy-backed service names.

Current limitation: the router does not distribute AdGuard as LAN DNS. The Mac is manually configured to use 10.0.0.112; other LAN devices and VMs should not assume that *.tuerolab.ca resolves until the router is replaced or they are explicitly configured to use AdGuard.

ClientName resolution todayPreferred access
MacAdGuard at 10.0.0.112HTTPS service names such as https://radarr.tuerolab.ca
Other LAN deviceRouter/default DNS unless manually configuredDirect IP and port, or configure AdGuard manually
Homelab VMDo not assume AdGuard DNSFixed IP and direct port when calling another VM
Tailscale clientSplit DNS sends tuerolab.ca queries to AdGuardHTTPS service names after route and DNS setup

Once the new router distributes 10.0.0.112 as DNS, LAN devices can use the HTTPS names without individual DNS configuration.

LAN Browser Flow

From the Mac, a Caddy-backed service follows this path:

Browser
  |
  | DNS query: radarr.tuerolab.ca
  v
AdGuard / Lumbridge (10.0.0.112)
  |
  | rewrite answer: 10.0.0.113
  v
Browser connects with HTTPS to Ardougne (10.0.0.113:443)
  |
  v
Caddy
  |
  +--> radarr:7878 on Docker proxy network
  +--> sonarr:8989 on Docker proxy network
  +--> bazarr:6767 on Docker proxy network
  +--> prowlarr:9696 on Docker proxy network
  +--> host.docker.internal:8080 for qBittorrent through Gluetun
  +--> 10.0.0.112:3001 for AdGuard Home
  +--> 10.0.0.111:8888 for JupyterLab
  +--> 10.0.0.234:81 for TrueNAS
  +--> homepage:3000 for Homepage
  `--> uptime-kuma:3001 for Uptime Kuma

The browser sees one HTTPS endpoint, 10.0.0.113:443, even when the upstream service runs on Lumbridge or Varrock.

Homepage and Uptime Kuma use the same Caddy endpoint but are restricted to requests sourced from the LAN or Tailscale address ranges. They are not intended for public Internet access.

How One IP Selects Different Services

DNS chooses an IP address only. It does not choose an application port or a Docker service.

radarr.tuerolab.ca  --DNS-->  10.0.0.113
sonarr.tuerolab.ca  --DNS-->  10.0.0.113

Both HTTPS URLs use the standard HTTPS port, so both requests connect to Caddy at 10.0.0.113:443. The hostname remains part of the connection and request, allowing Caddy to choose the correct certificate and upstream route.

https://radarr.tuerolab.ca
  |
  | DNS answer: 10.0.0.113
  | TCP/TLS connection: 10.0.0.113:443
  | TLS hostname (SNI): radarr.tuerolab.ca
  | HTTP Host header:   radarr.tuerolab.ca
  v
Caddy route: radarr.tuerolab.ca -> radarr:7878
 
https://sonarr.tuerolab.ca
  |
  | DNS answer: 10.0.0.113
  | TCP/TLS connection: 10.0.0.113:443
  | TLS hostname (SNI): sonarr.tuerolab.ca
  | HTTP Host header:   sonarr.tuerolab.ca
  v
Caddy route: sonarr.tuerolab.ca -> sonarr:8989

This is name-based virtual hosting: many HTTPS names share Caddy’s one IP address and port 443, while Caddy uses the requested hostname to select the certificate and proxy target.

Proxmox follows the same pattern: https://keldagrim.tuerolab.ca reaches Caddy, which proxies to Keldagrim’s HTTPS listener at 10.0.0.110:8006. This route is restricted to LAN and Tailscale source addresses.

The direct application ports bypass Caddy and therefore require the port in the URL:

http://10.0.0.113:7878  -> Radarr
http://10.0.0.113:8989  -> Sonarr

VM-to-VM Flow

The VMs currently should use direct IP/port access because router-provided DNS is not yet available to them. Caddy itself does not need guest DNS for cross-VM routes because its upstreams are fixed IP addresses.

Ardougne Caddy
  |
  +--> 10.0.0.112:3001  AdGuard Home
  `--> 10.0.0.111:8888  JupyterLab
 
Example direct recovery access from a VM:
  http://10.0.0.112:3001
  http://10.0.0.111:8888

Direct ports are also useful for recovery when DNS or Caddy is unavailable. They are currently published and are not restricted by a host firewall configured in this repository.

Remote Tailscale Flow

Lumbridge advertises 10.0.0.0/24 as a subnet route. A Tailscale device must accept that route to reach the LAN addresses returned by AdGuard.

Remote Tailscale device
  |
  | split DNS query for *.tuerolab.ca
  v
AdGuard / Lumbridge over Tailscale (10.0.0.112)
  |
  | returns a private LAN address, for example 10.0.0.113
  v
Tailscale subnet route
  |
  v
Lumbridge routes to the LAN
  |
  v
Ardougne / Caddy (10.0.0.113:443)
  |
  `--> requested service

Selecting Lumbridge as a Tailscale exit node sends general Internet traffic through it. The split-DNS setup additionally permits tuerolab.ca names to work remotely without using the exit node, provided the subnet route is approved and active.

HTTPS and Certificates

Caddy uses Cloudflare DNS-01 validation to obtain Let’s Encrypt certificates. No public inbound port forwarding is required for certificate issuance.

Caddy on Ardougne
  |
  | Cloudflare API token from Ansible Vault
  v
Cloudflare DNS API creates temporary ACME TXT record
  |
  v
Let's Encrypt validates DNS and issues certificate

The Cloudflare token is rendered to Ardougne’s cloudflare.env by Ansible and is not part of normal appdata configuration.

Adding a Caddy-Backed Service

For an HTTP service exposed as name.tuerolab.ca:

  1. Add its AdGuard rewrite in group_vars/infra_servers/vars.yml, normally pointing to 10.0.0.113.
  2. Add its Caddy route in roles/reverse_proxy/defaults/main.yml.
  3. Use a Docker service name and port for containers on the proxy network; use a fixed VM IP and port for services outside Docker.
  4. Deploy both changes:
./run.sh --limit infra_servers --tags adguard
./run.sh --limit services_servers --tags proxy
  1. Verify DNS and HTTPS:
dig @10.0.0.112 name.tuerolab.ca +short
curl --fail --head https://name.tuerolab.ca

Caddy is recreated when Caddyfile changes. This is deliberate: the file is a bind mount and Ansible replaces templates atomically, so a reload alone can retain the old mounted file inode.