Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Client failed to connect to Self-Hosted NetBird server: failed while getting Management Service public key #3110

Open
GeorgeDaGreatt opened this issue Dec 24, 2024 · 13 comments

Comments

@GeorgeDaGreatt
Copy link

GeorgeDaGreatt commented Dec 24, 2024

Describe the problem

I have a NetBird instance running locally behind Nginx Proxy Manager, with the IdP being Authentik. (Also behind NPM), the dashboard logs in fine through Authentik, and is able to operate just fine. But getting any client to work is near impossible because of the error. The ports that are needed for the server to communicate with clients have been forwarded and tested to work fine. NPM should be forwarding everything for it to work (Otherwise, the dashboard wouldn't load).

I tried using this solution, but I still encountered the same error. The error shows up regardless.

To Reproduce

Steps to reproduce the behavior:

  1. Host NetBird locally
  2. Connect the NetBird instance to Authentik
  3. Configure Nginx Proxy Manager to work with both NetBird and Authentik
  4. Install and Launch any NetBird client (I used Windows)
  5. Enter the Management and Admin URL (From the Dashboard)
  6. Press "Connect" in the right-click menu on the NetBird icon in taskbar
  7. See error pop up in this screen:
    image

Expected behavior

All clients were expected to work when connecting to the Self-Hosted NetBird Server, using the server URL provided in the dashboard.

Are you using NetBird Cloud?

No, Self-Hosted. And not in the cloud either.

NetBird version

netbird version 0.34.1

NetBird status -dA output:

Daemon status: LoginFailed

Run UP command to log in with SSO (interactive login):

 netbird up

If you are running a self-hosted version and no SSO provider has been configured in your Management Server,
you can use a setup-key:

 netbird up --management-url <YOUR_MANAGEMENT_URL> --setup-key <YOUR_SETUP_KEY>

More info: https://docs.netbird.io/how-to/register-machines-using-setup-keys

Additional context

Here is some of the configuration of the NetBird server, be aware that some details have been modified to ensure privacy.

Management.json

{
    "Stuns": [
        {
            "Proto": "udp",
            "URI": "stun:(domain here):3478",
            "Username": "",
            "Password": ""
        }
    ],
    "TURNConfig": {
        "TimeBasedCredentials": false,
        "CredentialsTTL": "12h0m0s",
        "Secret": "secret",
        "Turns": [
            {
                "Proto": "udp",
                "URI": "turn:(domain here):3478",
                "Username": "self",
                "Password": "ugQ9xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
            }
        ]
    },
    "Relay": {
        "Addresses": [
            "rel://(domain here):33080"
        ],
        "CredentialsTTL": "24h0m0s",
        "Secret": "BYbXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    },
    "Signal": {
        "Proto": "https",
        "URI": "(domain here):10000",
        "Username": "",
        "Password": ""
    },
    "Datadir": "/var/lib/netbird/",
    "DataStoreEncryptionKey": "6Rarxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "HttpConfig": {
        "LetsEncryptDomain": "",
        "CertFile": "",
        "CertKey": "",
        "AuthAudience": "kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
        "AuthIssuer": "https://(domain here)/application/o/netbird/",
        "AuthUserIDClaim": "",
        "AuthKeysLocation": "https://(domain here)/application/o/netbird/jwks/",
        "OIDCConfigEndpoint": "https://(domain here)/application/o/netbird/.well-known/openid-configuration",
        "IdpSignKeyRefreshEnabled": false,
        "ExtraAuthAudience": ""
    },
    "IdpManagerConfig": {
        "ManagerType": "authentik",
        "ClientConfig": {
            "Issuer": "https://(domain here)/application/o/netbird",
            "TokenEndpoint": "https://(domain here)/application/o/token/",
            "ClientID": "kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "ClientSecret": "",
            "GrantType": "client_credentials"
        },
        "ExtraConfig": {
            "Password": "6TFxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "Username": "Netbird"
        },
        "Auth0ClientCredentials": null,
        "AzureClientCredentials": null,
        "KeycloakClientCredentials": null,
        "ZitadelClientCredentials": null
    },
    "DeviceAuthorizationFlow": {
        "Provider": "hosted",
        "ProviderConfig": {
            "ClientID": "kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "ClientSecret": "",
            "Domain": "(domain here",
            "Audience": "kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "TokenEndpoint": "https://(domain here)/application/o/token/",
            "DeviceAuthEndpoint": "https://(domain here)/if/flow/default-device-code-flow/",
            "AuthorizationEndpoint": "",
            "Scope": "openid",
            "UseIDToken": false,
            "RedirectURLs": null
        }
    },
    "PKCEAuthorizationFlow": {
        "ProviderConfig": {
            "ClientID": "kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "ClientSecret": "",
            "Domain": "",
            "Audience": "kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "TokenEndpoint": "https://(domain here)/application/o/token/",
            "DeviceAuthEndpoint": "",
            "AuthorizationEndpoint": "https://(domain here)/application/o/authorize/",
            "Scope": "openid profile email offline_access api",
            "UseIDToken": false,
            "RedirectURLs": [
                "http://localhost:53000"
            ]
        }
    },
    "StoreConfig": {
        "Engine": "sqlite"
    },
    "ReverseProxy": {
        "TrustedHTTPProxies": [],
        "TrustedHTTPProxiesCount": 0,
        "TrustedPeers": [
            "0.0.0.0/0"
        ]
    }
}


docker-compose.yml

version: "3"
services:
  #UI dashboard
  dashboard:
    image: netbirdio/dashboard:latest
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    environment:
      # Endpoints
      - NETBIRD_MGMT_API_ENDPOINT=https://(domain here)
      - NETBIRD_MGMT_GRPC_API_ENDPOINT=https://(domain here)
      # OIDC
      - AUTH_AUDIENCE=kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      - AUTH_CLIENT_ID=kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      - AUTH_CLIENT_SECRET=
      - AUTH_AUTHORITY=https://(domain here)/application/o/netbird/
      - USE_AUTH0=false
      - AUTH_SUPPORTED_SCOPES=openid profile email offline_access api
      - AUTH_REDIRECT_URI=
      - AUTH_SILENT_REDIRECT_URI=
      - NETBIRD_TOKEN_SOURCE=accessToken
      # SSL
      - NGINX_SSL_PORT=443
      # Letsencrypt
      - LETSENCRYPT_DOMAIN=
      - LETSENCRYPT_EMAIL=
    volumes:
      - netbird-letsencrypt:/etc/letsencrypt/
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
  # Signal
  signal:
    image: netbirdio/signal:latest
    restart: unless-stopped
    volumes:
      - netbird-signal:/var/lib/netbird
    ports:
      - 10000:8080
  #      # port and command for Let's Encrypt validation
  #      - 443:443
  #    command: ["--letsencrypt-domain", "", "--log-file", "console"]
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
  # Relay
  relay:
    image: netbirdio/relay:latest
    restart: unless-stopped
    environment:
    - NB_LOG_LEVEL=info
    - NB_LISTEN_ADDRESS=(domain here):33080
    - NB_EXPOSED_ADDRESS=(domain here):33080
    # todo: change to a secure secret
    - NB_AUTH_SECRET=BYbXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ports:
      - 33080:33080
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"

  # Management
  management:
    image: netbirdio/management:latest
    restart: unless-stopped
    depends_on:
      - dashboard
    volumes:
      - netbird-mgmt:/var/lib/netbird
      - netbird-letsencrypt:/etc/letsencrypt:ro
      - ./management.json:/etc/netbird/management.json
    ports:
      - 33073:443 #API port
  #    # command for Let's Encrypt validation without dashboard container
  #    command: ["--letsencrypt-domain", "", "--log-file", "console"]
    command: [
      "--port", "443",
      "--log-file", "console",
      "--log-level", "info",
      "--disable-anonymous-metrics=false",
      "--single-account-mode-domain=netbird.truenasg.net",
      "--dns-domain=netbird.selfhosted"
      ]
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
    environment:
      - NETBIRD_STORE_ENGINE_POSTGRES_DSN=
      
  # Coturn
  coturn:
    image: coturn/coturn:latest
    restart: unless-stopped
    #domainname: (domain here) # only needed when TLS is enabled
    volumes:
      - ./turnserver.conf:/etc/turnserver.conf:ro
    #      - ./privkey.pem:/etc/coturn/private/privkey.pem:ro
    #      - ./cert.pem:/etc/coturn/certs/cert.pem:ro
    network_mode: host
    command:
      - -c /etc/turnserver.conf
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
volumes:
  netbird-mgmt:
  netbird-signal:
  netbird-letsencrypt:

setup.env (Copied example file and modified it)


## example file, you can copy this file to setup.env and update its values
##

# Image tags
# you can force specific tags for each component; will be set to latest if empty
NETBIRD_DASHBOARD_TAG=""
NETBIRD_SIGNAL_TAG=""
NETBIRD_MANAGEMENT_TAG=""
COTURN_TAG=""
NETBIRD_RELAY_TAG=""

# Dashboard domain. e.g. app.mydomain.com
NETBIRD_DOMAIN="(domain here)"

# TURN server domain. e.g. turn.mydomain.com
# if not specified it will assume NETBIRD_DOMAIN
NETBIRD_TURN_DOMAIN="(domain here)t"

# TURN server public IP address
# required for a connection involving peers in
# the same network as the server and external peers
# usually matches the IP for the domain set in NETBIRD_TURN_DOMAIN
NETBIRD_TURN_EXTERNAL_IP="(IP here)"

# -------------------------------------------
# OIDC
#  e.g., https://example.eu.auth0.com/.well-known/openid-configuration
# -------------------------------------------
NETBIRD_AUTH_OIDC_CONFIGURATION_ENDPOINT="https://(domain here)/application/o/netbird/.well-known/openid-configuration"
# The default setting is to transmit the audience to the IDP during authorization. However,
# if your IDP does not have this capability, you can turn this off by setting it to false.
#NETBIRD_DASH_AUTH_USE_AUDIENCE=false
NETBIRD_AUTH_AUDIENCE="kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# e.g. netbird-client
NETBIRD_AUTH_CLIENT_ID="kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# indicates the scopes that will be requested to the IDP
NETBIRD_AUTH_SUPPORTED_SCOPES="openid profile email offline_access api"
# NETBIRD_AUTH_CLIENT_SECRET is required only by Google workspace.
# NETBIRD_AUTH_CLIENT_SECRET=""
# if you want to use a custom claim for the user ID instead of 'sub', set it here
# NETBIRD_AUTH_USER_ID_CLAIM=""
# indicates whether to use Auth0 or not: true or false
NETBIRD_USE_AUTH0="false"
# if your IDP provider doesn't support fragmented URIs, configure custom
# redirect and silent redirect URIs, these will be concatenated into your NETBIRD_DOMAIN domain.
# NETBIRD_AUTH_REDIRECT_URI="/peers"
# NETBIRD_AUTH_SILENT_REDIRECT_URI="/add-peers"
# Updates the preference to use id tokens instead of access token on dashboard
# Okta and Gitlab IDPs can benefit from this
# NETBIRD_TOKEN_SOURCE="idToken"
# -------------------------------------------
# OIDC Device Authorization Flow
# -------------------------------------------
NETBIRD_AUTH_DEVICE_AUTH_PROVIDER="authentik"
NETBIRD_AUTH_DEVICE_AUTH_CLIENT_ID="kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Some IDPs requires different audience, scopes and to use id token for device authorization flow
# you can customize here:
NETBIRD_AUTH_DEVICE_AUTH_AUDIENCE="kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
NETBIRD_AUTH_DEVICE_AUTH_SCOPE="openid"
NETBIRD_AUTH_DEVICE_AUTH_USE_ID_TOKEN=false
# -------------------------------------------
# OIDC PKCE Authorization Flow
# -------------------------------------------
# Comma separated port numbers. if already in use, PKCE flow will choose an available port from the list as an alternative
# eg. 53000,54000
NETBIRD_AUTH_PKCE_REDIRECT_URL_PORTS="53000"
# -------------------------------------------
# IDP Management
# -------------------------------------------
# eg. zitadel, auth0, azure, keycloak
NETBIRD_MGMT_IDP="authentik"
# Some IDPs requires different client id and client secret for management api
NETBIRD_IDP_MGMT_CLIENT_SECRET="kNJuxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
# Required when setting up with Keycloak "https://<YOUR_KEYCLOAK_HOST_AND_PORT>/admin/realms/netbird"
# NETBIRD_IDP_MGMT_EXTRA_ADMIN_ENDPOINT=
# With some IDPs may be needed enabling automatic refresh of signing keys on expire
# NETBIRD_MGMT_IDP_SIGNKEY_REFRESH=false
# NETBIRD_IDP_MGMT_EXTRA_ variables. See https://docs.netbird.io/selfhosted/identity-providers for more information about your IDP of choice.
# -------------------------------------------
# Letsencrypt
# -------------------------------------------
# Disable letsencrypt
#  if disabled, cannot use HTTPS anymore and requires setting up a reverse-proxy to do it instead
NETBIRD_DISABLE_LETSENCRYPT=true
# e.g. [email protected]
NETBIRD_LETSENCRYPT_EMAIL=""
# -------------------------------------------
# Extra settings
# -------------------------------------------
# Disable anonymous metrics collection, see more information at https://netbird.io/docs/FAQ/metrics-collection
NETBIRD_DISABLE_ANONYMOUS_METRICS=false
# DNS DOMAIN configures the domain name used for peer resolution. By default it is netbird.selfhosted
NETBIRD_MGMT_DNS_DOMAIN=netbird.selfhosted

# -------------------------------------------
# Relay settings
# -------------------------------------------
# Relay server domain. e.g. relay.mydomain.com
# if not specified it will assume NETBIRD_DOMAIN
NETBIRD_RELAY_DOMAIN="(domain here)"

# Relay server connection port. If none is supplied
# it will default to 33080
NETBIRD_RELAY_PORT=""
NETBIRD_IDP_MGMT_EXTRA_USERNAME="Netbird"
NETBIRD_IDP_MGMT_EXTRA_PASSWORD="6TFSxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

I can provide further Information when requested, I hope all of this helps.

@creeram
Copy link

creeram commented Dec 26, 2024

@GeorgeDaGreatt Did you find the solution? I'm also getting the same issue.

@GeorgeDaGreatt
Copy link
Author

I'm glad to see that I'm not the only one with this error. But sadly, no.

@farewarr
Copy link

farewarr commented Jan 1, 2025

I'm getting the same issue and I opened a ticket on here too

@GeorgeDaGreatt
Copy link
Author

GeorgeDaGreatt commented Jan 1, 2025

I'm getting the same issue and I opened a ticket on here too

Could you share the issue's link with us? (in case I may need to reference it too)

@farewarr
Copy link

farewarr commented Jan 2, 2025

I'm getting the same issue and I opened a ticket on here too

Could you share the issue's link with us? (in case I may need to reference it too)

I resolved my issue myself:

Issue was resolved by adding the following in the setup.env file:

NETBIRD_MGMT_API_PORT to your reverse-proxy TLS-port (default: 443)
NETBIRD_SIGNAL_PORT to your reverse-proxy TLS-port

running ./configure.sh

then modifying docker-compose.yml to map ports 33073 for management to 443 and 10000 for signal to 443.

after running docker compose up -d I was able to add peers.

for the issue in this thread, make sure also your nginx configuration in the advanced tab as following:

# This is necessary so that grpc connections do not get closed early
# see https://stackoverflow.com/a/67805465
client_header_timeout 1d;
client_body_timeout 1d;

proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header        X-Scheme $scheme;
proxy_set_header        X-Forwarded-Proto https;
proxy_set_header        X-Forwarded-Host $host;
grpc_set_header         X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header       Authorization $http_authorization;
grpc_set_header         Authorization $http_authorization;

# Proxy dashboard
location / {
    proxy_pass http://ip-to-your-netbird-server:80;
}
# Proxy Signal
location /signalexchange.SignalExchange/ {
    grpc_pass grpc://ip-to-your-netbird-server:10000;
    grpc_set_header         Authorization $http_authorization;
    grpc_ssl_verify off;
    grpc_read_timeout 1d;
    grpc_send_timeout 1d;
    grpc_socket_keepalive on;
}
# Proxy Management http endpoint
location /api {
    proxy_pass http://ip-to-your-netbird-server:33073;
}
# Proxy Management grpc endpoint
location /management.ManagementService/ {
    grpc_pass grpc://ip-to-your-netbird-server:33073;
    grpc_set_header         Authorization $http_authorization;
    grpc_ssl_verify off;
    grpc_read_timeout 1d;
    grpc_send_timeout 1d;
    grpc_socket_keepalive on;
}

make sure the custom locations tab is blank. Let me know if you have any questions. Thanks.

@GeorgeDaGreatt
Copy link
Author

GeorgeDaGreatt commented Jan 2, 2025

After adding the configuration on both NetBird and Nginx Proxy Manager, the dashboard refused to load after authenticating with Authentik. To diagnose the issue, I opened my browser's console to see this error:

Screenshot 2025-01-02 123802

I made sure that there were no locations configured in Nginx Proxy Manager and that it was forwarding the correct host and ports and the formatting in the advanced section should be correct, because when it isn't Nginx Proxy Manager marks the Proxy Host as disabled and refuses to connect any clients to it.

That was before I looked at this message at the bottom of the advanced configuration which states:

image_2025-01-02_125044023

According to that message, I should be able to modify the configuration so that Nginx accepts gRPC and forwards everything perfectly fine.

My question is.. How?

And if I can't, is there another solution?

@farewarr
Copy link

farewarr commented Jan 2, 2025

@GeorgeDaGreatt I would ignore that message in the advanced tab, what that message is saying, which is misleading and kind of confusing, is that you cannot use the set_header or add_header simply by itself without also including code for the location blocks. But since we are including the location blocks in the advanced tab we are fine. What I have come to learn is that proxy manager itself is just a UI kid friendly verison of NGINX itself. So if you do not want to use any nginx code at all, you can use UI and the custom locations tab. If you do want to use standard nginx code you can do that in the advanced tab. I know how frustrating this is, as I spent days on this. So I am commited to helping you resolve this. if you want, you can post screenshots of all the tabs (execpt the advanced tab) and a copy of the code you have in the avanced tab and I will review it for you. Alternatively if you want to direct message me we can try to find time to hop on a zoom or webex or something.

@GeorgeDaGreatt
Copy link
Author

GeorgeDaGreatt commented Jan 3, 2025

Thanks for the clarification. I honestly think that they should really add more context about what they are talking about in the advanced tab, it confuses everyone that didn't spend days trying to figure it out.

Moving on..

After I found out that both types of configuration didn't work with NetBird (and Nginx didn't care where you placed configuration) I used the configuration @farewarr suggested earlier.

Here is the configuration I entered in the advanced tab:

client_header_timeout 1d;
client_body_timeout 1d;

proxy_set_header        X-Real-IP $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header        X-Scheme $scheme;
proxy_set_header        X-Forwarded-Proto https;
proxy_set_header        X-Forwarded-Host $host;
grpc_set_header         X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header       Authorization $http_authorization;
grpc_set_header         Authorization $http_authorization;

# Proxy dashboard
location / {
    proxy_pass http://192.168.1.67:80;
}
# Proxy Signal
location /signalexchange.SignalExchange/ {
    grpc_pass grpc://192.168.1.67:10000;
    grpc_set_header         Authorization $http_authorization;
    grpc_ssl_verify off;
    grpc_read_timeout 1d;
    grpc_send_timeout 1d;
    grpc_socket_keepalive on;
}
# Proxy Management http endpoint
location /api {
    proxy_pass http://192.168.1.67:33073;
}
# Proxy Management grpc endpoint
location /management.ManagementService/ {
    grpc_pass grpc://192.168.1.67:33073;
    grpc_set_header         Authorization $http_authorization;
    grpc_ssl_verify off;
    grpc_read_timeout 1d;
    grpc_send_timeout 1d;
    grpc_socket_keepalive on;
}

And the base configuration:

