Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6008d59c9f | ||
|
|
5aa6c0609d | ||
|
|
0ebe113abb | ||
|
|
1723f73b5d | ||
|
|
8d8df3b635 | ||
|
|
29c91769a7 | ||
|
|
2c47c68a8b | ||
|
|
ceff817d88 |
@@ -6,7 +6,9 @@ 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
|
||||
Traefik untouched, the proxy terminates nothing, and no domain resource is
|
||||
involved -- the routing peers stay ordinary IP routers.
|
||||
involved -- the routing peers stay ordinary IP routers. The target sends a
|
||||
PROXY protocol v2 header so Traefik (and CrowdSec behind its access log) sees
|
||||
the WAN client address instead of the routing peer's pod IP.
|
||||
|
||||
Ownership is derived from NetBird itself, not from local state: a service is
|
||||
managed iff its mode is "tls" and its target is this controller's subnet
|
||||
@@ -194,9 +196,12 @@ def ensure_policy(nb, resource, source_group):
|
||||
|
||||
|
||||
def service_body(host, resource, target_ip):
|
||||
# proxy_protocol: PROXY v2 header carries the WAN client address to
|
||||
# Traefik (proxyProtocol.trustedIPs on websecure); TCP/TLS modes only.
|
||||
return {"name": host, "domain": host, "mode": "tls", "listen_port": LISTEN_PORT, "enabled": True,
|
||||
"targets": [{"target_type": "subnet", "target_id": resource, "protocol": "tcp",
|
||||
"host": target_ip, "port": 443, "enabled": True}]}
|
||||
"host": target_ip, "port": 443, "enabled": True,
|
||||
"options": {"proxy_protocol": True}}]}
|
||||
|
||||
|
||||
def is_managed(svc, resource):
|
||||
@@ -208,7 +213,8 @@ def target_matches(svc, target_ip):
|
||||
return False
|
||||
ts = svc.get("targets") or []
|
||||
return len(ts) == 1 and ts[0].get("host") == target_ip and ts[0].get("port") == 443 \
|
||||
and ts[0].get("protocol") == "tcp" and ts[0].get("enabled")
|
||||
and ts[0].get("protocol") == "tcp" and ts[0].get("enabled") \
|
||||
and (ts[0].get("options") or {}).get("proxy_protocol") is True
|
||||
|
||||
|
||||
def reconcile():
|
||||
|
||||
@@ -21,6 +21,9 @@ metadata:
|
||||
namespace: audiobookshelf
|
||||
labels:
|
||||
app.kubernetes.io/name: audiobookshelf
|
||||
annotations:
|
||||
# envFrom does not restart the pod when the ConfigMap changes; Reloader does.
|
||||
configmap.reloader.stakater.com/reload: audiobookshelf-config
|
||||
spec:
|
||||
replicas: 1
|
||||
strategy:
|
||||
|
||||
@@ -35,6 +35,9 @@ metadata:
|
||||
namespace: immich
|
||||
labels:
|
||||
app.kubernetes.io/name: immich-server
|
||||
annotations:
|
||||
# envFrom does not restart the pod when the ConfigMap changes; Reloader does.
|
||||
configmap.reloader.stakater.com/reload: immich-config
|
||||
spec:
|
||||
# Scaled to 0 alongside immich-machine-learning during single-node
|
||||
# maintenance; see the note there. The CNPG Postgres cluster stays running,
|
||||
|
||||
@@ -76,7 +76,11 @@ spec:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: controller
|
||||
image: gitea.renner.uno/gitea_admin/netbird-proxy-services:2026-09-07
|
||||
# Pinned by digest: the date tag is rebuilt on every push of the
|
||||
# image directory (branch and master alike) and the registry keeps
|
||||
# only the newest manifest per tag, so the digest must come from
|
||||
# the MASTER build of the code change.
|
||||
image: gitea.renner.uno/gitea_admin/netbird-proxy-services:2026-09-07@sha256:caffa308d802c6fcc6aea919ac94657c08b993651baa6b8d18de395bcc40523e
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
|
||||
@@ -93,13 +93,17 @@ spec:
|
||||
# Real client-IP visibility. The netbird-ingress routing peer
|
||||
# re-originates every mesh + WAN-via-proxy connection from its own
|
||||
# pod IP (rootless userspace WireGuard), so Traefik's TCP peer for
|
||||
# that traffic is always a pod IP (e.g. fd10:244::2de1) — collapsing
|
||||
# all external clients to one source. The NetBird reverse-proxy
|
||||
# (HTTP mode, on the VPS) sets X-Forwarded-For with the real WAN
|
||||
# client IP; trust the pod CIDRs so Traefik reads it instead. Without
|
||||
# this, a CrowdSec bouncer bans the shared pod IP and 403s everyone
|
||||
# (the 2026-06-27 IPv6 outage). Harmless no-op when no XFF is present
|
||||
# (direct LAN/mesh) — those keep their RemoteAddr.
|
||||
# that traffic is always a pod IP — collapsing all external clients
|
||||
# to one source. The NetBird reverse-proxy services are TLS
|
||||
# passthrough and carry the WAN client address in a PROXY protocol
|
||||
# v2 header (options.proxy_protocol, set by netbird-proxy-services);
|
||||
# X-Forwarded-For stays trusted for HTTP-mode services. Both are
|
||||
# accepted from the pod CIDRs only; connections without a header
|
||||
# (direct LAN/mesh) keep their RemoteAddr.
|
||||
proxyProtocol:
|
||||
trustedIPs:
|
||||
- "10.244.0.0/16"
|
||||
- "fd10:244::/56"
|
||||
forwardedHeaders:
|
||||
trustedIPs:
|
||||
- "10.244.0.0/16"
|
||||
|
||||
Reference in New Issue
Block a user