Skip to main content
Proper security configuration is critical for protecting your NetBird network infrastructure. This guide covers all security-related environment variables and configuration options.

Environment Variables

Authentication & Authorization

NETBIRD_ALLOWED_DOMAIN

Purpose: Restrict access to users from a specific email domain
NETBIRD_ALLOWED_DOMAIN=example.com
Strongly recommended for production. Without this setting, any user with a valid Google account can authenticate and access your VPN management interface.
Behavior:
  • Enforced during OAuth callback after successful Google authentication
  • Case-insensitive domain matching
  • Users with non-matching domains are rejected with a clear error message
  • Existing users with non-matching domains can still access if already registered
// Source: config/netbird.php:12
'allowed_domain' => env('NETBIRD_ALLOWED_DOMAIN'),

// Source: app/Http/Controllers/Auth/GoogleController.php:24-31
$allowedDomain = config('netbird.allowed_domain');
if ($allowedDomain) {
    $emailDomain = substr(strrchr($googleUser->getEmail(), '@'), 1);
    if (strcasecmp($emailDomain, $allowedDomain) !== 0) {
        return redirect()->route('login')
            ->withErrors(['email' => 'Only users with @'.$allowedDomain.' email addresses are allowed.']);
    }
}

NETBIRD_ADMIN_EMAIL

Purpose: Define the administrator email address Admin Privileges:
  • Approve or deny resource requests
  • Create resources without approval
  • Edit and delete any resource
  • View activity logs
  • Manage all pending requests
Only one admin email is supported. For multiple admins, consider implementing role-based access control or granting elevated NetBird API permissions to multiple users.

API Security

NETBIRD_API_TOKEN

Purpose: Authenticate with the NetBird API
NETBIRD_API_TOKEN=nb_1234567890abcdef
Critical Security CredentialThis token has full access to your NetBird network. Compromise of this token could allow an attacker to:
  • Create, modify, or delete network resources
  • Access network configuration
  • Potentially expose customer networks
Protection measures:
  • Never commit to version control
  • Use different tokens for dev/staging/production
  • Rotate regularly (every 90 days recommended)
  • Store in secure secrets management system
  • Monitor API usage for anomalies
Configuration Reference:
// Source: config/netbird.php:5
'api_token' => env('NETBIRD_API_TOKEN'),

NETBIRD_API_URL

Purpose: NetBird API endpoint URL
NETBIRD_API_URL=https://api.netbird.io
  • Use official NetBird API URL or your self-hosted instance
  • Must use HTTPS in production
  • Default: https://api.netbird.io

Session Configuration

SESSION_DRIVER

Purpose: Session storage backend
SESSION_DRIVER=database
Recommended: database (default) Options:
  • database - Best for production (scalable, persistent)
  • redis - High-performance option for large deployments
  • file - Development only (not scalable)
  • cookie - Not recommended (security implications)
Database sessions provide the best balance of security, performance, and reliability for most deployments.

SESSION_LIFETIME

Purpose: Session idle timeout in minutes
SESSION_LIFETIME=120
Default: 120 minutes (2 hours) Security considerations:
  • Shorter lifetime = better security, more frequent re-authentication
  • Longer lifetime = better UX, higher session hijacking risk
  • Recommended range: 60-240 minutes
Balance security with user experience. For high-security environments, consider 60 minutes. For general use, 120 minutes is appropriate.
Purpose: Require HTTPS for session cookies
SESSION_SECURE_COOKIE=true
Required in production. Always set to true when using HTTPS. This prevents session cookies from being transmitted over unencrypted connections.
// Source: config/session.php:172
'secure' => env('SESSION_SECURE_COOKIE'),

SESSION_HTTP_ONLY

Purpose: Prevent JavaScript access to session cookies
SESSION_HTTP_ONLY=true
Default: true Leave enabled - This is critical XSS protection. There is no legitimate reason to disable this.

SESSION_SAME_SITE

Purpose: CSRF protection via SameSite cookie attribute
SESSION_SAME_SITE=lax
Default: lax Options:
  • lax (recommended) - Balances security and compatibility
  • strict - Maximum security, may break OAuth flows
  • none - Not recommended (requires secure=true)

SESSION_ENCRYPT

Purpose: Encrypt session data
SESSION_ENCRYPT=false
Default: false
Encryption adds overhead but provides defense-in-depth. Enable if storing sensitive data in sessions or if compliance requires it.

OAuth Configuration

Google OAuth (Example)

GOOGLE_CLIENT_ID=123456789-abc.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-abc123def456
GOOGLE_REDIRECT_URI=https://your-domain.com/auth/google/callback
OAuth Security Requirements:
  • Keep GOOGLE_CLIENT_SECRET confidential
  • Use separate OAuth apps for dev/staging/production
  • Whitelist only necessary redirect URIs in Google Console
  • Enable domain restrictions in Google OAuth consent screen if possible
  • Monitor OAuth app usage in Google Console
