This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Server Configuration

Nebula Commander is configured with environment variables. All backend settings use the prefix NEBULA_COMMANDER_. You can configure everything from the docs below.

  • Environment variables – Full list: database, JWT, OIDC, CORS, session, SMTP, debug. Use this to configure the backend completely.
  • OIDC – Log in with Keycloak or another OIDC provider: issuer URLs (internal vs public), client id/secret, redirect URI, and zero-touch vs manual setup.

Two-tier layout (Docker)

When using Docker:

  • Infrastructure – docker/.env: ports (e.g. frontend, backend, Keycloak), optional JWT_SECRET_FILE path.
  • Backend – docker/env.d/backend: every NEBULA_COMMANDER_* variable. Copy from env.d.example/backend and edit.

See Installation: Docker for the copy steps.

NixOS

services.nebula-commander exposes most of these settings as first-class options, including OIDC, publicUrl, corsOrigins, and sessionHttpsOnly — see Installation: NixOS for the full option table. Anything not yet exposed as an option can still be set by extending the service environment directly with the matching NEBULA_COMMANDER_* variable. A separate services.ncclient module is also available for running the device client declaratively.

1 - Environment Variables

All backend settings use the NEBULA_COMMANDER_ prefix. Set them in the environment or in a file (e.g. docker/env.d/backend). Optional values can be omitted; defaults apply.

Application

VariableDescriptionDefault
NEBULA_COMMANDER_DEBUGEnable debug mode (enables dev-token endpoint; do not use in production)false
NEBULA_COMMANDER_UPDATE_CHECK_ENABLEDCheck GitHub for a newer release, shown as a notification in the About screen. Set to false to disable all outbound calls to github.com (air-gapped/privacy-conscious deployments).true

Database

VariableDescriptionDefault
NEBULA_COMMANDER_DATABASE_URLDatabase URL (SQLite: use four slashes for absolute path, e.g. sqlite+aiosqlite:////var/lib/nebula-commander/db.sqlite)sqlite+aiosqlite:////var/lib/nebula-commander/db.sqlite
NEBULA_COMMANDER_DATABASE_PATHOverride for SQLite path—
NEBULA_COMMANDER_CERT_STORE_PATHDirectory for CA and host certificates/var/lib/nebula-commander/certs

Encryption at rest

Required. The backend refuses to boot if this is left at a placeholder/unset value — unlike most settings here, there’s no insecure-but-working default.

VariableDescriptionDefault
NEBULA_COMMANDER_ENCRYPTION_KEYFernet key used to encrypt certificates and private keys at rest. Generate one with python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())".— (required)
NEBULA_COMMANDER_ENCRYPTION_KEY_FILEPath to a file containing the Fernet key (overrides the plain env var when present). On NixOS this is auto-generated into a oneshot service the first time the module runs.—

JWT

VariableDescriptionDefault
NEBULA_COMMANDER_JWT_SECRET_KEYSecret for signing tokens (generate with e.g. openssl rand -base64 32)change-this-in-production
NEBULA_COMMANDER_JWT_SECRET_FILEPath to file containing JWT secret (overrides secret key when present)—
NEBULA_COMMANDER_JWT_ALGORITHMJWT algorithmHS256
NEBULA_COMMANDER_JWT_EXPIRATION_MINUTESToken expiration in minutes1440 (24 hours)

Public URL and OIDC

