Compare commits

..
24 Commits
Author SHA1 Message Date
willemjan a01ec4b1e8 feat: add route to external firefly service 2026-11-15 14:33:33 +01:00
willemjan e1018464da feat: add route to external beszel service 2026-11-15 14:27:22 +01:00
willemjan 050d030cea feat: route to autotune service on proxmox 2026-11-15 14:06:39 +01:00
willemjan 02f43e8f54 fix(ddns): create records with proxied:false (DNS-only)
Cloudflare's edge 308-redirects git smart-http info/refs requests when the
record is proxied, breaking git/ArgoCD. DNS-only sends traffic straight to
the router -> node -> Traefik, which terminates TLS with a valid LE cert.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-14 22:44:47 +01:00
willemjan e48e67fe7c chore: repoURL gitea.zb-kw.duckdns.org -> gitea.labzand.com in all ArgoCD apps + root-app
Gitea is now served via Traefik on gitea.labzand.com (external-gitea);
the old duckdns host has no route once the router points at the node.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-14 22:33:00 +01:00
willemjan 530af4620c feat: add gitea route 2026-11-14 22:20:12 +01:00
willemjan 8b8784d0f2 feat: add homeassistant to treafik including dns record to reach from outside 2026-11-14 21:43:45 +01:00
willemjan 9bbdf7d5d6 fix: required tls 2026-11-14 21:34:01 +01:00
willemjan e8af901b7b feat: add omada external 2026-11-14 21:29:34 +01:00
willemjan a0be22c67c feat: add sonarqube route 2026-11-14 21:21:22 +01:00
willemjan f261cdde66 fix(external-proxmox): valid ingressroute with https backend + working endpoints
- ingress.yaml had invalid 'https:' rules key (dropped by apiserver -> OutOfSync);
  replaced by IngressRoute on websecure with scheme:https + ServersTransport
  (insecureSkipVerify) since Proxmox :8006 is https with self-signed cert