Redirect URI Configuration:
  • Must exactly match the URI registered in Google Cloud Console
  • Must use HTTPS in production
  • Cannot use wildcards
  • Each environment needs its own redirect URI

Application Security

APP_ENV

Purpose: Application environment
APP_ENV=production
Critical: Always set to production in production. This disables debug mode and enables security features.

APP_DEBUG

Purpose: Enable/disable debug mode
APP_DEBUG=false
Must be false in production. Debug mode exposes:
  • Database queries and credentials
  • Application source code paths
  • Environment variables
  • Stack traces with sensitive information

APP_KEY

Purpose: Application encryption key
APP_KEY=base64:abc123def456...
Generated by: php artisan key:generate
Critical Security Key
  • Used for all encryption in Laravel
  • Changing this invalidates existing sessions and encrypted data
  • Never share or commit to version control
  • Back up securely before rotation

APP_URL

Purpose: Application base URL
APP_URL=https://vpn-selfservice.example.com
Production requirements:
  • Must use HTTPS (not HTTP)
  • Should match your actual domain
  • Used for generating OAuth callback URLs and email links
  • Include port if non-standard (e.g., https://example.com:8443)

Production Security Configuration

Minimal Secure Configuration

# Application
APP_NAME="VPN Selfservice"
APP_ENV=production
APP_DEBUG=false
APP_KEY=base64:your-generated-key
APP_URL=https://vpn.example.com

# Database (use strong credentials)
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=netbird_production
DB_USERNAME=netbird_user
DB_PASSWORD=<strong-random-password>

# Session Security
SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_SECURE_COOKIE=true
SESSION_HTTP_ONLY=true
SESSION_SAME_SITE=lax

# OAuth (Production credentials)
GOOGLE_CLIENT_ID=<production-client-id>
GOOGLE_CLIENT_SECRET=<production-client-secret>
GOOGLE_REDIRECT_URI=https://vpn.example.com/auth/google/callback

# NetBird Configuration
NETBIRD_API_URL=https://api.netbird.io
NETBIRD_API_TOKEN=<production-api-token>
NETBIRD_NETWORK_ID=<your-network-id>
[email protected]
NETBIRD_ALLOWED_DOMAIN=example.com  # CRITICAL

# Logging
LOG_CHANNEL=stack
LOG_LEVEL=warning

Configuration Checklist

Before going live:
  • APP_ENV=production
  • APP_DEBUG=false
  • APP_KEY generated and unique
  • APP_URL uses HTTPS
  • NETBIRD_ALLOWED_DOMAIN configured
  • NETBIRD_ADMIN_EMAIL set to trusted user
  • NETBIRD_API_TOKEN is production token
  • SESSION_SECURE_COOKIE=true
  • SESSION_HTTP_ONLY=true
  • Strong database password
  • OAuth production credentials
  • OAuth redirect URI uses HTTPS
  • .env file has proper permissions (600)
  • .env excluded from version control
  • Web server configured for HTTPS
  • Firewall rules configured
  • Database backups enabled
  • Log monitoring configured

Testing Security Configuration

Verify HTTPS Enforcement

# Should redirect to HTTPS
curl -I http://your-domain.com

# Should return 200 OK
curl -I https://your-domain.com

Verify Domain Restriction

  1. Attempt login with non-allowed domain email
  2. Should be rejected with error message
  3. Check error appears at post-OAuth step

Verify Session Security

Inspect session cookie in browser dev tools:
  • Secure flag should be true
  • HttpOnly flag should be true
  • SameSite should be Lax

Verify Admin Access

  1. Login as admin user (matching NETBIRD_ADMIN_EMAIL)
  2. Verify “Pending Approvals” section appears
  3. Verify ability to approve/deny requests
  4. Logout and login as non-admin
  5. Verify approval section is hidden

Troubleshooting

”CSRF token mismatch” errors

Cause: Session configuration issues Solutions:
  • Verify SESSION_DOMAIN matches your actual domain
  • Check SESSION_SECURE_COOKIE is correct for your protocol
  • Clear browser cookies and retry
  • Run php artisan config:clear

OAuth redirect errors

Cause: Mismatch between configured and registered URIs Solutions:
  • Verify GOOGLE_REDIRECT_URI exactly matches Google Console
  • Ensure using HTTPS in production
  • Check for trailing slashes (must match exactly)
  • Verify OAuth app is not in testing mode with limited users

Users bypassing domain restriction

Cause: Users registered before restriction was configured Solution:
-- Remove users not matching allowed domain
DELETE FROM users WHERE email NOT LIKE '%@example.com';
This will permanently delete user data. Back up first and notify affected users.

Next Steps

Overview

Return to security overview

Best Practices

Learn security best practices

Build docs developers (and LLMs) love