Files
Julia McGhee 71442a0405 Switch from homelab.local to coreworlds.io with split-horizon DNS and LAN-only access controls
- Migrate all ingress hostnames from *.homelab.local to *.coreworlds.io
- Remove broken Traefik certresolver config (cert-manager handles TLS)
- Add internal-only IP allowlist middleware for platform services
- Add IngressRoutes for ArgoCD, Grafana, Longhorn (LAN-only via middleware)
- Seal and add Cloudflare API token for cert-manager DNS-01 challenges
- Update cert-manager ClusterIssuers with real email
- Update k3s TLS SAN to k3s.coreworlds.io
- Rewrite Ubiquiti docs for single-node topology and split-horizon DNS
- Fix seal-secret.sh controller name to match Helm release
- Add UCG DNS setup script using API key auth
2026-03-20 19:21:46 +00:00
..

Ubiquiti Cloud Gateway Configuration

Documentation for the Ubiquiti Cloud Gateway (UCG) that manages network ingress for the homelab cluster.

Network Layout

Internet
  │
  ▼
UCG (Ubiquiti Cloud Gateway)
  │
  └── LAN (192.168.1.0/24)
        │
        └── catherby (192.168.1.50) — k3s single-node cluster

Node

Hostname IP Address Role
catherby 192.168.1.50 k3s server (all)

Port Forwarding Rules

Name External Port Internal IP Internal Port Protocol
HTTP 80 192.168.1.50 80 TCP
HTTPS 443 192.168.1.50 443 TCP

Note

: HTTP/HTTPS traffic routes to catherby where Traefik runs as the ingress controller. Do NOT forward port 6443 (k3s API) — kubectl access is LAN-only or via VPN.

Split-Horizon DNS

Same hostnames (*.coreworlds.io) resolve differently depending on the client's network:

Source Resolution Path
Internet Cloudflare DNS → public IP → UCG WAN:443 → port-forward → 192.168.1.50:443
LAN UCG local DNS → 192.168.1.50 Direct to 192.168.1.50:443 (no hairpin)

Why split-horizon?

Without it, LAN clients hitting the public IP would require hairpin NAT (traffic leaves the network and comes back in). UCG local DNS overrides avoid this — LAN clients resolve directly to the node IP.

UCG Local DNS Configuration

Add these entries in Settings → Networks → DNS:

Hostname IP Address
coreworlds.io 192.168.1.50
*.coreworlds.io 192.168.1.50

If the UCG doesn't support wildcard DNS entries, add individual records: api.coreworlds.io, argocd.coreworlds.io, grafana.coreworlds.io, longhorn.coreworlds.io, preview.coreworlds.io, api-preview.coreworlds.io

Cloudflare DNS (External)

Managed in Cloudflare dashboard for coreworlds.io:

Type Name Value Proxy
A coreworlds.io (public static IP) Off
CNAME * coreworlds.io Off

Cloudflare proxy must be off (DNS-only / grey cloud) so that cert-manager DNS-01 challenges work and Traefik sees real client IPs for the internal-only middleware.

Firewall Rules

Inbound Rules

  • Allow established/related connections
  • Allow HTTP (80) and HTTPS (443) to 192.168.1.50
  • Drop all other inbound

Setup Steps

  1. Add port forwarding rules (Settings → Firewall & Security → Port Forwarding)
    • WAN 80 → 192.168.1.50:80
    • WAN 443 → 192.168.1.50:443
  2. Configure local DNS (Settings → Networks → DNS)
    • *.coreworlds.io → 192.168.1.50
  3. Configure Cloudflare DNS (Cloudflare dashboard)
    • A record: coreworlds.io → public IP
    • CNAME: *coreworlds.io
  4. Configure firewall rules (Settings → Firewall & Security → Firewall Rules)