[GH-ISSUE #5540] [Self-Hosted v0.66.2] Mobile/Desktop clients redirect to netbird.io cloud instead of custom management endpoint through Caddy reverse proxy #11715

Open
opened 2026-08-05 01:30:39 -04:00 by saavagebueno · 0 comments
Owner

Originally created by @cnils on GitHub (Mar 7, 2026).
Original GitHub issue: https://github.com/netbirdio/netbird/issues/5540

Environment

  • NetBird version: v0.66.2
  • Setup: Self-hosted on Raspberry Pi + Docker Swarm
  • Reverse proxy: Caddy (latest)
  • Network: ASUS router with DDNS (xxxxxx.asuscomm.com)
  • Clients tested: Android app, Windows Tailscale client, desktop CLI

Symptoms

  1. Android NetBird app: After entering custom server URL (https://xxxxxx.asuscomm.com), app requests login, then silently redirects to netbird.io cloud
  2. Desktop CLI: tailscale commands fail with "failed to connect" errors
  3. Dashboard: Works perfectly from LAN browsers (valid HTTPS cert, login functional)
  4. OIDC endpoints: Responding correctly - /.well-known/openid-configuration returns 200 with correct issuer

Tests Performed

1. HTTPS Certificate & DNS

curl -k https://xxxxxx.asuscomm.com/

Result: 200 OK, valid Let's Encrypt certificate

2. OIDC Configuration Endpoint

curl -k https://xxxxxx.asuscomm.com/oauth2/.well-known/openid-configuration

Result: 200 OK, returns correct issuer https://xxxxxx.asuscomm.com/oauth2

3. Dashboard Login (from LAN)

Result: Successful - Dashboard accessible, login works, user authenticated

4. gRPC Protocol Negotiation (the critical finding)

curl -v https://xxxxxx.asuscomm.com/management.ManagementService/GetPublicKey

Output:

ALPN: server accepted http/1.1  ← PROBLEM: Should be h2 (HTTP/2)
Expected: h2c or h2

5. Direct gRPC Port (bypassing Caddy)

  • Exposed port 33073 on management service
  • Direct gRPC still fails: Test-NetConnection hangs, clients timeout
  • Suggests gRPC negotiation issue deeper than routing

6. Management Service Logs

2026-03-08T01:26:20Z INF running gRPC backward compatibility server: [::]:33073
2026-03-08T01:26:20Z INF running HTTP server and gRPC server on the same port: [::]:80

Service reports healthy, gRPC listening.

Caddy Configuration Tested

@mgmt path /api /api/* /oauth2 /oauth2/* /management.ManagementService /management.ManagementService/*
handle @mgmt {
    reverse_proxy tasks.netbird_management:80
}

Result: Still negotiated HTTP/1.1 for /management.ManagementService/*

Root Cause Hypothesis

Either:

  1. Caddy reverse proxy cannot properly negotiate HTTP/2 upgrade for gRPC with Docker internal DNS (tasks.netbird_management)
  2. NetBird v0.66.2 gRPC server doesn't properly advertise HTTP/2 support to reverse proxies
  3. Mobile app has hardcoded fallback logic that redirects to cloud when custom management endpoint fails (silent degradation)

Impact

  • Self-hosted deployments with reverse proxies cannot onboard clients
  • Affects all client types (mobile, desktop CLI; web dashboard works)
  • Dashboard functions correctly, suggesting API/HTTPS is fine; gRPC-specific routing issue
  • Clients consistently redirect to netbird.io cloud service instead of using custom server
Originally created by @cnils on GitHub (Mar 7, 2026). Original GitHub issue: https://github.com/netbirdio/netbird/issues/5540 ### Environment - NetBird version: v0.66.2 - Setup: Self-hosted on Raspberry Pi + Docker Swarm - Reverse proxy: Caddy (latest) - Network: ASUS router with DDNS (`xxxxxx.asuscomm.com`) - Clients tested: Android app, Windows Tailscale client, desktop CLI ### Symptoms 1. Android NetBird app: After entering custom server URL (`https://xxxxxx.asuscomm.com`), app requests login, then silently redirects to `netbird.io` cloud 2. Desktop CLI: `tailscale` commands fail with `"failed to connect"` errors 3. Dashboard: **Works perfectly** from LAN browsers (valid HTTPS cert, login functional) 4. OIDC endpoints: **Responding correctly** - `/.well-known/openid-configuration` returns 200 with correct issuer ### Tests Performed #### 1. HTTPS Certificate & DNS ```bash curl -k https://xxxxxx.asuscomm.com/ ``` **Result:** 200 OK, valid Let's Encrypt certificate #### 2. OIDC Configuration Endpoint ```bash curl -k https://xxxxxx.asuscomm.com/oauth2/.well-known/openid-configuration ``` **Result:** 200 OK, returns correct issuer https://xxxxxx.asuscomm.com/oauth2 #### 3. Dashboard Login (from LAN) **Result:** Successful - Dashboard accessible, login works, user authenticated #### 4. gRPC Protocol Negotiation (the critical finding) ```bash curl -v https://xxxxxx.asuscomm.com/management.ManagementService/GetPublicKey ``` Output: ``` ALPN: server accepted http/1.1 ← PROBLEM: Should be h2 (HTTP/2) Expected: h2c or h2 ``` #### 5. Direct gRPC Port (bypassing Caddy) - Exposed port 33073 on management service - Direct gRPC still fails: Test-NetConnection hangs, clients timeout - Suggests gRPC negotiation issue deeper than routing #### 6. Management Service Logs ``` 2026-03-08T01:26:20Z INF running gRPC backward compatibility server: [::]:33073 2026-03-08T01:26:20Z INF running HTTP server and gRPC server on the same port: [::]:80 ``` Service reports healthy, gRPC listening. Caddy Configuration Tested ``` @mgmt path /api /api/* /oauth2 /oauth2/* /management.ManagementService /management.ManagementService/* handle @mgmt { reverse_proxy tasks.netbird_management:80 } ``` **Result:** Still negotiated HTTP/1.1 for /management.ManagementService/* #### Root Cause Hypothesis Either: 1. Caddy reverse proxy cannot properly negotiate HTTP/2 upgrade for gRPC with Docker internal DNS (`tasks.netbird_management`) 2. NetBird v0.66.2 gRPC server doesn't properly advertise HTTP/2 support to reverse proxies 3. Mobile app has hardcoded fallback logic that redirects to cloud when custom management endpoint fails (silent degradation) #### Impact - Self-hosted deployments with reverse proxies cannot onboard clients - Affects all client types (mobile, desktop CLI; web dashboard works) - Dashboard functions correctly, suggesting API/HTTPS is fine; gRPC-specific routing issue - Clients consistently redirect to netbird.io cloud service instead of using custom server
saavagebueno added the triage-needed label 2026-08-05 01:30:39 -04:00
Sign in to join this conversation.
No Label triage-needed
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DYNR/netbird#11715