netbirdio/netbird · error
private services cannot enable bearer auth (SSO): NetBird-on
Error message
private services cannot enable bearer auth (SSO): NetBird-only access and SSO are mutually exclusive
What it means
Returned by Service.validatePrivateRequirements (management/internals/modules/reverseproxy/service/service.go:905). The private-service contract is mutually exclusive with SSO at the service level: NetBird-only access means the overlay's identity already authenticates users, while bearer auth would add a second, external identity layer. Enabling both on the same service is therefore rejected.
Source
Thrown at management/internals/modules/reverseproxy/service/service.go:905
return s.validateTLSMode()
default:
return fmt.Errorf("unsupported mode %q", s.Mode)
}
}
// validatePrivateRequirements enforces the private-service contract: HTTP mode, ≥1 access group, no bearer auth.
func (s *Service) validatePrivateRequirements() error {
if !s.Private {
return nil
}
if s.Mode != "" && s.Mode != ModeHTTP {
return fmt.Errorf("private services only support HTTP mode, got %q", s.Mode)
}
if len(s.AccessGroups) == 0 {
return errors.New("private services require at least one access group")
}
if s.Auth.BearerAuth != nil && s.Auth.BearerAuth.Enabled {
return errors.New("private services cannot enable bearer auth (SSO): NetBird-only access and SSO are mutually exclusive")
}
return nil
}
func (s *Service) validateHTTPMode() error {
if s.Domain == "" {
return errors.New("service domain is required")
}
if s.ListenPort != 0 {
return errors.New("listen_port is not supported for HTTP services")
}
return s.validateHTTPTargets()
}
func (s *Service) validateTCPUDPMode() error {
if s.Domain == "" {
return errors.New("domain is required for TCP/UDP services (used for cluster derivation)")
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Choose one model: for NetBird-only access set Private and remove/disable bearer auth.
- For SSO-protected public access, keep BearerAuth enabled and leave Private unset.
- If you need both identity layers, expose two services (one private, one SSO) rather than combining them.
Example fix
# before
{"name": "app", "private": true, "access_groups": ["grp-ops"],
"auth": {"bearer_auth": {"enabled": true, "issuer": "https://idp/example"}}}
# after: pick one access model
{"name": "app", "private": true, "access_groups": ["grp-ops"]} Defensive patterns
Strategy: validation
Validate before calling
if svc.Private && svc.Auth.BearerAuth != nil && svc.Auth.BearerAuth.Enabled {
return fmt.Errorf("choose one: NetBird-only access (private) or SSO bearer auth")
} Prevention
- Treat private and SSO as alternative access models, never combined.
- When copying service payloads, strip the auth block before setting private.
When it happens
Trigger: Creating or updating a service that simultaneously has Private: true and Auth.BearerAuth with Enabled: true.
Common situations: Reusing a public SSO-protected service definition and flipping on Private without clearing bearer auth; templates or copied payloads that carry auth blocks into private services; misreading SSO as an additional hardening layer on private services.
Related errors
- private services require at least one access group
- service name is required
- service name exceeds maximum length of 255 characters
- at least one target is required
- service domain is required
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/f55aa76b967253cf.
Report an issue: GitHub.