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

Creating Users via Dashboard

When embedded IdP is enabled, the Dashboard shows a "Create User" button (instead of "Invite User" shown for cloud-hosted NetBird):

  1. Navigate to TeamUsers
  2. Click Create User
  3. Fill in the user details:
    • Email (required) - User's email address for login
    • Name (required) - Display name
    • Groups (optional) - Auto-assign to groups
  4. 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

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

Comparison with External IdP

FeatureEmbedded IdPExternal IdP
Setup complexityMinimalModerate to High
Resource requirementsLow (~1GB RAM)Higher (2-4GB+ RAM)
Additional containersNoneIdP + Database
User managementDashboard/APIExternal IdP console
External SSOVia connectorsNative
SCIM provisioningNot availableAvailable (Enterprise)
MFAVia external connectorsNative IdP feature
Backup complexitySingle databaseMultiple databases

Disabling Embedded IdP

To switch from embedded IdP to an 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