VariableDescriptionDefault
NEBULA_COMMANDER_PUBLIC_URLBase URL where users reach the app (FQDN or host:port). Used to derive redirect URI and for redirect validation.—
NEBULA_COMMANDER_STANDALONE_ADMIN_BOOTSTRAPAllow the unauthenticated /api/auth/dev-token admin-bootstrap endpoint when no OIDC provider is configured below. Standalone (no-IdP) deployments must opt in explicitly — this grants unauthenticated system-admin access to anyone who can reach the backend, so only enable it for a genuinely no-IdP deployment. Deployments with OIDC configured are unaffected (always 404).false
NEBULA_COMMANDER_OIDC_ISSUER_URLOIDC issuer URL used by the backend to reach the provider (internal; e.g. http://keycloak:8080/realms/nebula-commander)—
NEBULA_COMMANDER_OIDC_PUBLIC_ISSUER_URLOIDC issuer URL as seen by the browser (FQDN or host:port)—
NEBULA_COMMANDER_OIDC_CLIENT_IDOIDC client ID—
NEBULA_COMMANDER_OIDC_CLIENT_SECRETOIDC client secret—
NEBULA_COMMANDER_OIDC_CLIENT_SECRET_FILEPath to file containing OIDC client secret—
NEBULA_COMMANDER_OIDC_REDIRECT_URICallback URL (optional; derived as PUBLIC_URL + /api/auth/callback when PUBLIC_URL is set)—
NEBULA_COMMANDER_OIDC_SCOPESOIDC scopes (space-separated)openid profile email
NEBULA_COMMANDER_OIDC_ADMIN_ROLE_CLAIMTop-level claim name used to detect the system-admin role (e.g. roles, groups, or an Auth0-style namespaced claim). Leave unset to use Keycloak’s default resource_access.<client_id>.roles shape.—
NEBULA_COMMANDER_OIDC_ADMIN_ROLE_VALUEValue that must appear in the admin-role claim to grant system-adminsystem-admin

CORS and session

VariableDescriptionDefault
NEBULA_COMMANDER_CORS_ORIGINSAllowed CORS origins: * or comma-separated list. Include your public app URL. Using * with credentials is insecure.http://localhost:3000, http://localhost:5173
NEBULA_COMMANDER_SESSION_HTTPS_ONLYSet session cookie to HTTPS-only (use true in production with HTTPS)false
NEBULA_COMMANDER_ALLOWED_REDIRECT_HOSTSAllowed hosts for OAuth/OIDC redirects (comma-separated). When empty and PUBLIC_URL is set, derived from PUBLIC_URL.—

Certificates and device tokens

VariableDescriptionDefault
NEBULA_COMMANDER_DEFAULT_CERT_EXPIRY_DAYSDefault certificate expiry in days365
NEBULA_COMMANDER_DEVICE_TOKEN_EXPIRATION_DAYSDevice token (enrollment) expiry in days365

SMTP (optional)

VariableDescriptionDefault
NEBULA_COMMANDER_SMTP_ENABLEDEnable sending email (e.g. for invitations)false
NEBULA_COMMANDER_SMTP_HOSTSMTP hostlocalhost
NEBULA_COMMANDER_SMTP_PORTSMTP port587
NEBULA_COMMANDER_SMTP_USERNAMESMTP username—
NEBULA_COMMANDER_SMTP_PASSWORDSMTP password—
NEBULA_COMMANDER_SMTP_PASSWORD_FILEPath to file containing SMTP password—
NEBULA_COMMANDER_SMTP_USE_TLSUse TLStrue
NEBULA_COMMANDER_SMTP_FROM_EMAILFrom addressnoreply@example.com
NEBULA_COMMANDER_SMTP_FROM_NAMEFrom nameNebula Commander

Analytics (optional)

Exposed publicly via GET /api/public-config (no auth) so the frontend can inject the corresponding script tags.

VariableDescriptionDefault
NEBULA_COMMANDER_PLAUSIBLE_DOMAINPlausible domain (e.g. example.com); set to enable Plausible analytics—
NEBULA_COMMANDER_PLAUSIBLE_SCRIPT_SRCCustom Plausible script URL (e.g. behind your own proxy), overriding the default script source—
NEBULA_COMMANDER_GA_MEASUREMENT_IDGoogle Analytics measurement ID (e.g. G-XXXXXXXXXX); set to enable GA—
NEBULA_COMMANDER_ANALYTICS_CUSTOM_SCRIPTSJSON array of custom scripts to inject, each {"src": "https://...", "defer": true} or {"inline": "..."}—

Server (advanced)

VariableDescriptionDefault
NEBULA_COMMANDER_HOSTBind host0.0.0.0
NEBULA_COMMANDER_PORTBind port8081

Security notes

  • Generate a strong JWT secret for production (e.g. openssl rand -base64 32). Do not use the default.
  • ENCRYPTION_KEY has no default to leave-unset-and-forget — the backend won’t start without one. Generate it once and keep it: losing it makes every stored certificate/private key unrecoverable.
  • Prefer *_FILE options (JWT, encryption key, OIDC secret, SMTP password) over plain env vars when possible.
  • In production: set DEBUG=false, use HTTPS for PUBLIC_URL and OIDC, and set CORS_ORIGINS to your actual frontend origin(s). For examples of putting Nebula Commander behind Nginx, Traefik, or Caddy with TLS and HSTS, see Reverse Proxy.

2 - OIDC Authentication

Nebula Commander can use OpenID Connect (OIDC) for login. Keycloak is supported with a pre-configured setup; other OIDC providers (Authentik, Auth0, etc.) work with the same environment variables.

Required variables

Set these in env.d/backend (Docker) or in the backend environment:

  • NEBULA_COMMANDER_PUBLIC_URL – URL where users reach the app (FQDN or host:port). The redirect URI is derived as PUBLIC_URL + /api/auth/callback if you do not set OIDC_REDIRECT_URI.
  • NEBULA_COMMANDER_OIDC_ISSUER_URL – Issuer URL used by the backend to talk to the provider. Inside Docker use the container name and container port (e.g. http://keycloak:8080/realms/nebula-commander). Do not use the host-mapped port here.
  • NEBULA_COMMANDER_OIDC_PUBLIC_ISSUER_URL – Issuer URL as seen by the browser (FQDN or host:port). Use the same URL users would use to open the provider’s login page.
  • NEBULA_COMMANDER_OIDC_CLIENT_ID – OIDC client ID (e.g. nebula-commander).
  • NEBULA_COMMANDER_OIDC_CLIENT_SECRET – Client secret from the provider. Prefer NEBULA_COMMANDER_OIDC_CLIENT_SECRET_FILE in production.

Optional: NEBULA_COMMANDER_OIDC_REDIRECT_URI – Override only if you need a callback URL different from PUBLIC_URL + /api/auth/callback.

Keycloak with Docker

  1. Copy example env files and edit env.d/backend (set PUBLIC_URL, OIDC issuer URLs, client id/secret).
  2. Start with Keycloak:
    docker compose -f docker-compose.yml -f docker-compose-keycloak.yml up -d
  3. Create a user in Keycloak Admin and assign client roles under the nebula-commander client: system-admin, network-owner, or user.

Zero-touch Keycloak

The project provides a custom Keycloak image that imports the realm and theme at startup. Build the image (see Installation: Docker and docker/keycloak), set the same OIDC variables in env.d/backend, and start the stack. No manual realm creation is required; create users and assign roles in the Admin console.

Manual Keycloak setup

If you do not use the zero-touch image, create the realm and client in Keycloak:

  • Client type: OpenID Connect, confidential, standard flow.
  • Valid redirect URI: your PUBLIC_URL + /api/auth/callback.
  • Valid post-logout redirect URIs: PUBLIC_URL + /*.
  • Web origins: your PUBLIC_URL.
  • Create client roles: system-admin, network-owner, user. Assign them to users via Role mapping.

Then set the client secret in env.d/backend.

Backend cannot reach Keycloak

The backend talks to Keycloak on the Docker network. Use the container port in NEBULA_COMMANDER_OIDC_ISSUER_URL (e.g. http://keycloak:8080/realms/nebula-commander), not the host-mapped port. Use the host port or FQDN only in NEBULA_COMMANDER_OIDC_PUBLIC_ISSUER_URL and in NEBULA_COMMANDER_PUBLIC_URL.

External OIDC provider

Keycloak is the default, but Nebula Commander’s OIDC integration is fully provider-agnostic: login, logout, and step-up reauth all use standard OIDC discovery (.well-known/openid-configuration) to find the provider’s actual endpoints, rather than assuming Keycloak’s URL conventions. Any standards-compliant provider — Authentik, Auth0, Okta, and others — works with the same environment variables.

Use the same variables as above. In the provider, set redirect URI to PUBLIC_URL + /api/auth/callback, client type Confidential, grant type Authorization Code. Set OIDC_ISSUER_URL and OIDC_PUBLIC_ISSUER_URL to the provider’s issuer URL (often the same).

docker-compose.yml includes the Keycloak stack by default. To use an external provider instead, comment out (or delete) the include: block at the top of docker-compose.yml:

# include:
#   - path: ./docker-compose-keycloak.yml

then docker compose up -d starts only the backend and frontend.

Admin role mapping

Keycloak assigns roles via a client-roles claim shaped like resource_access.<client_id>.roles, which most other providers don’t emit by default. If you’re not using Keycloak, set:

  • NEBULA_COMMANDER_OIDC_ADMIN_ROLE_CLAIM – the top-level claim your provider emits (e.g. roles, groups, or an Auth0-style namespaced claim like https://nebula.example.com/roles).
  • NEBULA_COMMANDER_OIDC_ADMIN_ROLE_VALUE – the value within that claim that grants system-admin (default system-admin).

Leave OIDC_ADMIN_ROLE_CLAIM unset to keep using Keycloak’s default shape — this is the default, so existing Keycloak deployments need no changes.

Roles and permissions

  • system-admin – Manage users; view all networks/nodes with limited data; delete networks/nodes (with reauth); request access grants from owners.
  • network-owner – Create and manage networks, nodes, invitations, node requests, and access; set default node parameters and auto-approval.
  • user – Access only what network owners grant; request nodes and higher access.

See the repository docker/README for detailed RBAC and permission features.