image
(All other tabs were left blank except the advanced tab)

I made sure that all configuration was removed in the location tab, and that all ports were matching. However, the configuration still returns the same error when logging in. (Shown below) I only modified the IP address needed in the advanced configuration for the correct forwarding.

image

I can share more configuration if needed to solve this issue, and I really appreciate all the help given to solve it.

@farewarr
Copy link

farewarr commented Jan 4, 2025

@GeorgeDaGreatt , whats handling your cert? Is Proxy Man terminating the SSL? Whether you are using a custom cert or a LetsEncrypt cert, you want to force SSL (enable that) and HTTP/2 (enable that). Also provide me your latest docker compose and management.json file. Thanks.

@GeorgeDaGreatt
Copy link
Author

GeorgeDaGreatt commented Jan 4, 2025

Edit: See next comment for an update

I use Cloudflare to manage my DNS and Certificates. and all my domains go to my Nginx Proxy Manager instance, where SSL is terminated.

I requested a LetsEncrypt Certificate in NPM and added it to the NPM configuration for NetBird, then turned on the settings I was suggested.

After saving those settings, my browser gave me this error:

image

After some trial and error, the error seemed to be caused by the "Force SSL" setting.

Moving on...

Here is the docker-compose.yml file and management.json file as requested:

docker-compose.yml

(some data has been redacted)

version: "3"
services:
  #UI dashboard
  dashboard:
    image: netbirdio/dashboard:latest
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    environment:
      # Endpoints
      - NETBIRD_MGMT_API_ENDPOINT=https://(domain here):443
      - NETBIRD_MGMT_GRPC_API_ENDPOINT=https://(domain here):443
      # OIDC
      - AUTH_AUDIENCE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      - AUTH_CLIENT_ID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      - AUTH_CLIENT_SECRET=
      - AUTH_AUTHORITY=https://(domain here)/application/o/netbird/
      - USE_AUTH0=false
      - AUTH_SUPPORTED_SCOPES=openid profile email offline_access api
      - AUTH_REDIRECT_URI=
      - AUTH_SILENT_REDIRECT_URI=
      - NETBIRD_TOKEN_SOURCE=accessToken
      # SSL
      - NGINX_SSL_PORT=443
      # Letsencrypt
      - LETSENCRYPT_DOMAIN=
      - LETSENCRYPT_EMAIL=
    volumes:
      - netbird-letsencrypt:/etc/letsencrypt/
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
  # Signal
  signal:
    image: netbirdio/signal:latest
    restart: unless-stopped
    volumes:
      - netbird-signal:/var/lib/netbird
    ports:
      - 10000:443
  #      # port and command for Let's Encrypt validation
  #      - 443:443
  #    command: ["--letsencrypt-domain", "", "--log-file", "console"]
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
  # Relay
  relay:
    image: netbirdio/relay:latest
    restart: unless-stopped
    environment:
    - NB_LOG_LEVEL=info
    - NB_LISTEN_ADDRESS=:33080
    - NB_EXPOSED_ADDRESS=(domain here):33080
    # todo: change to a secure secret
    - NB_AUTH_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    ports:
      - 33080:33080
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"

  # Management
  management:
    image: netbirdio/management:latest
    restart: unless-stopped
    depends_on:
      - dashboard
    volumes:
      - netbird-mgmt:/var/lib/netbird
      - netbird-letsencrypt:/etc/letsencrypt:ro
      - ./management.json:/etc/netbird/management.json
    ports:
      - 33073:443 #API port
  #    # command for Let's Encrypt validation without dashboard container
  #    command: ["--letsencrypt-domain", "", "--log-file", "console"]
    command: [
      "--port", "443",
      "--log-file", "console",
      "--log-level", "info",
      "--disable-anonymous-metrics=false",
      "--single-account-mode-domain=(domain here)",
      "--dns-domain=netbird.selfhosted"
      ]
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
    environment:
      - NETBIRD_STORE_ENGINE_POSTGRES_DSN=
      
  # Coturn
  coturn:
    image: coturn/coturn:latest
    restart: unless-stopped
    #domainname:  (domain here) # only needed when TLS is enabled
    volumes:
      - ./turnserver.conf:/etc/turnserver.conf:ro
    #      - ./privkey.pem:/etc/coturn/private/privkey.pem:ro
    #      - ./cert.pem:/etc/coturn/certs/cert.pem:ro
    network_mode: host
    command:
      - -c /etc/turnserver.conf
    logging:
      driver: "json-file"
      options:
        max-size: "500m"
        max-file: "2"
