diff --git a/src/components/NavigationDocs.jsx b/src/components/NavigationDocs.jsx index f79dfaa2..aae001c0 100644 --- a/src/components/NavigationDocs.jsx +++ b/src/components/NavigationDocs.jsx @@ -389,6 +389,7 @@ export const docsNavigation = [ links: [ { title: 'Coturn to Embedded STUN', href: '/selfhosted/migration/coturn-to-stun-migration' }, { title: 'Enable Reverse Proxy', href: '/selfhosted/migration/enable-reverse-proxy' }, + { title: 'Caddy NetBird Proxy Setup', href: '/selfhosted/migration/caddy-netbird-proxy-setup' }, ] }, ], diff --git a/src/pages/manage/reverse-proxy/index.mdx b/src/pages/manage/reverse-proxy/index.mdx index 7e5a70d4..776f487c 100644 --- a/src/pages/manage/reverse-proxy/index.mdx +++ b/src/pages/manage/reverse-proxy/index.mdx @@ -13,6 +13,9 @@ NetBird Reverse Proxy lets you expose internal services running on peers or behi **Self-hosted requirement:** Self-hosted deployments **must** use [Traefik](/selfhosted/reverse-proxy) as their reverse proxy. Traefik is the only supported reverse proxy that provides TLS passthrough, which is required for the Reverse Proxy feature to function correctly. + + **Non-production workaround for caddy:** A selfhosted deployment using caddy is also possible but considered not production ready. You can find a setup-guide [here](/selfhosted/migration/caddy-netbird-proxy-setup). + The Reverse Proxy feature does not currently support pre-shared keys or Rosenpass. If your network relies on either of these features, reverse proxy services will not function as expected. diff --git a/src/pages/selfhosted/migration/caddy-netbird-proxy-setup.mdx b/src/pages/selfhosted/migration/caddy-netbird-proxy-setup.mdx new file mode 100644 index 00000000..605d9221 --- /dev/null +++ b/src/pages/selfhosted/migration/caddy-netbird-proxy-setup.mdx @@ -0,0 +1,158 @@ +# Migration Guide: Setup Caddy with L4 to support the netbird proxy feature + +This guide walks you through adding or modifying Caddy as external reverse proxy inside docker while supporting the netbird proxy feature. By the end, your Caddy reverse proxy will correctly forward the requests to the netbird proxy without TLS termination. + + +This setup is **not** production ready! + +It uses a caddy plugin that is still under development. Use with caution. + + +## Docker Compose Setup for Caddy + +This guide covers the basics about the setup of caddy using docker compose with a focus on the modifications needed to run it with TLS passthrough. + +### Dockerfile + +Caddy on default does not support TLS passthrough. There is a [caddy plugin](https://github.com/mholt/caddy-l4) that makes this functionality work. We need to create our own caddy docker image with this plugin installed. For this create the following `Dockerfile`: + +```dockerfile +ARG VERSION=2 + +FROM caddy:${VERSION}-builder AS builder +RUN xcaddy build --with github.com/mholt/caddy-l4 + +FROM caddy:${VERSION}-alpine +COPY --from=builder /usr/bin/caddy /usr/bin/caddy +``` + +This will build the docker image with the caddy plugin installed. + +### Docker Compose + +The build process of the image and the caddy management can be done using docker compose. Use the following `docker-compose.yml`: + +```yaml +name: caddy + +services: + caddy: + image: local-caddy-l4 + build: + context: . + dockerfile: Dockerfile + args: + VERSION: 2 + restart: unless-stopped + ports: + - 80:80 + - 443:443 + volumes: + - ./caddy:/etc/caddy + - ./data:/data + - ./config:/config + networks: + caddy: + ipv4_address: 172.30.0.10 # Define your IPv4 here, that you might reference inside the netbird proxy setup, the IP needs to be inside the subnet of the caddy network + +networks: + caddy: + driver: bridge + ipam: + config: + - subnet: 172.30.0.0/24 +``` + +Alternativly you can use `docker network create caddy --subnet 172.30.0.0/24` to create the network externally and instead use the following + +```yaml +networks: + caddy: + external: true +``` + +This way this docker-compose doesnt need to be up for the caddy network to be created. Else other services, that depend on the caddy network wont start if it is not initialized. + + +### Caddy Setup + +Create a folder called `caddy` and inside create the `Caddyfile`: + +```nginx +# This section needs to be first inside the Caddyfile and cannot be moved! +{ + admin off # Optional, disables the admin web ui (recommended if not used) + servers { + listener_wrappers { + layer4 { # This section passes the TLS directly to the container for the specified domain (and wildcard subdomain) + @proxy-exact tls sni proxy.domain.com + route @proxy-exact { + proxy netbird-proxy:8443 + } + @proxy-wild tls sni_regexp ^[^.]+\.proxy\.domain\.com$ + route @proxy-wild { + proxy netbird-proxy:8443 + } + } + tls + } + } +} + +netbird.domain.com { + # ws-proxy signal + handle /ws-proxy/signal* { + reverse_proxy netbird-signal:80 + } + + # ws-proxy management + handle /ws-proxy/management* { + reverse_proxy netbird-management:33073 + } + + # SignalExchange (gRPC) + handle /signalexchange.SignalExchange/* { + reverse_proxy h2c://netbird-signal:10000 + } + + # Relay + handle /relay* { + reverse_proxy netbird-relay:33080 + } + + # API + handle /api* { + reverse_proxy netbird-management:33073 + } + + # Management gRPC + handle /management.ManagementService/* { + reverse_proxy h2c://netbird-management:33073 + } + + # Proxy gRPC -> DONT FORGET TO ADD THIS + handle /management.ProxyService/* { + reverse_proxy h2c://netbird-management:33073 + } + + # Dashboard + handle { + reverse_proxy netbird-dashboard:80 + } +} + +# ... additional hosts +``` + +### Start Caddy + +Your folder structure for caddy should look like this: +``` +caddy-docker +| caddy +| | Caddyfile +| docker-compose.yml +| Dockerfile +``` + +After all these configurations navigate into the `caddy-docker` folder. Run the following command `docker compose up -d --build`. This will build the caddy docker image and start it. \ No newline at end of file diff --git a/src/pages/selfhosted/migration/enable-reverse-proxy.mdx b/src/pages/selfhosted/migration/enable-reverse-proxy.mdx index 8162974c..f17afb6d 100644 --- a/src/pages/selfhosted/migration/enable-reverse-proxy.mdx +++ b/src/pages/selfhosted/migration/enable-reverse-proxy.mdx @@ -15,7 +15,11 @@ The NetBird proxy container manages its own TLS certificates (via Let's Encrypt This capability is called **TLS passthrough**, and among common reverse proxies, **only Traefik supports it** via its TCP routers. Other reverse proxies (Nginx, Caddy, Nginx Proxy Manager) terminate TLS themselves and cannot forward the raw encrypted connection, which breaks the proxy's certificate management. -If your current deployment uses a reverse proxy other than Traefik, you'll need to switch before enabling this feature. See [Switching to Traefik](/selfhosted/reverse-proxy#traefik) for instructions. +If your current deployment uses a reverse proxy other than Traefik, you'll need to switch before enabling this feature for production environments. See [Switching to Traefik](/selfhosted/reverse-proxy#traefik) for instructions. + + +This guide also covers using Caddy as reverse proxy, even tho this is not considered production ready. + ## Overview of changes @@ -86,6 +90,9 @@ docker exec -it netbird-server netbird-mgmt token revoke Add the following service to your `docker-compose.yml`. Replace the placeholder values with your actual domains: + + +Traefik-Setup: ```yaml proxy: image: netbirdio/reverse-proxy:latest @@ -114,6 +121,39 @@ proxy: max-size: "500m" max-file: "2" ``` + + +Caddy-Setup: (not production ready) +```yaml +proxy: + image: netbirdio/reverse-proxy:latest + container_name: netbird-proxy + extra_hosts: + - "netbird.example.com:172.30.0.10" + restart: unless-stopped + networks: [netbird,caddy] + depends_on: + - netbird-server + env_file: + - ./proxy.env + volumes: + - netbird_proxy_certs:/certs + logging: + driver: "json-file" + options: + max-size: "500m" + max-file: "2" + +# Also add the network +networks: + # ... + caddy: + external: true +``` + +This setup expects the caddy network with the caddy-container already created and accessible. + + Also add the `netbird_proxy_certs` volume to your `volumes:` section: @@ -161,7 +201,10 @@ Create two DNS records pointing to the server running your NetBird stack — one The base domain record is required because a wildcard DNS record does not cover the bare domain itself. The wildcard record ensures that all service subdomains (e.g., `myapp.proxy.example.com`, `dashboard.proxy.example.com`) resolve to your server where Traefik forwards them to the proxy container. -### Step 5: Apply changes +### Step 5 (caddy only): Setup Caddy +Follow the instructions from [Setup external Caddy for use with Netbird Reverse-Proxy feature](/selfhosted/migration/caddy-netbird-proxy-setup). Afterwards continue with step 6. + +### Step 6: Apply changes ```bash # Pull the new image @@ -179,7 +222,7 @@ docker compose logs -f proxy You should see log messages indicating the proxy has connected to the management server and is ready to serve traffic. -### Step 6: Verify in the dashboard +### Step 7: Verify in the dashboard Once the proxy connects to the management server: diff --git a/src/pages/selfhosted/reverse-proxy.mdx b/src/pages/selfhosted/reverse-proxy.mdx index 6b918856..653e8b7c 100644 --- a/src/pages/selfhosted/reverse-proxy.mdx +++ b/src/pages/selfhosted/reverse-proxy.mdx @@ -677,6 +677,8 @@ netbird.example.com { } ``` +To support the [Netbird Proxy feature](/manage/reverse-proxy) using caddy follow this [guide](/selfhosted/migration/caddy-netbird-proxy-setup). Be aware that it is **not** considered production ready. + #### Caddy running on host (not in Docker) If Caddy is installed directly on the host, use localhost addresses: