netbird server setup behind nat

netbird | pfsync | haproxy | nginx | client

tested on debian12

                               ┌──────────────────┐       CARP      ┌──────────────────┐       
                               │                  │    PUBLIC VIP   │                  │       
                               │   pfsync1        │                 │   pfsync2        │       
                               │   10.1.0.28/16   │       CARP      │   10.1.0.29/16   │       
                               │                  │   INTERNAL VIP  │                  │       
                               └──────────────────┘ 10.1.255.254/16 └──────────────────┘       

                                                    │ │         │                              
                                                    │ │         │                              
                                                    │ │         └───────────────────┐          
                    ┌───────────────────────────────┘ │                             │          
                    │                                 │ 10000/tcp (http)            │          
         80,443/tcp │                                 │                             │          
                    ▼                                 │ 3478,5349/tcp               │          
┌────────────────────────┐                            │ 3478,5349/udp               │          
│                        │                            │ 49152:49999/udp             │          
│   dnc-haproxy          │                            ▼                             │          
│   10.1.0.27/16         │                  ┌────────────────────────┐              │          
│                        ├────────────────► │                        │              │          
└────────────────────────┘                  │   dnc-netbird          │  ┌───────────┤          
                                            │   10.1.0.20/16         │  │           │          
                                            │                        │  │ 51853/udp │ 51854/udp
                                            └────────────────────────┘  │           │          
                                                                        ▼           ▼          
                                                              ┌──────────────┐ ┌──────────────┐
                                                              │              │ │              │
                                                              │ bastion53    │ │ bastion54    │
                                                              │ 10.1.0.53/16 │ │ 10.1.0.54/16 │
                                                              │              │ │              │
                                                              └──────────────┘ └──────────────┘

warning // lessons learned

public poc

that poc needs to be on the public network as NETBIRD_DOMAIN resolves while SSL is required – not sure it’s possible to PoC within with static name resolution

behind a reverse-proxy

in the compose file, api mgmt endpoints need to be fixed manually

NETBIRD_MGMT_API_ENDPOINT
NETBIRD_MGMT_GRPC_API_ENDPOINT

mgmt grpc needs to be reverse-proxied in a special way

as for signal grpc, we did not manage: haproxy was constantly reporting a 503, therefore we switched to plain text http for that haproxy backend.

network requirements

you need an auth server and it needs to resolve from within the docker instances e.g.

    ping -c1 keycloak.nethence.com
    nmap -p 443 keycloak.nethence.com

see netbird-pfsync if you want DNAT

and eventually a reverse-proxy e.g. haproxy or nginx

system requirements

unless you want docker-ce

apt install docker.io docker-compose
docker ps

apt install jq curl gettext-base

keycloak setup

see keycloak and setup as such

realm       netbird

user        netbird & credentials (not temporary)

clients
  client id netbird-client -- NETBIRD_AUTH_CLIENT_ID
            + oauth2 device auth grant
            + direct access grants
  root url  https://netbird.nethence.com/
  redirect  https://netbird.nethence.com/* & http://localhost:53000
  post logout   https://netbird.nethence.com/*
  web origins   "+"

client scopes   "api" (default & OIDC)
            + include in token scope
  new mapper    type audience netbird-audience (client audience: netbird-client)

clients
        netbird-client / client scopes --> api (default)

clients
  client id netbird-backend -- NETBIRD_IDP_MGMT_CLIENT_ID
            + client auth
            + oauth2 device auth grant
            + direct access grants
            + service accounts roles
        credentials tab / check credentials client secret -- NETBIRD_IDP_MGMT_CLIENT_SECRET
        service accounts roles tab / assign view-users (realm mgmt)

install

grab latest tag

ver=0.41.0

cd /opt/
wget https://github.com/netbirdio/netbird/archive/refs/tags/v$ver.tar.gz
tar xzf v$ver.tar.gz
rm -f v$ver.tar.gz

ln -s netbird-$ver netbird

setup

cd netbird/infrastructure_files/
ls -lF setup.env.example

curl ifconfig.me; echo

# new file
vi setup.env
NETBIRD_DOMAIN="netbird.nethence.com"
NETBIRD_TURN_EXTERNAL_IP="@@@@@ front-facing public ip here @@@@@"

# keycloak setup
NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://keycloak.nethence.com/realms/netbird/.well-known/openid-configuration"
NETBIRD_USE_AUTH0=false
NETBIRD_AUTH_CLIENT_ID="netbird-client"
NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api"
NETBIRD_AUTH_AUDIENCE="netbird-client"
NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID="netbird-client"
NETBIRD_MGMT_IDP="keycloak"
NETBIRD_IDP_MGMT_CLIENT_ID="netbird-backend"
NETBIRD_IDP_MGMT_CLIENT_SECRET="@@@@@ netbird-backend client secret here @@@@@"
NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT="https://keycloak.nethence.com/admin/realms/netbird"

# we already got an ssl certificate
NETBIRD_DISABLE_LETSENCRYPT=true
NETBIRD_DISABLE_ANONYMOUS_METRICS=true
NETBIRD_MGMT_DNS_DOMAIN=netbird.selfhosted

#NETBIRD_MGMT_API_PORT=
#NETBIRD_SIGNAL_PORT=
#TURN_MIN_PORT="49152"
#TURN_MAX_PORT="49999"

NETBIRD_MGMT_DNS_DOMAIN=nethence.com
NETBIRD_SIGNAL_PROTOCOL=http

proceed

cp -pi base.setup.env base.setup.env.dist
vi base.setup.env

# default https port is good enough
NETBIRD_MGMT_API_ENDPOINT=https://$NETBIRD_DOMAIN

cp -pi docker-compose.yml.tmpl docker-compose.yml.tmpl.dist
vi docker-compose.yml.tmpl

(make the dashboard listen 80 only)
s/:443//
(remove nginx ssl & letsencrypt volume)

  dashboard:
  signal:
  relay:
  management:
  coturn:
    extra_hosts:
      - "keycloak.nethence.com=127.0.0.1"
      - "netbird.nethence.com=127.0.0.1"

./configure.sh
cd artifacts/

check that you obtained the right kc setup (mgmt needs that to get a token endpoint)

#curl -s https://keycloak.nethence.com/realms/netbird/.well-known/openid-configuration > openid-configuration.json
jq < openid-configuration.json

vi docker-compose.yml

tuning 1/3

in our case we also had to add static name resolution (anyhow it might help, makes the path shorter)

tuning 2/3

vi management.json

    "Signal": {
        "Proto": "http",

ready to go

#docker compose down
docker compose up -d
# --force-recreate

docker ps -a
netstat -lntup

https://netbird.nethence.com/ ==> login as netbird (owner)

troubleshooting

docker compose logs signal
docker compose logs management
docker compose logs coturn
docker compose logs dashboard

troubleshooting

    Fatal glibc error: CPU does not support x86-64-v2

==> either rebuild keycloak (w/o RHEL9 as base) or change the VPS – works fine on xen/pvh

Error: failed retrieving a new idp manager with err: keycloak IdP configuration is incomplete, TokenEndpoint is missing

==> fix openid-configuration.json

resources

https://docs.netbird.io/selfhosted/selfhosted-guide

https://docs.netbird.io/selfhosted/identity-providers#keycloak

kc setup

https://docs.netbird.io/selfhosted/identity-providers#keycloak

troubles

https://github.com/netbirdio/netbird/issues/1247 ==> using advanced install and kc instead


HOME | GUIDES | LECTURES | LAB | SMTP HEALTH | HTML5 | CONTACT
Copyright © 2024 Pierre-Philipp Braun