Phase 1 (#802) put the ServersTransport under post-crds and infrastructure-crds has applied it. The copy in crowdsec/lapi-ingress.yaml goes; the Ingress stays (core kind). With it, the infrastructure apply set holds no traefik.io consumer any more, which is what a cold rebuild needs. Prune: infrastructure reconciles first and skips the object if the last applier label names infrastructure-crds; otherwise it deletes and infrastructure-crds recreates it seconds later. Only the public LAPI ingress used by the external bouncers is behind that transport. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
76 lines
3.5 KiB
YAML
76 lines
3.5 KiB
YAML
# Public LAPI endpoint for the firewall bouncers on proxy-1/proxy-2.
|
|
#
|
|
# WHY PUBLIC AT ALL. The bouncers run as host processes on the proxies, and
|
|
# the proxies have no mesh access: the netbird-proxy container runs non-root
|
|
# (see the ip_unprivileged_port_start task in the netbird-proxy role), so it
|
|
# has no NET_ADMIN and no /dev/net/tun, and its embedded NetBird client
|
|
# therefore terminates the tunnel in userspace. The tunnel belongs to that
|
|
# process, not to the host netns — a second process on the same host cannot
|
|
# route through it. The alternative was a host-level NetBird client plus the
|
|
# LAPI on a LoadBalancer VIP; this reuses the path every other service already
|
|
# takes instead of adding two peers and an ACL policy.
|
|
#
|
|
# NO IP ALLOWLIST, deliberately. The bouncer key is the access control.
|
|
#
|
|
# An allowlist was the obvious second factor and it does not work here. A
|
|
# request originating on a proxy host does not arrive carrying that host's
|
|
# public address: the client connects to the local proxy on 127.0.0.1, the
|
|
# reverse-proxy puts what it saw into X-Forwarded-For, and Traefik resolves
|
|
# that. Measured against the netbird-proxy-watchdog, which makes exactly this
|
|
# kind of request every round:
|
|
#
|
|
# 172.18.0.3 - - [02/Sep/2026:10:12:01] "GET /" 200 websecure-immich-...
|
|
# 172.18.0.3 - - [02/Sep/2026:10:12:01] "GET /" 200 websecure-home-...
|
|
#
|
|
# 172.18.0.3 is a Docker bridge address on the proxy side. Allowlisting the
|
|
# published proxy addresses would have rejected the bouncer with 403;
|
|
# allowlisting 172.18.0.0/16 would be a private range on a host we do not
|
|
# control the addressing of, which is not a security control.
|
|
#
|
|
# What remains is the API key, which is the real control anyway: this endpoint
|
|
# serves read-only decision streams to a valid bouncer key and nothing else.
|
|
# The admin surface is cscli, in-cluster. If the source address ever becomes
|
|
# deterministic, an ipAllowList can be added on top.
|
|
#
|
|
# The LAPI serves HTTPS only once tls.enabled is set — there is no plaintext
|
|
# fallback and no second port; 8080 is the TLS port. Its certificate comes
|
|
# from the chart's own self-signed CA, so Traefik needs that CA to verify the
|
|
# backend; the ServersTransport carrying it is a traefik.io CRD consumer and
|
|
# lives in post-crds/crowdsec-lapi-serverstransport.yaml.
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: crowdsec-lapi
|
|
namespace: crowdsec
|
|
labels:
|
|
# Public DNS via Cloudflare; the proxies resolve it from outside. The UDM
|
|
# external-dns instance skips it, LAN reaches it via the hairpin NAT.
|
|
dns.renner.uno/public: "true"
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-cluster
|
|
# NOT behind the Authentik gate: the client is a daemon with an API key,
|
|
# not a browser that can complete an OIDC flow.
|
|
#
|
|
# The backend scheme and ServersTransport are NOT set here. Under the
|
|
# Kubernetes Ingress provider, `traefik.ingress.kubernetes.io/service.*`
|
|
# are SERVICE annotations — on an Ingress they are silently ignored, and
|
|
# Traefik then talks plaintext to a TLS-only backend. They live on the
|
|
# chart's Service instead, via lapi.service.annotations in helmrelease.yaml.
|
|
spec:
|
|
ingressClassName: traefik
|
|
rules:
|
|
- host: crowdsec.renner.uno
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: crowdsec-service
|
|
port:
|
|
number: 8080
|
|
tls:
|
|
- secretName: crowdsec-lapi-public-tls
|
|
hosts:
|
|
- crowdsec.renner.uno
|