volumes:
  netbird-mgmt:
  netbird-signal:
  netbird-letsencrypt:

management.json

(some data has been redacted)

{
  "Stuns": [
    {
      "Proto": "udp",
      "URI": "stun:(domain here):3478",
      "Username": "",
      "Password": null
    }
  ],
  "TURNConfig": {
    "Turns": [
      {
        "Proto": "udp",
        "URI": "turn:(domain here):3478",
        "Username": "self",
        "Password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
      }
    ],
    "CredentialsTTL": "12h",
    "Secret": "secret",
    "TimeBasedCredentials": false
  },
  "Relay": {
    "Addresses": [
      "rel://(domain here):33080"
    ],
    "CredentialsTTL": "24h",
    "Secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "Signal": {
    "Proto": "https",
    "URI": "(domain here):443",
    "Username": "",
    "Password": null
  },
  "ReverseProxy": {
    "TrustedHTTPProxies": [],
    "TrustedHTTPProxiesCount": 0,
    "TrustedPeers": [
      "0.0.0.0/0"
    ]
  },
  "Datadir": "",
  "DataStoreEncryptionKey": "",
  "StoreConfig": {
    "Engine": "sqlite"
  },
  "HttpConfig": {
    "Address": "0.0.0.0:443",
    "AuthIssuer": "https://(domain here)/application/o/netbird/",
    "AuthAudience": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "AuthKeysLocation": "https://(domain here)/application/o/netbird/jwks/",
    "AuthUserIDClaim": "",
    "CertFile": "",
    "CertKey": "",
    "IdpSignKeyRefreshEnabled": false,
    "OIDCConfigEndpoint": "https://(domain here)/application/o/netbird/.well-known/openid-configuration"
  },
  "IdpManagerConfig": {
    "ManagerType": "authentik",
    "ClientConfig": {
      "Issuer": "https://(domain here)/application/o/netbird/",
      "TokenEndpoint": "https://(domain here)/application/o/token/",
      "ClientID": "",
      "ClientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "GrantType": "client_credentials"
    },
    "ExtraConfig": {
      "Password": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "Username": "Netbird"
    },
    "Auth0ClientCredentials": null,
    "AzureClientCredentials": null,
    "KeycloakClientCredentials": null,
    "ZitadelClientCredentials": null
  },
  "DeviceAuthorizationFlow": {
    "Provider": "hosted",
    "ProviderConfig": {
      "Audience": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "AuthorizationEndpoint": "",
      "Domain": "",
      "ClientID": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "ClientSecret": "",
      "TokenEndpoint": "https://(domain here)/application/o/token/",
      "DeviceAuthEndpoint": "https://(domain here)/application/o/device/",
      "Scope": "openid",
      "UseIDToken": false,
      "RedirectURLs": null
    }
  },
  "PKCEAuthorizationFlow": {
    "ProviderConfig": {
      "Audience": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "ClientID": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
      "ClientSecret": "",
      "Domain": "",
      "AuthorizationEndpoint": "https://(domain here)/application/o/authorize/",
      "TokenEndpoint": "https://(domain here)/application/o/token/",
      "Scope": "openid profile email offline_access api",
      "RedirectURLs": [
        "http://localhost:53000"
      ],
      "UseIDToken": false
    }
  }
}

