Local User Management

NetBird's Management service includes built-in user management, allowing you to create and manage local users directly without requiring an external identity provider. This functionality is powered by an embedded Dex server.

Starting with version 0.62, NetBird no longer requires an external identity provider. The Management service now supports creating and managing local users directly, so you can get started without setting up Zitadel, Keycloak, or any other IdP.

With local user management, you can:

  • Create local users directly from the NetBird Dashboard
  • Add external identity providers (Google, Microsoft, Okta, etc.) through the Dashboard UI
  • Configure multiple IdPs simultaneously, users see all providers as login options
  • Simplify your deployment with fewer containers and reduced resource requirements
  • Get started faster with no additional IdP setup required

Get Started →

When to Use Local Users

Local user management is ideal for:

Use CaseWhy Local Users Work
HomelabsSimple setup, minimal resources, no external dependencies
Small teamsEasy user management, quick onboarding
Proof of conceptGet started in minutes, upgrade path available
Air-gapped environmentsNo external service dependencies
Development/testingFast iteration, simple reset

Consider a standalone external IdP if you need:

  • SCIM user provisioning (Enterprise feature)
  • Complex user lifecycle management
  • Integration with existing enterprise SSO infrastructure
  • Specific IdP features not available via OIDC connectors

Configuration

Enabling Embedded IdP

The embedded IdP is enabled by default when using the new getting-started.sh quickstart script. For manual configuration, update your management.json:

{
  "EmbeddedIdP": {
    "Enabled": true,
    "DataDir": "/var/lib/netbird/idp"
  },
  "EncryptionKey": "<auto-generated-base64-key>"
}

Configuration Options

OptionDescriptionDefault
EmbeddedIdP.EnabledEnable/disable the embedded IdPtrue (quickstart)
EmbeddedIdP.DataDirDirectory for IdP data storage/var/lib/netbird/idp
EncryptionKeyBase64-encoded AES-256 key for encrypting user dataAuto-generated

Environment Variables

When using docker-compose, you can configure these via environment variables:

environment:
  - NETBIRD_EMBEDDED_IDP_ENABLED=true
  - NETBIRD_EMBEDDED_IDP_DATA_DIR=/var/lib/netbird/idp
  - NETBIRD_ENCRYPTION_KEY=${ENCRYPTION_KEY}

Generating an Encryption Key

If you need to generate an encryption key manually:

openssl rand -base64 32

User Management

Inviting Users via Dashboard

You can invite users via a secure invite link, allowing them to set their own password.

Invite User

  1. Navigate to TeamUsers
  2. Click Add User
  3. Select the Invite User tab
  4. Fill in the user details:
    • Name (required) - Display name
    • Email (required) - User's email address
    • Role - User role (User, Admin, etc.)
    • Expires in - Number of days until the invite link expires (default: 3 days)
    • Auto-assigned groups (optional) - Groups to assign when the user joins
  5. Click Create Invite Link

After creation, a modal displays:

  • The invite link that you can share with the user
  • The expiration date of the invite
  • Copy & Close button to copy the link

Invite Link

The invited user can then:

  1. Open the invite link in their browser
  2. Set their own password
  3. Log in to NetBird with their new credentials

Accept User Invite

Managing Pending Invites

To view and manage pending invites:

  1. Navigate to TeamUsers
  2. Click Show Invites to switch to the invites view

From the invites view, you can:

  • Regenerate an invite link if it has expired or needs to be resent
  • Delete an invite to revoke access before it's accepted

Creating Users via Dashboard

As an alternative to inviting users, you can create users with a generated password:

  1. Navigate to TeamUsers
  2. Click Add User
  3. Select the Create User tab
  4. Fill in the user details:
    • Email (required) - User's email address for login
    • Name (required) - Display name
    • Groups (optional) - Auto-assign to groups
  5. Click Create

After creation, a modal displays with:

  • The generated password with a copy button
  • Warning: "This password will only be shown once. Please copy it now."
  • Copy & Close button to copy password and dismiss

Inviting Users via API

curl -X POST "https://netbird.example.com/api/users/invites" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "name": "New User",
    "role": "user",
    "auto_groups": ["group-id-1"],
    "expires_in": 259200
  }'

The expires_in field specifies the invite validity period in seconds (e.g., 259200 = 3 days).

Response:

