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
This commit is contained in:
Julia McGhee
2026-03-20 19:21:46 +00:00
parent 4135d2102e
commit 71442a0405
18 changed files with 292 additions and 92 deletions

View File

@@ -10,64 +10,79 @@ Internet
UCG (Ubiquiti Cloud Gateway)
── VLAN 1 - Management (10.0.1.0/24)
├── VLAN 10 - Servers (10.0.10.0/24)
├── VLAN 20 - IoT (10.0.20.0/24)
└── VLAN 99 - Guest (10.0.99.0/24)
── LAN (192.168.1.0/24)
└── catherby (192.168.1.50) — k3s single-node cluster
```
## VLAN Configuration
## Node
| VLAN ID | Name | Subnet | Purpose |
|---------|------------|-----------------|------------------------|
| 1 | Management | 10.0.1.0/24 | Network devices, admin |
| 10 | Servers | 10.0.10.0/24 | k3s cluster nodes |
| 20 | IoT | 10.0.20.0/24 | IoT devices |
| 99 | Guest | 10.0.99.0/24 | Guest WiFi |
## DHCP Reservations (VLAN 10 — Servers)
| Hostname | IP Address | MAC Address | Role |
|----------|-------------|-------------------|-------------|
| nuc01 | 10.0.10.11 | XX:XX:XX:XX:XX:01 | k3s server |
| nuc02 | 10.0.10.12 | XX:XX:XX:XX:XX:02 | k3s agent |
| nuc03 | 10.0.10.13 | XX:XX:XX:XX:XX:03 | k3s agent |
| 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 | 10.0.10.11 | 80 | TCP |
| HTTPS | 443 | 10.0.10.11 | 443 | TCP |
| k3s API | 6443 | 10.0.10.11 | 6443 | TCP |
| 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 nuc01 where Traefik runs as the ingress controller.
> k3s API port is only forwarded if external kubectl access is needed.
> **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
### Inter-VLAN Rules
- **Servers → Internet**: Allow all outbound
- **Servers → Management**: Allow (for UCG API access)
- **IoT → Servers**: Deny (isolate IoT from cluster)
- **Guest → ***: Allow Internet only, block all local
### Inbound Rules
- Allow established/related connections
- Allow HTTP (80) and HTTPS (443) to VLAN 10
- Allow HTTP (80) and HTTPS (443) to 192.168.1.50
- Drop all other inbound
## DNS Configuration
- **Internal DNS**: Use UCG as DNS server for VLAN 10
- **External DNS**: Cloudflare (1.1.1.1, 1.0.0.1)
- **Local DNS entries**: Add `*.homelab.local` → 10.0.10.11 for internal access
## Setup Steps
1. **Create VLANs** in UniFi Network → Settings → Networks
2. **Assign ports** on the switch to VLAN 10 for NUC connections
3. **Create DHCP reservations** for each NUC (Settings → Networks → VLAN 10)
4. **Add port forwarding rules** (Settings → Firewall & Security → Port Forwarding)
5. **Configure firewall rules** (Settings → Firewall & Security → Firewall Rules)
6. **Set local DNS** entries for *.homelab.local
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)