If you need any more configuration or information, I will provide it on request. As always, thank you so much for your help on solving this issue.

@GeorgeDaGreatt
Copy link
Author

UPDATE

Since that clearly didn't work, I tried downloading a Cloudflare Origin server certificate to replace the LetsEncrypt certificate, I also changed some Cloudflare settings (Setting the SSL settings to be "Full (Strict)") which fixed the "Too many redirects" error.

However, my browser still reported the same error found a little bit before:

image

@farewarr
Copy link

farewarr commented Jan 5, 2025

@GeorgeDaGreatt,

ok in your docker compose file, signal port is set to 10000:443 and needs to be set to 10000:80

also, your relay domain (since its redacted, no worries) just make sure you have a separate domain for you relay pointing directly to the ip address of the nebird server, and not your reverse proxy. because we are not proxying the relay and if you have it pointing to the ip address of your proxy server it will try to access 33080 on the proxy server and not the netbird server.

as for cloudflare, not too familiar with it, are you using it as a tunnel? or does the cloudfalre itself terminate the SSL?

@GeorgeDaGreatt
Copy link
Author

GeorgeDaGreatt commented Jan 5, 2025

I changed the value in the docker-compose.yml file from 10000:443 to 10000:80. That, sadly, didn't change anything.

My Relay domain is separate, strictly not forwarded through Nginx Proxy Manager and (In Cloudflare) DNS queries are not proxied for that domain specifically. Thanks for the reassurance on that.

Cloudflare does have cloudflared (Cloudflare Tunnels), which I used to use when I didn't have NPM running. But now It is used mainly for DNS and SSL (And its very effective Proxying).

Cloudflare (On its free plan), provides a free SSL certificate and Proxying for your DNS queries, among other things. As for how SSL on Cloudflare works here is a little breakdown:

Cloudflare by default provides a Universal Certificate for your zone (domain). How Cloudflare handles encrypted traffic is a choice you make. Cloudflare gives you these options for how SSL traffic is handled:

Strict

Enforces and ensures encryption between Cloudflare and your Origin Server. You would normally use this to make sure ALL traffic is encrypted, regardless of user choice.

Full (Strict) *

Basically End-To-End encryption using Cloudflare's Origin certificates on your server, which your server HAS to have in order to use. (This is what I now use)

Full

End-To End encryption but without the Certificate Cloudflare provides, people normally use this if they already have a certificate (Like LetsEncrypt).

Flexible

Cloudflare serves traffic with encryption enabled, but connections made from Cloudflare to the Origin Server are unencrypted.

Off

Plain HTTP, no encryption whatsoever. Your browser doesn't trust your website by default.

| *=Its important to mention that the Origin Certificate you download and import on your Servers, is only valid for encryption between Cloudflare and your origin server. You CANNOT use the certificate for traffic served outside Cloudflare.

I hope that this provides a helpful guide for how SSL works on Cloudflare. I still cannot thank you enough for the help provided to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants