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:
@@ -7,7 +7,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
rules:
|
rules:
|
||||||
- host: api.homelab.local
|
- host: api.coreworlds.io
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -19,5 +19,5 @@ spec:
|
|||||||
number: 80
|
number: 80
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- api.homelab.local
|
- api.coreworlds.io
|
||||||
secretName: api-tls
|
secretName: api-tls
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ patches:
|
|||||||
patch: |
|
patch: |
|
||||||
- op: replace
|
- op: replace
|
||||||
path: /spec/rules/0/host
|
path: /spec/rules/0/host
|
||||||
value: api-preview.homelab.local
|
value: api-preview.coreworlds.io
|
||||||
- op: replace
|
- op: replace
|
||||||
path: /spec/tls/0/hosts/0
|
path: /spec/tls/0/hosts/0
|
||||||
value: api-preview.homelab.local
|
value: api-preview.coreworlds.io
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
ingressClassName: traefik
|
ingressClassName: traefik
|
||||||
rules:
|
rules:
|
||||||
- host: homelab.local
|
- host: coreworlds.io
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
@@ -19,5 +19,5 @@ spec:
|
|||||||
number: 80
|
number: 80
|
||||||
tls:
|
tls:
|
||||||
- hosts:
|
- hosts:
|
||||||
- homelab.local
|
- coreworlds.io
|
||||||
secretName: web-tls
|
secretName: web-tls
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ patches:
|
|||||||
patch: |
|
patch: |
|
||||||
- op: replace
|
- op: replace
|
||||||
path: /spec/rules/0/host
|
path: /spec/rules/0/host
|
||||||
value: preview.homelab.local
|
value: preview.coreworlds.io
|
||||||
- op: replace
|
- op: replace
|
||||||
path: /spec/tls/0/hosts/0
|
path: /spec/tls/0/hosts/0
|
||||||
value: preview.homelab.local
|
value: preview.coreworlds.io
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ k3s_server_args: >-
|
|||||||
--disable=servicelb
|
--disable=servicelb
|
||||||
--write-kubeconfig-mode=644
|
--write-kubeconfig-mode=644
|
||||||
--tls-san={{ ansible_host }}
|
--tls-san={{ ansible_host }}
|
||||||
--tls-san=k3s.homelab.local
|
--tls-san=k3s.coreworlds.io
|
||||||
--kube-apiserver-arg=audit-log-maxage=30
|
--kube-apiserver-arg=audit-log-maxage=30
|
||||||
--kube-apiserver-arg=audit-log-maxbackup=10
|
--kube-apiserver-arg=audit-log-maxbackup=10
|
||||||
--kube-apiserver-arg=audit-log-maxsize=100
|
--kube-apiserver-arg=audit-log-maxsize=100
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
apiVersion: bitnami.com/v1alpha1
|
||||||
|
kind: SealedSecret
|
||||||
|
metadata:
|
||||||
|
name: cloudflare-api-token
|
||||||
|
namespace: cert-manager
|
||||||
|
spec:
|
||||||
|
encryptedData:
|
||||||
|
api-token: AgBhOS+L5bWj4YIxV+u6waATX0iT9EAOCoA2FNDcJfqcH4nICK7zUakh7KaWjrLIYqlNHOFU66a5MZiuNs9IGtDwNSRXBXsuYauJoI2NripYchZ4InswNdzN3CjE9kgOwShOjCAcJz+emogXJq5lSFGr9pIYeyaZ2NIxKR6kcqBmNB1lTBeAOB5c8h/xh/eKq66HEd2gcaXqYgpe+w9I90f1WjASqV92oj6CNT4XhExAmThia7olA5n0o9ogJjdIb9LND/AL/Hf6USGpdfpu7Dr4XfNG1JzyksSiZVIXDXFlO7N6fyWrhOFWCZFCzdIvVhnt8niqCgSY2LutodqMjkfUM7WXjflznqf1x7b8jMb/O6RIYTGkOs8Dno7FrrYXJXOVoumbbd4eBvRUunfsa3qIE6LYSDmb9b8qZx03XKoS4hvcNSXh9VPJYCCK1uRHH6sbAcRwyLalAkuysAtOqH7ZIhAo5GsBwSaQjNVQIxFnDbKtOpQIcS3+nnJcPMcMa56OAAxFDG16J+U16PI/KJzhO4ubBWNt60yALhTtWizygVCPSxtLOU78VbMmAdZwdkc9daOy2USVDSxgJd0EhTunoQYcZUuJqjzCTlfflGP9XJ7WgGItXhsnQTJZVk7Np4s/9KGZtnJVTYpFp94Jp3yPxDXcgJX+6I+YSkqjvq3iYNlVrF4NDyEUE8C00zDE+6zbybsth1t6xXsMWxEU3g1rLtBxYIppBuI0INCLTUCuCzKUSC9oQvXo9mAVXQjgJ4I1za01lA==
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
name: cloudflare-api-token
|
||||||
|
namespace: cert-manager
|
||||||
@@ -9,7 +9,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
acme:
|
acme:
|
||||||
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
server: https://acme-staging-v02.api.letsencrypt.org/directory
|
||||||
email: admin@homelab.local
|
email: julia.eloise@pm.me
|
||||||
privateKeySecretRef:
|
privateKeySecretRef:
|
||||||
name: letsencrypt-staging-key
|
name: letsencrypt-staging-key
|
||||||
solvers:
|
solvers:
|
||||||
@@ -26,7 +26,7 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
acme:
|
acme:
|
||||||
server: https://acme-v02.api.letsencrypt.org/directory
|
server: https://acme-v02.api.letsencrypt.org/directory
|
||||||
email: admin@homelab.local
|
email: julia.eloise@pm.me
|
||||||
privateKeySecretRef:
|
privateKeySecretRef:
|
||||||
name: letsencrypt-production-key
|
name: letsencrypt-production-key
|
||||||
solvers:
|
solvers:
|
||||||
|
|||||||
@@ -2,3 +2,4 @@ apiVersion: kustomize.config.k8s.io/v1beta1
|
|||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
- clusterissuer-letsencrypt.yaml
|
- clusterissuer-letsencrypt.yaml
|
||||||
|
- cloudflare-api-token-sealed.yaml
|
||||||
|
|||||||
@@ -22,5 +22,3 @@ spec:
|
|||||||
metrics:
|
metrics:
|
||||||
prometheus:
|
prometheus:
|
||||||
entryPoint: metrics
|
entryPoint: metrics
|
||||||
additionalArguments:
|
|
||||||
- "--entrypoints.websecure.http.tls.certresolver=letsencrypt"
|
|
||||||
|
|||||||
22
infra/kubernetes/platform/traefik/ingressroute-argocd.yaml
Normal file
22
infra/kubernetes/platform/traefik/ingressroute-argocd.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: argocd
|
||||||
|
namespace: platform
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-production
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`argocd.coreworlds.io`)
|
||||||
|
kind: Rule
|
||||||
|
middlewares:
|
||||||
|
- name: internal-only
|
||||||
|
namespace: platform
|
||||||
|
services:
|
||||||
|
- name: argocd-server
|
||||||
|
namespace: argocd
|
||||||
|
port: 80
|
||||||
|
tls:
|
||||||
|
secretName: argocd-tls
|
||||||
22
infra/kubernetes/platform/traefik/ingressroute-grafana.yaml
Normal file
22
infra/kubernetes/platform/traefik/ingressroute-grafana.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: grafana
|
||||||
|
namespace: platform
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-production
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`grafana.coreworlds.io`)
|
||||||
|
kind: Rule
|
||||||
|
middlewares:
|
||||||
|
- name: internal-only
|
||||||
|
namespace: platform
|
||||||
|
services:
|
||||||
|
- name: kube-prometheus-stack-grafana
|
||||||
|
namespace: observability
|
||||||
|
port: 80
|
||||||
|
tls:
|
||||||
|
secretName: grafana-tls
|
||||||
22
infra/kubernetes/platform/traefik/ingressroute-longhorn.yaml
Normal file
22
infra/kubernetes/platform/traefik/ingressroute-longhorn.yaml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: IngressRoute
|
||||||
|
metadata:
|
||||||
|
name: longhorn
|
||||||
|
namespace: platform
|
||||||
|
annotations:
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-production
|
||||||
|
spec:
|
||||||
|
entryPoints:
|
||||||
|
- websecure
|
||||||
|
routes:
|
||||||
|
- match: Host(`longhorn.coreworlds.io`)
|
||||||
|
kind: Rule
|
||||||
|
middlewares:
|
||||||
|
- name: internal-only
|
||||||
|
namespace: platform
|
||||||
|
services:
|
||||||
|
- name: longhorn-frontend
|
||||||
|
namespace: longhorn-system
|
||||||
|
port: 80
|
||||||
|
tls:
|
||||||
|
secretName: longhorn-tls
|
||||||
@@ -3,3 +3,7 @@ kind: Kustomization
|
|||||||
resources:
|
resources:
|
||||||
- helmchartconfig.yaml
|
- helmchartconfig.yaml
|
||||||
- middleware-default-headers.yaml
|
- middleware-default-headers.yaml
|
||||||
|
- middleware-internal-only.yaml
|
||||||
|
- ingressroute-argocd.yaml
|
||||||
|
- ingressroute-grafana.yaml
|
||||||
|
- ingressroute-longhorn.yaml
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: traefik.io/v1alpha1
|
||||||
|
kind: Middleware
|
||||||
|
metadata:
|
||||||
|
name: internal-only
|
||||||
|
namespace: platform
|
||||||
|
spec:
|
||||||
|
ipAllowList:
|
||||||
|
sourceRange:
|
||||||
|
- 192.168.1.0/24
|
||||||
|
- 10.42.0.0/16
|
||||||
|
- 10.43.0.0/16
|
||||||
@@ -10,64 +10,79 @@ Internet
|
|||||||
▼
|
▼
|
||||||
UCG (Ubiquiti Cloud Gateway)
|
UCG (Ubiquiti Cloud Gateway)
|
||||||
│
|
│
|
||||||
├── VLAN 1 - Management (10.0.1.0/24)
|
└── LAN (192.168.1.0/24)
|
||||||
├── VLAN 10 - Servers (10.0.10.0/24)
|
│
|
||||||
├── VLAN 20 - IoT (10.0.20.0/24)
|
└── catherby (192.168.1.50) — k3s single-node cluster
|
||||||
└── VLAN 99 - Guest (10.0.99.0/24)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## VLAN Configuration
|
## Node
|
||||||
|
|
||||||
| VLAN ID | Name | Subnet | Purpose |
|
| Hostname | IP Address | Role |
|
||||||
|---------|------------|-----------------|------------------------|
|
|-----------|---------------|-------------------|
|
||||||
| 1 | Management | 10.0.1.0/24 | Network devices, admin |
|
| catherby | 192.168.1.50 | k3s server (all) |
|
||||||
| 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 |
|
|
||||||
|
|
||||||
## Port Forwarding Rules
|
## Port Forwarding Rules
|
||||||
|
|
||||||
| Name | External Port | Internal IP | Internal Port | Protocol |
|
| Name | External Port | Internal IP | Internal Port | Protocol |
|
||||||
|------------|---------------|--------------|---------------|----------|
|
|-------|---------------|----------------|---------------|----------|
|
||||||
| HTTP | 80 | 10.0.10.11 | 80 | TCP |
|
| HTTP | 80 | 192.168.1.50 | 80 | TCP |
|
||||||
| HTTPS | 443 | 10.0.10.11 | 443 | TCP |
|
| HTTPS | 443 | 192.168.1.50 | 443 | TCP |
|
||||||
| k3s API | 6443 | 10.0.10.11 | 6443 | TCP |
|
|
||||||
|
|
||||||
> **Note**: HTTP/HTTPS traffic routes to nuc01 where Traefik runs as the ingress controller.
|
> **Note**: HTTP/HTTPS traffic routes to catherby where Traefik runs as the ingress controller.
|
||||||
> k3s API port is only forwarded if external kubectl access is needed.
|
> 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
|
## 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
|
### Inbound Rules
|
||||||
- Allow established/related connections
|
- 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
|
- 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
|
## Setup Steps
|
||||||
|
|
||||||
1. **Create VLANs** in UniFi Network → Settings → Networks
|
1. **Add port forwarding rules** (Settings → Firewall & Security → Port Forwarding)
|
||||||
2. **Assign ports** on the switch to VLAN 10 for NUC connections
|
- WAN 80 → 192.168.1.50:80
|
||||||
3. **Create DHCP reservations** for each NUC (Settings → Networks → VLAN 10)
|
- WAN 443 → 192.168.1.50:443
|
||||||
4. **Add port forwarding rules** (Settings → Firewall & Security → Port Forwarding)
|
2. **Configure local DNS** (Settings → Networks → DNS)
|
||||||
5. **Configure firewall rules** (Settings → Firewall & Security → Firewall Rules)
|
- `*.coreworlds.io` → 192.168.1.50
|
||||||
6. **Set local DNS** entries for *.homelab.local
|
3. **Configure Cloudflare DNS** (Cloudflare dashboard)
|
||||||
|
- A record: `coreworlds.io` → public IP
|
||||||
|
- CNAME: `*` → `coreworlds.io`
|
||||||
|
4. **Configure firewall rules** (Settings → Firewall & Security → Firewall Rules)
|
||||||
|
|||||||
@@ -1,37 +1,66 @@
|
|||||||
# Network Diagram
|
# Network Diagram
|
||||||
|
|
||||||
```
|
## External Traffic Flow
|
||||||
┌──────────────┐
|
|
||||||
│ Internet │
|
|
||||||
└──────┬───────┘
|
|
||||||
│
|
|
||||||
┌──────┴───────┐
|
|
||||||
│ UCG │
|
|
||||||
│ 10.0.1.1 │
|
|
||||||
└──────┬───────┘
|
|
||||||
│
|
|
||||||
┌────────────┼────────────┐
|
|
||||||
│ │ │
|
|
||||||
┌──────┴───┐ ┌─────┴────┐ ┌────┴──────┐
|
|
||||||
│ VLAN 10 │ │ VLAN 20 │ │ VLAN 99 │
|
|
||||||
│ Servers │ │ IoT │ │ Guest │
|
|
||||||
└──────┬───┘ └──────────┘ └───────────┘
|
|
||||||
│
|
|
||||||
┌────────────┼────────────┐
|
|
||||||
│ │ │
|
|
||||||
┌────┴────┐ ┌────┴────┐ ┌────┴────┐
|
|
||||||
│ nuc01 │ │ nuc02 │ │ nuc03 │
|
|
||||||
│ .10.11 │ │ .10.12 │ │ .10.13 │
|
|
||||||
│ server │ │ agent │ │ agent │
|
|
||||||
└─────────┘ └─────────┘ └─────────┘
|
|
||||||
|
|
||||||
Services on k3s cluster:
|
```
|
||||||
┌─────────────────────────────────────┐
|
┌──────────────┐
|
||||||
│ Traefik (Ingress) ← :80/:443 │
|
│ Internet │
|
||||||
│ ArgoCD ← :8080 │
|
└──────┬───────┘
|
||||||
│ Grafana ← :3001 │
|
│
|
||||||
│ PostgreSQL (CNPG) ← :5432 │
|
┌────────┴────────┐
|
||||||
│ Valkey ← :6379 │
|
│ Cloudflare DNS │
|
||||||
│ Longhorn UI ← :8000 │
|
│ coreworlds.io │
|
||||||
└─────────────────────────────────────┘
|
│ → public IP │
|
||||||
|
└────────┬────────┘
|
||||||
|
│
|
||||||
|
┌──────┴───────┐
|
||||||
|
│ UCG │
|
||||||
|
│ WAN :443 │
|
||||||
|
└──────┬───────┘
|
||||||
|
│ port-forward
|
||||||
|
┌──────┴───────┐
|
||||||
|
│ catherby │
|
||||||
|
│ 192.168.1.50 │
|
||||||
|
│ Traefik │
|
||||||
|
└──────┬───────┘
|
||||||
|
│
|
||||||
|
┌─────────────┼─────────────┐
|
||||||
|
│ │ │
|
||||||
|
coreworlds.io api.coreworlds.io ...
|
||||||
|
(web app) (api server)
|
||||||
|
```
|
||||||
|
|
||||||
|
## LAN Traffic Flow (Split-Horizon DNS)
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────┐
|
||||||
|
│ LAN Client │
|
||||||
|
└──────┬───────┘
|
||||||
|
│ DNS query: argocd.coreworlds.io
|
||||||
|
┌──────┴───────┐
|
||||||
|
│ UCG DNS │
|
||||||
|
│ *.coreworlds │
|
||||||
|
│ → 192.168.1 │
|
||||||
|
│ .50 │
|
||||||
|
└──────┬───────┘
|
||||||
|
│ direct (no hairpin NAT)
|
||||||
|
┌──────┴───────┐
|
||||||
|
│ catherby │
|
||||||
|
│ 192.168.1.50 │
|
||||||
|
│ Traefik │
|
||||||
|
└──────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Routing
|
||||||
|
|
||||||
|
```
|
||||||
|
Traefik (192.168.1.50:443)
|
||||||
|
│
|
||||||
|
├── coreworlds.io → web (public)
|
||||||
|
├── api.coreworlds.io → api (public)
|
||||||
|
├── preview.coreworlds.io → web (public, preview ns)
|
||||||
|
├── api-preview.coreworlds.io → api (public, preview ns)
|
||||||
|
├── argocd.coreworlds.io → argocd (LAN only — internal-only middleware)
|
||||||
|
├── grafana.coreworlds.io → grafana (LAN only — internal-only middleware)
|
||||||
|
└── longhorn.coreworlds.io → longhorn (LAN only — internal-only middleware)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ kubectl create secret generic "$SECRET_NAME" \
|
|||||||
| kubeseal \
|
| kubeseal \
|
||||||
--format yaml \
|
--format yaml \
|
||||||
--controller-namespace kube-system \
|
--controller-namespace kube-system \
|
||||||
--controller-name sealed-secrets \
|
--controller-name sealed-secrets-helm \
|
||||||
> "${SECRET_NAME}-sealed.yaml"
|
> "${SECRET_NAME}-sealed.yaml"
|
||||||
|
|
||||||
echo "Sealed secret written to ${SECRET_NAME}-sealed.yaml"
|
echo "Sealed secret written to ${SECRET_NAME}-sealed.yaml"
|
||||||
|
|||||||
63
scripts/ucg-dns-setup.sh
Executable file
63
scripts/ucg-dns-setup.sh
Executable file
@@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
UCG_HOST="${UCG_HOST:-192.168.1.1}"
|
||||||
|
BASE_URL="https://${UCG_HOST}"
|
||||||
|
|
||||||
|
TARGET_IP="${1:-192.168.1.50}"
|
||||||
|
DOMAIN="${2:-coreworlds.io}"
|
||||||
|
|
||||||
|
RECORDS=(
|
||||||
|
"$DOMAIN"
|
||||||
|
"*.$DOMAIN"
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- Auth ---
|
||||||
|
|
||||||
|
if [[ -z "${UCG_API_KEY:-}" ]]; then
|
||||||
|
echo "Error: UCG_API_KEY is not set"
|
||||||
|
echo "Create an API key in UniFi OS → Settings → API Keys"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
AUTH_HEADER="X-API-Key: ${UCG_API_KEY}"
|
||||||
|
|
||||||
|
# --- Fetch existing records ---
|
||||||
|
|
||||||
|
echo "Fetching existing static DNS entries..."
|
||||||
|
EXISTING=$(curl -sk -X GET "${BASE_URL}/proxy/network/v2/api/site/default/static-dns" \
|
||||||
|
-H "$AUTH_HEADER")
|
||||||
|
|
||||||
|
# --- Create records ---
|
||||||
|
|
||||||
|
for RECORD in "${RECORDS[@]}"; do
|
||||||
|
# Skip if record already exists
|
||||||
|
if echo "$EXISTING" | grep -q "\"key\":\"${RECORD}\""; then
|
||||||
|
echo " [skip] ${RECORD} → ${TARGET_IP} (already exists)"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo " [create] ${RECORD} → ${TARGET_IP}"
|
||||||
|
HTTP_CODE=$(curl -sk -X POST "${BASE_URL}/proxy/network/v2/api/site/default/static-dns" \
|
||||||
|
-H "$AUTH_HEADER" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{\"key\":\"${RECORD}\",\"value\":\"${TARGET_IP}\",\"record_type\":\"A\",\"enabled\":true}" \
|
||||||
|
-o /dev/null \
|
||||||
|
-w '%{http_code}')
|
||||||
|
|
||||||
|
if [[ "$HTTP_CODE" == "200" || "$HTTP_CODE" == "201" ]]; then
|
||||||
|
echo " ✓ created"
|
||||||
|
else
|
||||||
|
echo " ✗ failed (HTTP ${HTTP_CODE})"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# --- Verify ---
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Current static DNS entries:"
|
||||||
|
curl -sk -X GET "${BASE_URL}/proxy/network/v2/api/site/default/static-dns" \
|
||||||
|
-H "$AUTH_HEADER" | python3 -m json.tool 2>/dev/null || echo "(could not pretty-print response)"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Done. Test with: dig @${UCG_HOST} ${DOMAIN}"
|
||||||
Reference in New Issue
Block a user