Skip to content

Hitting nginx 404 with Caddy and PocketID #4978

@ujaandas

Description

@ujaandas

Describe the problem

I'm having a little trouble figuring out how I'm supposed to serve Netbird with PocketID on NixOS. I have it running inside a VM, and have all the enableNginx options enabled. Then, in another VM (acts like a nameserver/proxy) which is running Caddy, I forward all Netbird requests to my Netbird VM, ie; reverse_proxy 192.168.100.5:80.

What happens is that when I access netbird.domain, I see the dashboard load, it forwards to PocketID which asks me to authenticate, then it goes to this URL: https://netbird.domain.tld/auth?code=k21CjtEE4PxYhPgyXcmRlgMgMKmpRPrk&state=8ZWS2F3KCd7eP9Cq&iss=https%3A%2F%2Fpocketid.domain.tld, which leads to a 404 from nginx.

I've tried doing it with enableNginx disabled and serving all the routes myself, but I cannot for the life of me get it to work - how do I even serve the frontend? AFAIK, it's served with the mgmt server, but for some reason, I can't access anything.

In any case, I am 99% sure my Netbird configuration is fine, and that it's just something to do with how I'm forwarding requests. In my Caddyfile, all I do is literally just forward all requests to the Netbird VM:

"netbird.${domain}".extraConfig = ''
  reverse_proxy 192.168.100.5:80
'';

Again, my best guess is that ^^^ is forwarding the request to /auth to the wrong place. I've tried more complex ones, like I saw some on closed issues where they forward /api/* to one place, or gRPC requests to another, but (obviously) none of those helped here.

I've also attached my generated management.json file below.

management.json
{
  "DataStoreEncryptionKey": "REDACTED_DATASTORE_KEY",
  "Datadir": "/var/lib/netbird-mgmt/data",
  "DeviceAuthorizationFlow": {
    "Provider": "none",
    "ProviderConfig": {
      "Audience": "netbird",
      "ClientID": "netbird",
      "DeviceAuthEndpoint": "",
      "Domain": null,
      "Scope": "openid profile email groups",
      "TokenEndpoint": null,
      "UseIDToken": true
    }
  },
  "HttpConfig": {
    "Address": "127.0.0.1:8011",
    "AuthAudience": "REDACTED_AUTH_AUDIENCE",
    "IdpSignKeyRefreshEnabled": true,
    "OIDCConfigEndpoint": "https://pocketid.domain.tld/.well-known/openid-configuration"
  },
  "IdpManagerConfig": {
    "Auth0ClientCredentials": null,
    "AzureClientCredentials": null,
    "ClientConfig": {
      "ClientID": "netbird",
      "ClientSecret": "",
      "GrantType": "client_credentials",
      "Issuer": "",
      "TokenEndpoint": ""
    },
    "ExtraConfig": {
      "ApiToken": "REDACTED_API_TOKEN",
      "ManagementEndpoint": "https://pocketid.domain.tld"
    },
    "KeycloakClientCredentials": null,
    "ManagerType": "pocketid",
    "ZitadelClientCredentials": null
  },
  "PKCEAuthorizationFlow": {
    "ProviderConfig": {
      "Audience": "REDACTED_PKCE_AUDIENCE",
      "AuthorizationEndpoint": "",
      "ClientID": "REDACTED_PKCE_CLIENT_ID",
      "ClientSecret": "",
      "RedirectURLs": [
        "http://localhost:53000"
      ],
      "Scope": "openid profile email",
      "TokenEndpoint": "",
      "UseIDToken": false
    }
  },
  "Relay": {
    "Addresses": [
      "rels://netbird.domain.tld:33080"
    ],
    "CredentialsTTL": "24h",
    "Secret": "REDACTED_RELAY_SECRET"
  },
  "ReverseProxy": {
    "TrustedHTTPProxies": [],
    "TrustedHTTPProxiesCount": 0,
    "TrustedPeers": [
      "0.0.0.0/0"
    ]
  },
  "Signal": {
    "Password": null,
    "Proto": "https",
    "URI": "netbird.domain.tld:443",
    "Username": ""
  },
  "StoreConfig": {
    "Engine": "sqlite"
  },
  "Stuns": [
    {
      "Password": null,
      "Proto": "udp",
      "URI": "stun:netbird.domain.tld:3478",
      "Username": ""
    }
  ],
  "TURNConfig": {
    "CredentialsTTL": "12h",
    "Secret": "REDACTED_TURN_SECRET",
    "TimeBasedCredentials": false,
    "Turns": [
      {
        "Password": "REDACTED_TURN_PASSWORD",
        "Proto": "udp",
        "URI": "turn:netbird.domain.tld:3478",
        "Username": "netbird"
      }
    ]
  }
}

