Skip to content

Proxy Setup with Caddy #5359

Description

@da-wilky

Is your feature request related to a problem? Please describe.
Some time ago I switched from Traefik to Caddy and wont ever go back based on the UX of those two reverse proxies. I had kinda a bad time with Traefik (better than NGINX, but I feel its a pain to add the labels to each container and have this config spread around) and Caddy solved all my problems. So I want to keep Caddy while also being able to use the proxy.

Describe the solution you'd like
A stable production ready Caddy configuration, even tho I think this might not be in your hand. But maybe something can be done by design.

Describe alternatives you've considered
Currently I have a working setup with Caddy for the new Proxy. I will soon create a PR for adding it to the docs as beta, because I dont think this is really production ready, even tho I encountered no issues yet.

Setup

Follow the docs (https://docs.netbird.io/selfhosted/migration/enable-reverse-proxy)

  1. In case you are using the microservice architecture/not netbird-server, use this command instead of the provided command inside the docs to create the management token: docker exec -it netbird-management /go/bin/netbird-mgmt token create --name "my-proxy", thanks to @derlaft

  2. Modify the docker-compose.yml to this:

  # ...

  # Proxy
  proxy:
    image: netbirdio/reverse-proxy:latest
    container_name: netbird-proxy
    extra_hosts:
      - "netbird.domain.com:172.18.0.18" # IP of the Caddy Container
    restart: unless-stopped
    depends_on: # If you use microservice arch use this instead of the docs, if using netbird-server dont change this section
      - management
      - signal
      - relay
    env_file:
      - ./proxy.env
    volumes:
      - netbird_proxy_certs:/certs
    # Remove all the labels
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
    networks:
      default:
      caddy: # Add caddy network to the container

volumes:
  # ...
  netbird_proxy_certs:

networks:
  caddy:              # Add caddy network
    external: true

Also make sure the proxy.env file contains the following line:

...
NB_PROXY_PROXY_PROTOCOL=true
  1. Setup Caddy
  • To be able to pass TLS directly to the netbird-proxy we need the caddy l4 plugin (https://github.com/mholt/caddy-l4). This plugin is still in development, so this setup is not production ready.
  • Create a 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
  • Use this Dockerfile and build your own caddy image from docker-compose.yml
name: caddy

services:
  caddy:
    image: local-caddy-l4  # Name it how you like
    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.18.0.18 # 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:
    external: true
  1. Caddy Configuration
    Create the caddy folder and go into it with mkdir caddy && cd caddy (the name should be caddy, or change the name inside the volume section of docker-compose). Inside add the Caddyfile:
# 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 {
            proxy_protocol v2
            upstream netbird-proxy:8443
          }
        } 
        @proxy-wild tls sni_regexp ^[^.]+\.proxy\.domain\.com$
        route @proxy-wild {
          proxy {
            proxy_protocol v2
            upstream 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
  1. Caddy startup
  • Run docker compose build to build the image and docker compose up -d to run caddy.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions