gateway-routing
Gateway Routing
The homelab uses Kubernetes Gateway API with Istio as the gateway controller. Two gateways handle traffic:
- internal — accessible only within the home network
- external — accessible from the internet, protected by Coraza WAF
All gateway resources live in the istio-gateway namespace. HTTPRoutes in any namespace reference them via parentRefs.
See references/reference.md for gateway selection table, ClusterIssuer comparison, and WAF metrics.
Gateway Selection
Internal for public internet access -> external gateway; internal-only -> internal gateway; both -> create two HTTPRoutes (examples: Authelia, Immich, Kromgo).
Creating an HTTPRoute
Choose gateway and hostname -> create YAML -> place in correct directory -> set network policy profile.
Internal-only route (most common for platform services):
---
# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/gateway.networking.k8s.io/httproute_v1.json
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app
spec:
parentRefs:
- name: internal
namespace: istio-gateway
hostnames:
- "my-app.${internal_domain}"
rules:
- backendRefs:
- name: my-app-service
port: 8080
External route (internet-facing, WAF-protected) — same structure with name: external and ${external_domain} hostname.
File placement: platform services go in kubernetes/platform/config/<subsystem>/; cluster-specific apps go in kubernetes/clusters/<cluster>/config/<app>/. Add to the subsystem's kustomization.yaml.
Network policy: set network-policy.homelab/profile on the namespace in kubernetes/platform/namespaces.yaml. See references/reference.md for profile-by-gateway mapping.
parentRefs Details
Route Patterns
Simple backend (most common — Grafana, Longhorn, Hubble, Alertmanager, Prometheus, Garage, Kromgo):
rules:
- backendRefs:
- name: service-name
port: 80
Dual gateway: create two separate HTTPRoute resources, one per gateway, differing only in parentRefs.name and hostnames domain.
HTTP-to-HTTPS redirect: already platform-managed in config/gateway/http-to-https-redirect.yaml — do not create redirect routes for new services.
TLS Certificates
Wildcard certs are provisioned at the gateway level. Adding a new subdomain requires only creating the HTTPRoute — no cert changes needed.
Run scripts/validate-tls.sh [external|internal] to check certificate and issuer status.
Coraza WAF (External Gateway Only)
The WAF runs as an Istio WasmPlugin on the external gateway with OWASP CRS at Paranoia Level 1. Key behaviors:
- FAIL_OPEN: if the WASM binary fails to load, traffic flows unfiltered (check gateway pod logs for
applying allow RBAC filter) - Rules are inlined in
coraza-wasm-plugin.yaml(WasmPlugin does not support volume mounts) - To disable a rule causing false positives: add
- SecRuleRemoveById <ID>to thedirectives_map.defaultarray
Testing WAF endpoints — Istio matches on SNI, so raw IP requests are rejected. Use --resolve:
GATEWAY_IP=$(kubectl --context <cluster> get gateway external -n istio-gateway -o jsonpath='{.metadata.annotations.lbipam\.cilium\.io/ips}')
curl -kI --resolve "app.${external_domain}:443:${GATEWAY_IP}" "https://app.${external_domain}/"
Attack pattern verification (expect 403): pass ?id=1'%20OR%20'1'='1 (SQLi), ?q=<script>alert(1)</script> (XSS), or ?cmd=;cat%20/etc/passwd (RCE) with the same --resolve pattern.
Common Issues
Cross-References
| Document | Focus |
|---|---|
kubernetes/platform/config/gateway/ |
Gateway definitions, WAF config |
kubernetes/platform/config/issuers/ |
ClusterIssuer definitions |
kubernetes/platform/config/certs/ |
Certificate resources |
| references/reference.md | Gateway table, issuer comparison, WAF metrics |
deploy-app skill |
Full app deployment workflow including routing |
More from ionfury/homelab
prometheus
Query Prometheus API for cluster metrics, alerts, and observability data. Use when investigating cluster health, performance issues, resource utilization, or alert status. Triggers on questions like "what's the CPU usage", "show me firing alerts", "check memory pressure", "query prometheus for", or any PromQL-related requests.
66taskfiles
|
63opentofu-modules
|
59terragrunt
|
59k8s
|
46cnpg-database
|
37