feat(reverse_proxy): raw-directive route type; wire NetBird (gRPC/WS) route

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
sjat 2026-06-15 17:55:05 +02:00
parent 3762be4622
commit 1333ec181f
4 changed files with 24 additions and 5 deletions

View file

@ -3,4 +3,15 @@
reverse_proxy__acme_email: admin@wingu.me
reverse_proxy__routes:
- {host: test.askari.wingu.me, respond: "boma reverse proxy"}
# M4b appends: {host: netbird.askari.wingu.me, upstream: "netbird-dashboard:80"}
# NetBird control plane (M4b). gRPC (h2c) + WebSocket + path-based routing to two
# backend containers on the shared `boma` Docker network (ADR-024, ADR-016).
- host: netbird.askari.wingu.me
caddy: |
# gRPC needs HTTP/2 cleartext (h2c) to the backend
@grpc header Content-Type application/grpc*
reverse_proxy @grpc h2c://netbird-server:80
# management REST, embedded IdP, relay + ws-proxy (WebSocket) — same backend
@backend path /relay* /ws-proxy/* /api/* /oauth2/*
reverse_proxy @backend netbird-server:80
# dashboard SPA (everything else)
reverse_proxy /* netbird-dashboard:80

View file

@ -11,6 +11,10 @@
upstream: "app:80"
- host: t.example.test
respond: "ok"
- host: grpc.example.test
caddy: |
@grpc header Content-Type application/grpc*
reverse_proxy @grpc h2c://backend:80
roles:
- role: reverse_proxy

View file

@ -15,5 +15,7 @@
- "'app.example.test' in (_caddyfile.content | b64decode)"
- "'reverse_proxy app:80' in (_caddyfile.content | b64decode)"
- "'respond \"ok\" 200' in (_caddyfile.content | b64decode)"
- "'grpc.example.test' in (_caddyfile.content | b64decode)"
- "'reverse_proxy @grpc h2c://backend:80' in (_caddyfile.content | b64decode)"
fail_msg: "Caddyfile is missing expected content"
success_msg: "Caddyfile rendered correctly"

View file

@ -9,11 +9,13 @@
{% endif %}
}
{% for r in reverse_proxy__routes %}
{{ r.host }} {
{% if r.upstream is defined %}
reverse_proxy {{ r.upstream }}
{{ r['host'] }} {
{% if r['caddy'] is defined %}
{{ r['caddy'] | trim | indent(2, first=true) }}
{% elif r['upstream'] is defined %}
reverse_proxy {{ r['upstream'] }}
{% else %}
respond "{{ r.respond | default('boma') }}" 200
respond "{{ r['respond'] | default('boma') }}" 200
{% endif %}
}
{% endfor %}