- EndpointSlice apply fails with kubectl 1.31 vs server 1.36 ('unknown field
  spec'), so keep v1 Endpoints (auto-mirrored to EndpointSlice); fixed spec
- shared namespace+middleware moved to services/external (app 'external')

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-14 21:08:52 +01:00
willemjan b9f5f5a2ae fix: address unqouted 2026-11-14 20:54:54 +01:00
willemjan f2ae7dde3e fix: add service to endpoint slice 2026-11-14 20:50:56 +01:00
willemjan e6b3ac4c4d fix: add endpoint slice 2026-11-14 20:45:56 +01:00
willemjan 69a3ed9ffe feat: moved the namespace and middleware to a spereate app and added proxmox stuff 2026-11-14 20:42:25 +01:00
willemjan 36ed5cf464 feat: traefik route to extenal adguard1 on proxmox lxc 2026-11-14 20:10:35 +01:00
willemjan ef58a7c0ca fix: drop lan-only ipAllowList (klipper-lb SNATs all LB traffic to 10.42.0.1, so Traefik never sees real client IPs)
Internal-only for argocd/auth/adguard.labzand.com is now enforced at DNS level:
cloudflare-ddns only publishes ns.labzand.com; internal names resolve solely via
AdGuard rewrites. Delete the *.labzand.com A record in Cloudflare once.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-14 17:35:35 +01:00
willemjan 43fdc020f4 feat: lan-only + force-ssl for argocd/authentik/adguard labzand.com ingresses
ipAllowList middleware (192.168.0.0/16) on the websecure routers blocks
external access; separate IngressRoute on web 301-redirects http->https.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-14 16:37:02 +01:00
willemjan e857cb989c feat: adguard admin console on adguard.labzand.com (internal-only, labzand wildcard cert)
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-06 20:43:20 +01:00
willemjan 264815b2d2 feat: move argocd/authentik to *.labzand.com with Cloudflare DNS-01 wildcard certs
Internal-only hostnames (argocd.labzand.com, auth.labzand.com) via AdGuard
wildcard rewrite; certs still valid via DNS-01 so no browser warnings.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-06 20:37:30 +01:00
willemjan f585fa0aa9 fix: separate web-entrypoint IngressRoute for http->https redirect
A router with TLS enabled (from the Ingress tls section) never matches on
the plain web entrypoint, so entrypoints web,websecure on the Ingress itself
still 404'd on :80. Keep the Ingress on websecure only and add an
IngressRoute on web with the redirect-https middleware.

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-06 20:20:23 +01:00
willemjan db1adfc229 feat: redirect http->https for ns.labzand.com (web entrypoint + redirect-https middleware)
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <[email protected]>
2026-11-06 20:10:38 +01:00
willemjan 789b9d0a79 fix: token 2026-11-04 21:01:54 +01:00
willemjan a9d8896081 fix: token 2026-11-04 20:59:29 +01:00
69 changed files with 1091 additions and 28 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main targetRevision: main
path: services/adguard path: services/adguard
destination: destination:
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main targetRevision: main
path: services/argocd path: services/argocd
destination: destination:
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main targetRevision: main
path: services/authentik path: services/authentik
destination: destination:
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main targetRevision: main
path: services/cloudfare-ddns path: services/cloudfare-ddns
destination: destination:
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-adguard
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external-adguard
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-autotune
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external/external-autotune
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-beszel
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external/external-beszel
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-firefly
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external/external-firefly
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-gitea
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external-gitea
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-homeassistant
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external-homeassistant
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+2 -2
View File
@@ -6,7 +6,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main targetRevision: main
path: services/external-nightscout path: services/external-nightscout
destination: destination:
@@ -15,4 +15,4 @@ spec:
syncPolicy: syncPolicy:
automated: {prune: true, selfHeal: true} automated: {prune: true, selfHeal: true}
syncOptions: syncOptions:
- CreateNamespace=true - CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-omada
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external-omada
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-proxmox
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external-proxmox
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-sonarqube
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external-sonarqube
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=false
+18
View File
@@ -0,0 +1,18 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external
namespace: argocd
spec:
project: default
source:
repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main
path: services/external
destination:
server: https://kubernetes.default.svc
namespace: external
syncPolicy:
automated: {prune: true, selfHeal: true}
syncOptions:
- CreateNamespace=true
+1 -1
View File
@@ -7,7 +7,7 @@ metadata:
spec: spec:
project: default project: default
source: source:
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git repoURL: https://gitea.labzand.com/willemjan/cluster.git
targetRevision: main targetRevision: main
path: apps # elke yaml hierin = één Application path: apps # elke yaml hierin = één Application
directory: directory:
@@ -6,7 +6,7 @@ metadata:
namespace: cert-manager namespace: cert-manager
spec: spec:
encryptedData: encryptedData:
api-token: AgA+SL4T6mIhlShhHf7wEJhXWGCo2lmtFhNlWJotBlIvaZttsknSaaAzmEwolk+Kk5i8JA6yTSkgi2dux0EVkl3waLgnEFvmcHMSgKbJDiosgVOgIjPOriy5rrgeqZaWLplmkqVEI20NYe/6rW9ByVBf38RAaQsx2msxO7u3dKXC5fJXlDwCosdNKo4eik7OFJrb+X9nBc3gpF3DgBQeWK/QtdC9di3fVpYlRhxC2X0o73rDaqauUvERG1fl78DtuteRiIFpRESstP9cyjgdDRNH5WvSX+Wc+TgUOPk/LmnO0gnfTwhk1GK//2NdO065tQeAkM9aaajOLgyC5rTvo7cK+4FcG92wb1aPU0Vr93V4rj8lgBFOBWmg/64r25rNSNEA/eOpyDw4Vzb3c7PyqRUlMQ1xNoMNXfBzBHlS5wjn5nJm8A9TwDPEKHbYVLzvUkMpaXYUJUOVqBL5czOIcr2UdaOEK6sIFtLVe/dGejT+ZlgM4V9BfQGXJYS1NdWtHX2iXKWhAWU4EyodS5MaQMjggW/VN8CsRvnLZo3m+YLCZmH7FVQisjovhhhon+IFyzzggWtDy3NiKGx1pfVN1x/bvFJ/MkaS5kbxFwvvqh3A1cJSnsAAVV4qJ12MwSawh++QzNG7b/plOgLtDnzTrofjcsgf6iBuGBPI6xYPlWKxp4kPqGjpi/rAqMD/0ZzpQz2fu92gEBBjsKNGYbIf1k+IFy8DoGbu8Y172OLGa1JrLZcgmm8bMuYEiZqQrLb84lqHOg4rkuw= api-token: AgBeOIVgJuFtfm4XMy9NqTCqaJ5Gmckk95koM0g6frGZA/FvU87hVGl9rwL/eZ9lSPAdEBTVXelo0pi5cJfFebhjoJfzse3TcfoJGPo5B41167pyrsVsfSailk3ZPwB6rPWoWMRGtct4SLIK4makh2xTE9ez7rZRxEXi8DGPWf7Bn7IIiV27R4MARR6SWeB9F4svvbJOgAfRjf+7pY95epHaFiNy2BUBkjrT6To98XlhsENNgLTTiS8kj6guT5BoPM+hKzQnHF+fCF6nucyddnnYvfxptjSNLEoDY2b2Iy2OUimb7arZXjmGBhAyH4ZQLsLQbF6OrixlR1Q60XsGcZkXebEC7nBDiaAvs7FFUeBO4gdvWIUeADqRkJLxETL3nodhFPjV6MaDJcH4ZGG4FOHA7ytWJ1n6+RJ0WaxC+JcYi5R6DvqNOFPJsvaKcr8aeG5YdrCLYeXzU95huNkX/AnDgAqcXVJAaWI+LN40B6Oq5z2lyz/oO1edOk170G52Qm7D+NwYq5/Dzm6oCuct2jieu/oI07784Ja1r9bMobIJr7cTBe2mHoEDvencFrc/vLViRXj/B6lfxQOcrkaKa+Bu4hOGlmBkLEqAlhyxVfSXk3EO6iqveahcdMmhngtrxmcjJW2WZQUNMBAGxo8kGGas8UFjzfdLD4zAqSl4Tmz6zcy3xO1z0FHfDRYplmAmFU+ji2C5qQVIczZOzAIuO6lN0JXUpo8Bk+jAZiM5Ic8RYQud30j+gQZMhFQfyRy99qdbOC6Ihr0=
template: template:
metadata: metadata:
name: cloudflare-api-token name: cloudflare-api-token
+6 -3
View File
@@ -85,9 +85,12 @@ kind: Ingress
metadata: metadata:
name: adguard name: adguard
namespace: adguard namespace: adguard
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
rules: rules:
- host: adguard-cluster.zb-kw.duckdns.org - host: adguard.labzand.com
http: http:
paths: paths:
- path: / - path: /
@@ -95,5 +98,5 @@ spec:
backend: backend:
service: {name: adguard-service, port: {number: 80}} service: {name: adguard-service, port: {number: 80}}
tls: tls:
- hosts: [adguard-cluster.zb-kw.duckdns.org] - hosts: [adguard.labzand.com]
secretName: zb-kw-wildcard-tls secretName: labzand-wildcard-tls
+8 -4
View File
@@ -1,10 +1,14 @@
# services/<naam>/cert.yaml # services/<naam>/cert.yaml
# Wildcard-certificaat voor *.labzand.com via Cloudflare DNS-01.
# Vervangt de oude duckdns-cert (zb-kw-wildcard-tls).
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: zb-kw-wildcard name: labzand-wildcard
namespace: adguard namespace: adguard
spec: spec:
secretName: zb-kw-wildcard-tls secretName: labzand-wildcard-tls
dnsNames: ["adguard-cluster.zb-kw.duckdns.org"] dnsNames: ["*.labzand.com"]
issuerRef: {name: duckdns, kind: ClusterIssuer} issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,19 @@
# HTTP (entrypoint web) -> HTTPS redirect voor adguard.labzand.com.
# services: api@internal is een dummy - de redirect middleware stuurt
# nooit door naar een backend.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: adguard-redirect
namespace: adguard
spec:
entryPoints:
- web
routes:
- match: Host(`adguard.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+11
View File
@@ -0,0 +1,11 @@
# Middleware voor adguard.labzand.com: http (web) -> https redirect.
# (lan-only verwijderd: klipper-lb SNAT't al verkeer naar 10.42.0.1, zie argocd/middleware.yaml)
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-https
namespace: adguard
spec:
redirectScheme:
scheme: https
permanent: true
+13
View File
@@ -0,0 +1,13 @@
# Wildcard-certificaat voor *.labzand.com via Cloudflare DNS-01.
# DNS-01 werkt ook voor hostnames die niet publiek bereikbaar zijn.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: labzand-wildcard
namespace: argocd
spec:
secretName: labzand-wildcard-tls
dnsNames: ["*.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
+7 -3
View File
@@ -3,9 +3,13 @@ kind: Ingress
metadata: metadata:
name: argocd name: argocd
namespace: argocd namespace: argocd
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec: spec:
ingressClassName: traefik
rules: rules:
- host: argocd.zb-kw.duckdns.org - host: argocd.labzand.com
http: http:
paths: paths:
- path: / - path: /
@@ -16,5 +20,5 @@ spec:
port: port:
number: 80 # poort 80 van de svc = HTTP-backend number: 80 # poort 80 van de svc = HTTP-backend
tls: tls:
- hosts: [argocd.zb-kw.duckdns.org] - hosts: [argocd.labzand.com]
secretName: zb-kw-wildcard-tls secretName: labzand-wildcard-tls
@@ -0,0 +1,19 @@
# HTTP (entrypoint web) -> HTTPS redirect voor argocd.labzand.com.
# services: api@internal is een dummy - de redirect middleware stuurt
# nooit door naar een backend.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: argocd-redirect
namespace: argocd
spec:
entryPoints:
- web
routes:
- match: Host(`argocd.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+13
View File
@@ -0,0 +1,13 @@
# Middleware voor argocd.labzand.com: http (web) -> https redirect.
# (lan-only ipAllowList verwijderd: k3s klipper-lb SNAT't al LB-verkeer naar
# 10.42.0.1, waardoor Traefik nooit het echte client-IP ziet. Internal-only
# wordt afgedwongen via DNS: geen publiek A-record voor interne namen.)
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-https
namespace: argocd
spec:
redirectScheme:
scheme: https
permanent: true
+8 -4
View File
@@ -1,9 +1,13 @@
# Wildcard-certificaat voor *.labzand.com via Cloudflare DNS-01.
# Vervangt de oude duckdns-cert (zb-kw-wildcard-tls).
apiVersion: cert-manager.io/v1 apiVersion: cert-manager.io/v1
kind: Certificate kind: Certificate
metadata: metadata:
name: zb-kw-wildcard name: labzand-wildcard
namespace: authentik namespace: authentik
spec: spec:
secretName: zb-kw-wildcard-tls secretName: labzand-wildcard-tls
dnsNames: ["auth.zb-kw.duckdns.org"] dnsNames: ["*.labzand.com"]
issuerRef: {name: duckdns, kind: ClusterIssuer} issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
+3 -3
View File
@@ -9,7 +9,7 @@ metadata:
spec: spec:
ingressClassName: traefik ingressClassName: traefik
rules: rules:
- host: auth.zb-kw.duckdns.org - host: auth.labzand.com
http: http:
paths: paths:
- path: / - path: /
@@ -21,5 +21,5 @@ spec:
number: 9000 number: 9000
tls: tls:
- hosts: - hosts:
- auth.zb-kw.duckdns.org - auth.labzand.com
secretName: zb-kw-wildcard-tls secretName: labzand-wildcard-tls
+27
View File
@@ -0,0 +1,27 @@
# HTTP (entrypoint web) -> HTTPS redirect voor auth.labzand.com.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-https
namespace: authentik
spec:
redirectScheme:
scheme: https
permanent: true
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: auth-redirect
namespace: authentik
spec:
entryPoints:
- web
routes:
- match: Host(`auth.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+5 -2
View File
@@ -6,5 +6,8 @@ metadata:
data: data:
# Comma-separated list of domains to update # Comma-separated list of domains to update
# Format: subdomain.domain.tld,subdomain2.domain.tld # Format: subdomain.domain.tld,subdomain2.domain.tld
DOMAINS: "*.labzand.com" # Alleen namen die écht publiek bereikbaar moeten zijn (via router -> cluster).
ZONE_ID: "6093605ad5a8db13e9c9d9faad240ca6" # Interne-only namen (argocd/auth/adguard.labzand.com) bewust NIET hier:
# die krijgen geen publiek A-record en resolven alleen intern via AdGuard.
DOMAINS: "ns.labzand.com, ha.labzand.com, gitea.labzand.com"
ZONE_ID: "6093605ad5a8db13e9c9d9faad240ca6"
@@ -84,7 +84,7 @@ data:
CREATE_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \ CREATE_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $API_TOKEN" \ -H "Authorization: Bearer $API_TOKEN" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$PUBLIC_IP\",\"ttl\":120,\"proxied\":true}") --data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$PUBLIC_IP\",\"ttl\":120,\"proxied\":false}")
CREATE_SUCCESS=$(echo "$CREATE_RESPONSE" | grep -o '"success":[^,]*' | cut -d':' -f2) CREATE_SUCCESS=$(echo "$CREATE_RESPONSE" | grep -o '"success":[^,]*' | cut -d':' -f2)
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-adguard-labzand
namespace: external
spec:
secretName: external-adguard-labzand-tls
dnsNames: ["adguard1.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
+25
View File
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-adguard
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: adguard1.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: adguard-external
port:
number: 80
tls:
- hosts:
- adguard1.labzand.com
secretName: external-adguard-labzand-tls
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-adguard-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`adguard1.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+27
View File
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: adguard-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: adguard-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.53
ports:
- name: http
port: 80
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: gitea-labzand
namespace: external
spec:
secretName: gitea-labzand-tls
dnsNames: ["gitea.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
+25
View File
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: gitea
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: gitea.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: gitea-external
port:
number: 3000
tls:
- hosts:
- gitea.labzand.com
secretName: gitea-labzand-tls
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: gitea-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`gitea.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+25
View File
@@ -0,0 +1,25 @@
apiVersion: v1
kind: Service
metadata:
name: gitea-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 3000
targetPort: 3000
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: gitea-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.52
ports:
- name: http
port: 3000
protocol: TCP
+14
View File
@@ -0,0 +1,14 @@
# Certificaat voor ns.labzand.com via Cloudflare DNS-01.
# Vereist: ClusterIssuer 'cloudflare-dns' (infrastructure/cert-manager/cloudflare-issuer.yaml)
# en een secret 'cloudflare-api-token' in namespace cert-manager.
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: ha-labzand
namespace: external
spec:
secretName: ha-labzand-tls
dnsNames: ["ha.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: homeassistant
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: ha.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ha-external
port:
number: 8123
tls:
- hosts:
- ha.labzand.com
secretName: ha-labzand-tls
@@ -0,0 +1,21 @@
# HTTP (entrypoint web) -> HTTPS redirect voor ns.labzand.com.
# De Ingress zelf heeft een tls-sectie, waardoor Traefik die router alleen
# op websecure matcht; daarom hier een aparte router op web.
# services: api@internal is een dummy - de redirect middleware stuurt
# nooit door naar een backend.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ha-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`ha.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: ha-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 8123
targetPort: 8123
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: ha-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.146
ports:
- name: http
port: 8123
protocol: TCP
@@ -0,0 +1,21 @@
# HTTP (entrypoint web) -> HTTPS redirect voor ns.labzand.com.
# De Ingress zelf heeft een tls-sectie, waardoor Traefik die router alleen
# op websecure matcht; daarom hier een aparte router op web.
# services: api@internal is een dummy - de redirect middleware stuurt
# nooit door naar een backend.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: ns-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`ns.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-omada-labzand
namespace: external
spec:
secretName: external-omada-labzand-tls
dnsNames: ["omada.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-omada-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`omada.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+29
View File
@@ -0,0 +1,29 @@
# omada (:8043) spricht HTTPS met een self-signed cert — daarom een
# IngressRoute (i.p.v. een plain Ingress, die altijd HTTP naar de backend praat)
# met scheme: https en een ServersTransport die het cert niet checkt.
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
name: omada-insecure
namespace: external
spec:
insecureSkipVerify: true
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-omada
namespace: external
spec:
entryPoints:
- websecure
tls:
secretName: external-omada-labzand-tls
routes:
- match: Host(`omada.labzand.com`)
kind: Rule
services:
- name: omada-external
port: 8043
scheme: https
serversTransport: omada-insecure
+27
View File
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: omada-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 8043
targetPort: 8043
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: omada-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.62
ports:
- name: http
port: 8043
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-proxmox-labzand
namespace: external
spec:
secretName: external-proxmox-labzand-tls
dnsNames: ["proxmox.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-proxmox-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`proxmox.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
@@ -0,0 +1,29 @@
# Proxmox (:8006) spricht HTTPS met een self-signed cert — daarom een
# IngressRoute (i.p.v. een plain Ingress, die altijd HTTP naar de backend praat)
# met scheme: https en een ServersTransport die het cert niet checkt.
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
name: proxmox-insecure
namespace: external
spec:
insecureSkipVerify: true
---
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-proxmox
namespace: external
spec:
entryPoints:
- websecure
tls:
secretName: external-proxmox-labzand-tls
routes:
- match: Host(`proxmox.labzand.com`)
kind: Rule
services:
- name: proxmox-external
port: 8006
scheme: https
serversTransport: proxmox-insecure
+33
View File
@@ -0,0 +1,33 @@
# Service zonder selector: Kubernetes maakt zelf geen endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (Proxmox, buiten het cluster).
# De endpoints-controller mirrored dit automatisch naar een EndpointSlice.
# (Een handmatige discovery.k8s.io/v1 EndpointSlice faalt op deze cluster met
# kubectl 1.31 tegen server 1.36: "unknown field spec" — daher v1 Endpoints.)
# Let op: ArgoCD trackt Endpoints/EndpointSlice niet — apply deze file handmatig
# als het endpoint ontbreekt:
# kubectl apply -f services/external-proxmox/service.yaml
apiVersion: v1
kind: Service
metadata:
name: proxmox-external
namespace: external
spec:
type: ClusterIP
ports:
- name: https
port: 8006
targetPort: 8006
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: proxmox-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.64
ports:
- name: https
port: 8006
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-sonarqube-labzand
namespace: external
spec:
secretName: external-sonarqube-labzand-tls
dnsNames: ["sonarqube.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
+25
View File
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-sonarqube
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: sonarqube.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: sonarqube-external
port:
number: 9000
tls:
- hosts:
- sonarqube.labzand.com
secretName: external-sonarqube-labzand-tls
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-sonarqube-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`sonarqube.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+27
View File
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: sonarqube-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 9000
targetPort: 9000
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: sonarqube-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.49
ports:
- name: http
port: 9000
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-autotune-labzand
namespace: external
spec:
secretName: external-autotune-labzand-tls
dnsNames: ["autotune.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-autotune-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`autotune.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+25
View File
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-autotune
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: autotune.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: autotune-external
port:
number: 8502
tls:
- hosts:
- autotune.labzand.com
secretName: external-autotune-labzand-tls
+27
View File
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: autotune-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 8502
targetPort: 8502
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: autotune-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.51
ports:
- name: http
port: 8502
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-beszel-labzand
namespace: external
spec:
secretName: external-beszel-labzand-tls
dnsNames: ["beszel.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-beszel-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`beszel.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+25
View File
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-beszel
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: beszel.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: beszel-external
port:
number: 8090
tls:
- hosts:
- beszel.labzand.com
secretName: external-beszel-labzand-tls
+27
View File
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: beszel-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 8090
targetPort: 8090
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: beszel-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.61
ports:
- name: http
port: 8090
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: external-firefly-labzand
namespace: external
spec:
secretName: external-firefly-labzand-tls
dnsNames: ["firefly.labzand.com"]
issuerRef:
name: cloudflare-dns
kind: ClusterIssuer
@@ -0,0 +1,16 @@
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: external-firefly-redirect
namespace: external
spec:
entryPoints:
- web
routes:
- match: Host(`firefly.labzand.com`)
kind: Rule
middlewares:
- name: redirect-https
services:
- name: api@internal
kind: TraefikService
+25
View File
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: external-firefly
namespace: external
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
spec:
ingressClassName: traefik
rules:
- host: firefly.labzand.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: firefly-external
port:
number: 80
tls:
- hosts:
- firefly.labzand.com
secretName: external-firefly-labzand-tls
+27
View File
@@ -0,0 +1,27 @@
# Service zonder selector: Kubernetes maakt zelf geen Endpoints aan.
# Het Endpoints-object hieronder levert het externe adres (buiten het cluster).
apiVersion: v1
kind: Service
metadata:
name: firefly-external
namespace: external
spec:
type: ClusterIP
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
---
apiVersion: v1
kind: Endpoints
metadata:
name: firefly-external
namespace: external
subsets:
- addresses:
- ip: 192.168.2.59
ports:
- name: http
port: 80
protocol: TCP
+11
View File
@@ -0,0 +1,11 @@
# Redirect plain HTTP (entrypoint web) naar HTTPS.
# Op websecure is het scheme al https, dus daar doet deze middleware niets.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: redirect-https
namespace: external
spec:
redirectScheme:
scheme: https
permanent: true