Any help at all is greatly appreciated!

UPDATE: Apparently, no route other than the base route works, is this expected?

Some more logs below:

Details
[default@vpn:~]$ curl -v https://netbird.domain.tld/auth
* Host netbird.domain.tld:443 was resolved.
* IPv6: 2606:4700:3033::6815:3a75, 2606:4700:3036::ac43:9f69
* IPv4: 192.168.100.4
*   Trying [2606:4700:3033::6815:3a75]:443...
* Immediate connect fail for 2606:4700:3033::6815:3a75: Network is unreachable
*   Trying 192.168.100.4:443...
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* SSL Trust Anchors:
*   OpenSSL default paths (fallback)
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519MLKEM768 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
*   subject: CN=*.domain.tld
*   start date: Dec  5 10:38:30 2025 GMT
*   expire date: Mar  5 10:38:29 2026 GMT
*   issuer: C=US; O=Let's Encrypt; CN=E8
*   Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA384
*   Certificate level 1: Public key type EC/secp384r1 (384/192 Bits/secBits), signed using sha256WithRSAEncryption
*   Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha256WithRSAEncryption
*   subjectAltName: "netbird.domain.tld" matches cert's "*.domain.tld"
* SSL certificate verified via OpenSSL.
* Established connection to netbird.domain.tld (192.168.100.4 port 443) from 192.168.100.5 port 43832 
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://netbird.domain.tld/auth
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: netbird.domain.tld]
* [HTTP/2] [1] [:path: /auth]
* [HTTP/2] [1] [user-agent: curl/8.17.0]
* [HTTP/2] [1] [accept: */*]
> GET /auth HTTP/2
> Host: netbird.domain.tld
> User-Agent: curl/8.17.0
> Accept: */*
> 
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Request completely sent off
< HTTP/2 404 
< alt-svc: h3=":443"; ma=2592000
< content-type: text/html
< date: Mon, 22 Dec 2025 01:44:30 GMT
< server: nginx
< via: 1.1 Caddy
< content-length: 146
< 
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host netbird.domain.tld:443 left intact
[default@vpn:~]$ curl -v http://192.168.100.5:80/auth
*   Trying 192.168.100.5:80...
* Established connection to 192.168.100.5 (192.168.100.5 port 80) from 192.168.100.5 port 58326 
* using HTTP/1.x
> GET /auth HTTP/1.1
> Host: 192.168.100.5
> User-Agent: curl/8.17.0
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 404 Not Found
< Server: nginx
< Date: Mon, 22 Dec 2025 01:44:50 GMT
< Content-Type: text/html
< Content-Length: 146
< Connection: keep-alive
< 
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
* Connection #0 to host 192.168.100.5:80 left intact

Expected behavior

I assume this should redirect to the Netbird dashboard?

Are you using NetBird Cloud?

No, I'm self hosting

NetBird version

I'm using an overlay while I wait for my PR.

Is any other VPN software installed?

Nope.

Have you tried these troubleshooting steps?

  • Reviewed client troubleshooting (if applicable)
  • Checked for newer NetBird versions
  • Searched for similar issues on GitHub (including closed ones)
  • Restarted the NetBird client
  • Disabled other VPN software
  • Checked firewall settings

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