Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bfa957f29 |
Binary file not shown.
@@ -1,10 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""netbird-service-sync: reconcile NetBird reverse-proxy services from Ingresses.
|
||||
|
||||
Source of truth: every Ingress carrying one of the public labels.
|
||||
dns.renner.uno/public also takes the host out of the LAN DNS (external-dns-unifi
|
||||
skips it); netbird.renner.uno/public publishes on the proxy only and leaves the
|
||||
LAN record in place.
|
||||
Source of truth: every Ingress labeled netbird.renner.uno/public=true. DNS is
|
||||
independent of it: dns.renner.uno/internal (UDM) and dns.renner.uno/public
|
||||
(Cloudflare) are read by the two external-dns instances.
|
||||
For each host on such an Ingress the NetBird management gets one reverse-proxy
|
||||
service in TLS-passthrough mode on :443, targeting Traefik's ClusterIP through a
|
||||
subnet resource that covers the cluster's service CIDR. SNI and Host reach
|
||||
@@ -45,7 +44,7 @@ NETWORK_NAME = os.environ.get("NETWORK_NAME", "k8s public ingress")
|
||||
ROUTER_GROUP = os.environ.get("ROUTER_GROUP_NAME", "k8s-ingress-router")
|
||||
SOURCE_GROUP = os.environ.get("SOURCE_GROUP_NAME", "All")
|
||||
TRAEFIK_NS, TRAEFIK_SVC = os.environ.get("TRAEFIK_SERVICE", "ingress/traefik").split("/", 1)
|
||||
PUBLIC_LABELS = os.environ.get("PUBLIC_LABELS", "dns.renner.uno/public,netbird.renner.uno/public").split(",")
|
||||
PUBLIC_LABELS = os.environ.get("PUBLIC_LABELS", "netbird.renner.uno/public").split(",")
|
||||
LISTEN_PORT = int(os.environ.get("LISTEN_PORT", "443"))
|
||||
INTERVAL = int(os.environ.get("INTERVAL_SECONDS", "60"))
|
||||
HTTP_TIMEOUT = 20
|
||||
|
||||
@@ -43,16 +43,16 @@ spec:
|
||||
name: cloudflare-api-token
|
||||
key: api-token
|
||||
extraArgs:
|
||||
- --cloudflare-proxied
|
||||
- --cloudflare-dns-records-per-page=5000
|
||||
- --default-targets=d2386ccd-a665-41e7-8631-603fdafcb006.cfargotunnel.com
|
||||
# Every public host is a DNS-only CNAME to the proxy load balancer (kubernetes/apps/cloudflare-lb-sync).
|
||||
- --default-targets=proxy.renner.uno
|
||||
- --force-default-targets
|
||||
domainFilters:
|
||||
- renner.uno
|
||||
sources:
|
||||
- ingress
|
||||
txtOwnerId: k8s-homelab
|
||||
policy: upsert-only
|
||||
policy: sync
|
||||
# Filter by label, not annotation. external-dns translates annotations
|
||||
# in its prefix namespace into ProviderSpecific properties on desired
|
||||
# endpoints; the UniFi webhook does not implement AdjustEndpoints, so
|
||||
@@ -60,4 +60,4 @@ spec:
|
||||
# records and cause every reconcile to delete-and-recreate the same
|
||||
# values. Labels are not translated, so they are safe to use as a
|
||||
# selector without leaking provider-specific state to the UniFi side.
|
||||
labelFilter: external-dns/cloudflare=true
|
||||
labelFilter: dns.renner.uno/public=true
|
||||
|
||||
@@ -8,6 +8,7 @@ metadata:
|
||||
# Published on the NetBird proxy; LAN DNS stays on the Traefik VIP.
|
||||
netbird.renner.uno/public: "true"
|
||||
dns.renner.uno/internal: "true"
|
||||
dns.renner.uno/public: "true"
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-cluster
|
||||
spec:
|
||||
|
||||
@@ -9,6 +9,7 @@ metadata:
|
||||
# SSH (gitea-ssh) and node image pulls stay local.
|
||||
netbird.renner.uno/public: "true"
|
||||
dns.renner.uno/internal: "true"
|
||||
dns.renner.uno/public: "true"
|
||||
annotations:
|
||||
cert-manager.io/cluster-issuer: letsencrypt-cluster
|
||||
# Long-running git fetch/push and container-registry blob uploads:
|
||||
|
||||
@@ -28,9 +28,8 @@ spec:
|
||||
hosts:
|
||||
- immich.renner.uno
|
||||
---
|
||||
# photos.renner.uno is LAN-registered (no proxy tunnel), so it lives on its
|
||||
# own unlabeled Ingress: the dns.renner.uno/public label-filter is
|
||||
# per-resource, and this name must keep its UDM record. It was the LXC alias
|
||||
# photos.renner.uno is LAN-only (UDM record, no proxy), so it lives on its
|
||||
# own Ingress: DNS label filters are per-resource. It was the LXC alias
|
||||
# served by Caddy; preserved so external-dns-unifi can take over once the
|
||||
# tofu CNAME on lxc_225 is removed.
|
||||
apiVersion: networking.k8s.io/v1
|
||||
|
||||
@@ -51,9 +51,6 @@ metadata:
|
||||
name: wordpress-admin
|
||||
namespace: wordpress
|
||||
labels:
|
||||
# external-dns-unifi runs with --label-filter=dns.renner.uno/public!=true,
|
||||
# so an unlabelled Ingress on this host would gain a UDM A-record pointing
|
||||
# LAN clients at the Traefik VIP.
|
||||
dns.renner.uno/public: "true"
|
||||
netbird.renner.uno/public: "true"
|
||||
annotations:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# Reconciles NetBird reverse-proxy services from Ingresses that carry
|
||||
# dns.renner.uno/public or netbird.renner.uno/public (proxy only, LAN DNS
|
||||
# untouched): one TLS-passthrough service per host on :443,
|
||||
# netbird.renner.uno/public: one TLS-passthrough service per host on :443,
|
||||
# targeting Traefik's ClusterIP through a subnet resource over the service
|
||||
# CIDR (ci/images/netbird-service-sync/controller.py).
|
||||
#
|
||||
|
||||
@@ -82,25 +82,12 @@ spec:
|
||||
# once via the UDM UI instead.
|
||||
domainFilters:
|
||||
- renner.uno
|
||||
# The label controls where a domain is registered: resources labeled
|
||||
# dns.renner.uno/public=true are publicly-served (Cloudflare wildcard ->
|
||||
# NetBird proxy) and must NOT get a LAN-only A/AAAA on the UDM — a phone
|
||||
# that caches 10.2.99.86 / fd99::86 on wifi and then roams to cellular
|
||||
# blackholes on it (RFC1918/ULA gives no RST and no ICMP, so the app
|
||||
# hangs until TCP timeout). This instance therefore skips labeled
|
||||
# resources; LAN clients follow the public answer and the UDM hairpins
|
||||
# the proxy addresses back to the cluster (opentofu/unifi_nat_hairpin.tf).
|
||||
#
|
||||
# The filter is per-RESOURCE: every Ingress/IngressRoute/Service that
|
||||
# carries a public host must be labeled, and a public host must not share
|
||||
# a resource with a LAN-registered host (split it, see immich-photos).
|
||||
#
|
||||
# Unlike a domain filter, the label filter applies only to the SOURCE
|
||||
# side: records already on the UDM stay visible through the TXT registry,
|
||||
# so labeling a resource drops its names from desired state and
|
||||
# policy: sync deletes the now-stale records automatically. No manual
|
||||
# cleanup step exists in this design.
|
||||
labelFilter: dns.renner.uno/public!=true
|
||||
# Opt-in: only resources labeled dns.renner.uno/internal=true get a UDM
|
||||
# record. Public hosts without it resolve on-LAN via the public answer and
|
||||
# the UDM hairpin (opentofu/unifi_nat_hairpin.tf). The filter is
|
||||
# per-resource; policy: sync deletes the records of resources that lose
|
||||
# the label.
|
||||
labelFilter: dns.renner.uno/internal=true
|
||||
sources:
|
||||
- ingress
|
||||
- service
|
||||
|
||||
Reference in New Issue
Block a user