{
  "id": "invite-abc123",
  "email": "user@example.com",
  "name": "New User",
  "role": "user",
  "invite_link": "abc123-token-xyz",
  "invite_expires_at": "2024-01-10T12:00:00Z",
  "auto_groups": ["group-id-1"]
}

Construct the full invite URL by appending the token to your dashboard URL:

https://netbird.example.com/invite?token=abc123-token-xyz

Changing User Passwords

The Change Password feature allows local users on self-hosted NetBird deployments to update their account password directly from the dashboard.

Change Password

This feature is available when:

  • The deployment is self-hosted (not NetBird's hosted platform)
  • The user authenticates via local authentication

Users authenticated through SSO/OIDC providers will not see this option.

How to Use:

  1. Click your avatar in the top-right corner of the dashboard
  2. Select "Change Password" from the dropdown menu
  3. Enter your current password to verify your identity
  4. Enter your new password (minimum 8 characters)
  5. Confirm your new password
  6. Click "Change Password" or press Enter
Change Password

Password Requirements

  • Minimum length: eight characters
  • New password and confirmation must match

User IdP Badges

In the Users table, each user shows a badge indicating their identity provider:

  • Users created locally show no badge (or "Local" badge)
  • Users who authenticated via an external connector show that provider's icon (Google, Microsoft, etc.)
  • The badge links to the idp_id field in the user record

Creating Users via API

curl -X POST "https://netbird.example.com/api/users" \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "name": "New User",
    "auto_groups": ["group-id-1"]
  }'

Response includes the generated password:

{
  "id": "user-abc123",
  "email": "user@example.com",
  "name": "New User",
  "role": "user",
  "status": "active",
  "password": "generated-password-here"
}

User Roles

Users created through the embedded IdP can be assigned roles:

RolePermissions
OwnerFull administrative access, cannot be demoted
AdminManage users, peers, policies, and settings
UserConnect devices, view assigned resources

Instance Setup (First Run)

When NetBird starts with the embedded IdP and no existing accounts, the Dashboard redirects to the /setup route and displays the Instance Setup Wizard:

  1. The Dashboard checks GET /instance for setup_required: true
  2. If setup is required, users are redirected to /setup
  3. The wizard collects:
    • Email address (required)
    • Password (required, minimum 8 characters)
    • Name (optional)
  4. On submit, the owner account is created via POST /instance/setup
  5. User is redirected to login with the credentials they just created

Setup API

For automated deployments, you can complete setup via API:

# Check if setup is required
curl "https://netbird.example.com/api/instance"

# Response when setup is needed:
{
  "setup_required": true
}

# Complete setup
curl -X POST "https://netbird.example.com/api/instance/setup" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@example.com",
    "password": "securepassword123",
    "name": "Admin User"
  }'

# Response:
{
  "user_id": "user-abc123",
  "account_id": "account-xyz789"
}

Data Encryption

The embedded IdP encrypts sensitive user data at rest:

FieldEncryption
EmailAES-256-GCM
NameAES-256-GCM
Passwordbcrypt hash (via Dex)

The encryption key is configured in management.json and should be:

  • Generated using a cryptographically secure random generator
  • Stored securely (not in version control)
  • Included in backup procedures
  • Rotated according to your security policies

Security Considerations

Password Requirements

Default password requirements for local users:

  • Minimum 8 characters
  • No specific complexity requirements (consider your security policy)

Session Management

  • JWT tokens are issued upon successful authentication
  • Token expiration follows OIDC best practices
  • Device authorization flow available for CLI clients

Audit Logging

User authentication events are logged in the activity log:

  • Login attempts (successful and failed)
  • User creation/deletion
  • Connector configuration changes

Troubleshooting

"Embedded IdP not available" error

Ensure EmbeddedIdP.Enabled is true in management.json and the Management service has been restarted.

Users can't log in

  1. Check Management service logs: docker compose logs management
  2. Verify the encryption key hasn't changed
  3. Confirm the user exists: Check TeamUsers in Dashboard

Disabling Embedded IdP

To switch from embedded IdP to a (standalone) external IdP:

  1. Configure your external IdP following the Advanced guide

  2. Update management.json:

    {
      "EmbeddedIdP": {
        "Enabled": false
      },
      "HttpConfig": {
        "OIDCConfigEndpoint": "https://your-idp.example.com/.well-known/openid-configuration"
      }
    }
    
  3. Restart the Management service

  4. Users will need to re-authenticate with the new IdP