Add i18n, branding, user management, health checks, and cleanup for deployment

- Multi-language support (EN/DE) with i18n engine and language files
- Configurable branding (name, subtitle, logo) in Settings
- Global default language and per-user language preference
- User management router with CRUD endpoints
- Customer status sync on start/stop/restart
- Health check fixes: derive status from container state, remove broken wget healthcheck
- Caddy reverse proxy and dashboard env templates for customer stacks
- Updated README with real hardware specs, prerequisites, and new features
- Removed .claude settings (JWT tokens) and build artifacts from tracking
- Updated .gitignore for .claude/ and Windows artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 17:24:05 +01:00
parent c4d68db2f4
commit 41ba835a99
28 changed files with 2550 additions and 661 deletions

36
templates/Caddyfile.j2 Normal file
View File

@@ -0,0 +1,36 @@
{
auto_https off
}
:80 {
# Embedded IdP OAuth2/OIDC endpoints
handle /oauth2/* {
reverse_proxy netbird-kunde{{ customer_id }}-management:80
}
# NetBird Management API + gRPC
handle /api/* {
reverse_proxy netbird-kunde{{ customer_id }}-management:80
}
handle /management.ManagementService/* {
reverse_proxy netbird-kunde{{ customer_id }}-management:80 {
transport http {
versions h2c
}
}
}
# NetBird Signal gRPC
handle /signalexchange.SignalExchange/* {
reverse_proxy netbird-kunde{{ customer_id }}-signal:80 {
transport http {
versions h2c
}
}
}
# Default: NetBird Dashboard
handle {
reverse_proxy netbird-kunde{{ customer_id }}-dashboard:80
}
}

View File

@@ -0,0 +1,13 @@
# NetBird Dashboard - Customer {{ customer_id }}
NETBIRD_MGMT_API_ENDPOINT={{ external_url }}
NETBIRD_MGMT_GRPC_API_ENDPOINT={{ external_url }}
AUTH_AUTHORITY={{ external_url }}/oauth2
AUTH_CLIENT_ID=netbird-dashboard
AUTH_AUDIENCE=netbird-dashboard
AUTH_SUPPORTED_SCOPES=openid profile email groups offline_access
AUTH_REDIRECT_URI=/nb-auth
AUTH_SILENT_REDIRECT_URI=/nb-silent-auth
USE_AUTH0=false
NETBIRD_TOKEN_SOURCE=accessToken
LETSENCRYPT_DOMAIN=none
NGINX_SSL_PORT=443

View File

@@ -1,10 +1,21 @@
version: '3.8'
networks:
{{ docker_network }}:
external: true
services:
# --- Caddy Reverse Proxy (entry point) ---
netbird-caddy:
image: caddy:2-alpine
container_name: netbird-kunde{{ customer_id }}-caddy
restart: unless-stopped
networks:
- {{ docker_network }}
ports:
- "{{ dashboard_port }}:80"
volumes:
- {{ instance_dir }}/Caddyfile:/etc/caddy/Caddyfile:ro
# --- NetBird Management (with embedded IdP) ---
netbird-management:
image: {{ netbird_management_image }}
container_name: netbird-kunde{{ customer_id }}-management
@@ -21,15 +32,11 @@ services:
- "console"
- "--log-level"
- "info"
- "--single-account-mode-domain={{ subdomain }}.{{ base_domain }}"
- "--dns-domain={{ subdomain }}.{{ base_domain }}"
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://localhost:80/api/accounts"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
- "--single-account-mode-domain={{ netbird_domain }}"
- "--dns-domain={{ netbird_domain }}"
- "--idp-sign-key-refresh-enabled"
# --- NetBird Signal ---
netbird-signal:
image: {{ netbird_signal_image }}
container_name: netbird-kunde{{ customer_id }}-signal
@@ -39,6 +46,7 @@ services:
volumes:
- {{ instance_dir }}/data/signal:/var/lib/netbird
# --- NetBird Relay ---
netbird-relay:
image: {{ netbird_relay_image }}
container_name: netbird-kunde{{ customer_id }}-relay
@@ -49,19 +57,13 @@ services:
- "{{ relay_udp_port }}:3478/udp"
env_file:
- {{ instance_dir }}/relay.env
environment:
- NB_ENABLE_STUN=true
- NB_STUN_PORTS=3478
- NB_LISTEN_ADDRESS=:80
- NB_EXPOSED_ADDRESS=rels://{{ subdomain }}.{{ base_domain }}:443
- NB_AUTH_SECRET={{ relay_secret }}
# --- NetBird Dashboard ---
netbird-dashboard:
image: {{ netbird_dashboard_image }}
container_name: netbird-kunde{{ customer_id }}-dashboard
restart: unless-stopped
networks:
- {{ docker_network }}
environment:
- NETBIRD_MGMT_API_ENDPOINT=https://{{ subdomain }}.{{ base_domain }}
- NETBIRD_MGMT_GRPC_API_ENDPOINT=https://{{ subdomain }}.{{ base_domain }}
env_file:
- {{ instance_dir }}/dashboard.env

View File

@@ -2,7 +2,7 @@
"Stuns": [
{
"Proto": "udp",
"URI": "stun:{{ subdomain }}.{{ base_domain }}:{{ relay_udp_port }}",
"URI": "stun:{{ netbird_domain }}:{{ relay_udp_port }}",
"Username": "",
"Password": null
}
@@ -11,7 +11,7 @@
"Turns": [
{
"Proto": "udp",
"URI": "turn:{{ subdomain }}.{{ base_domain }}:{{ relay_udp_port }}",
"URI": "turn:{{ netbird_domain }}:{{ relay_udp_port }}",
"Username": "netbird",
"Password": "{{ relay_secret }}"
}
@@ -22,42 +22,35 @@
},
"Relay": {
"Addresses": [
"rels://{{ subdomain }}.{{ base_domain }}:443"
"rels://{{ netbird_domain }}:443"
],
"CredentialsTTL": "12h",
"CredentialsTTL": "24h",
"Secret": "{{ relay_secret }}"
},
"Signal": {
"Proto": "https",
"URI": "{{ subdomain }}.{{ base_domain }}:443",
"Proto": "{{ netbird_protocol }}",
"URI": "{{ netbird_domain }}:{{ netbird_port }}",
"Username": "",
"Password": null
},
"HttpConfig": {
"AuthIssuer": "https://{{ subdomain }}.{{ base_domain }}",
"AuthAudience": "{{ subdomain }}.{{ base_domain }}",
"OIDCConfigEndpoint": ""
"AuthIssuer": "{{ external_url }}/oauth2",
"AuthAudience": "netbird-dashboard",
"OIDCConfigEndpoint": "{{ external_url }}/oauth2/.well-known/openid-configuration"
},
"IdpManagerConfig": {
"ManagerType": "none"
"EmbeddedIdP": {
"Enabled": true,
"Issuer": "{{ external_url }}/oauth2",
"LocalAddress": "http://127.0.0.1:80",
"DashboardRedirectURIs": [
"{{ external_url }}/nb-auth",
"{{ external_url }}/nb-silent-auth"
],
"CLIRedirectURIs": [
"http://localhost:53000/",
"http://localhost:54000/"
],
"SignKeyRefreshEnabled": true
},
"DeviceAuthorizationFlow": {
"Provider": "none"
},
"PKCEAuthorizationFlow": {
"ProviderConfig": {
"Audience": "{{ subdomain }}.{{ base_domain }}",
"ClientID": "",
"ClientSecret": "",
"Domain": "",
"AuthorizationEndpoint": "",
"TokenEndpoint": "",
"Scope": "openid profile email",
"RedirectURLs": [
"https://{{ subdomain }}.{{ base_domain }}/auth/callback"
],
"UseIDToken": false
}
},
"DataStoreEncryptionKey": "{{ relay_secret }}"
"DataStoreEncryptionKey": "{{ datastore_encryption_key }}"
}