Add NetBird server add-on

This commit is contained in:
Alexandre
2026-02-06 12:26:42 +01:00
parent 7cdb4b478a
commit 8c515797ed
12 changed files with 667 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# ==============================================================================
# Home Assistant Add-on: NetBird Server
# Configures NetBird services
# ==============================================================================
create_or_load_secret() {
local secret_file="$1"
local provided_value="$2"
local generated=""
if [[ -n "$provided_value" ]]; then
echo "$provided_value"
return
fi
if [[ -f "$secret_file" ]]; then
cat "$secret_file"
return
fi
generated=$(LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -c 32)
echo "$generated" > "$secret_file"
chmod 600 "$secret_file"
echo "$generated"
}
extract_port() {
local address="$1"
echo "${address##*:}"
}
DATA_DIR=$(bashio::config 'data_dir')
DOMAIN=$(bashio::config 'domain')
EXTERNAL_BASE_URL=$(bashio::config 'external_base_url')
MANAGEMENT_LISTEN=$(bashio::config 'management_listen')
SIGNAL_LISTEN=$(bashio::config 'signal_listen')
DASHBOARD_LISTEN=$(bashio::config 'dashboard_listen')
TURN_LISTEN_PORT=$(bashio::config 'turn_listen_port')
TURN_REALM=$(bashio::config 'turn_realm')
TURN_EXTERNAL_IP=$(bashio::config 'turn_external_ip')
TURN_MIN_PORT=$(bashio::config 'turn_min_port')
TURN_MAX_PORT=$(bashio::config 'turn_max_port')
TURN_USER=$(bashio::config 'turn_user')
TURN_PASSWORD=$(bashio::config 'turn_password')
IDP_MANAGER_TYPE=$(bashio::config 'idp_manager_type')
AUTH_AUTHORITY=$(bashio::config 'auth_authority')
AUTH_AUDIENCE=$(bashio::config 'auth_audience')
AUTH_JWT_CERTS=$(bashio::config 'auth_jwt_certs')
AUTH_USER_ID_CLAIM=$(bashio::config 'auth_user_id_claim')
AUTH_OIDC_CONFIGURATION_ENDPOINT=$(bashio::config 'auth_oidc_configuration_endpoint')
AUTH_TOKEN_ENDPOINT=$(bashio::config 'auth_token_endpoint')
IDP_CLIENT_ID=$(bashio::config 'idp_client_id')
IDP_CLIENT_SECRET=$(bashio::config 'idp_client_secret')
DISABLE_DEFAULT_POLICY=$(bashio::config 'disable_default_policy')
DISABLE_DASHBOARD=$(bashio::config 'disable_dashboard')
ENABLE_RELAY=$(bashio::config 'enable_relay')
RELAY_EXPOSED_ADDRESS=$(bashio::config 'relay_exposed_address')
RELAY_AUTH_SECRET=$(bashio::config 'relay_auth_secret')
MANAGEMENT_PORT=$(extract_port "$MANAGEMENT_LISTEN")
SIGNAL_PORT=$(extract_port "$SIGNAL_LISTEN")
DASHBOARD_PORT=$(extract_port "$DASHBOARD_LISTEN")
if [[ -z "$DOMAIN" ]]; then
DOMAIN="localhost"
bashio::log.warning "domain is empty; defaulting to localhost in generated configs."
fi
if [[ -z "$AUTH_AUTHORITY" || -z "$AUTH_AUDIENCE" || -z "$AUTH_JWT_CERTS" ]]; then
bashio::log.warning "OIDC configuration is incomplete. Update auth_* options or edit ${DATA_DIR}/management/management.json."
fi
mkdir -p "$DATA_DIR" \
"$DATA_DIR/management" \
"$DATA_DIR/turn" \
"$DATA_DIR/secrets" \
"$DATA_DIR/dashboard" \
"$DATA_DIR/relay"
TURN_PASSWORD=$(create_or_load_secret "$DATA_DIR/secrets/turn_password" "$TURN_PASSWORD")
TURN_SECRET=$(create_or_load_secret "$DATA_DIR/secrets/turn_secret" "")
DATASTORE_ENC_KEY=$(create_or_load_secret "$DATA_DIR/secrets/management_datastore_key" "")
if [[ "$ENABLE_RELAY" == "true" ]]; then
if [[ -z "$RELAY_EXPOSED_ADDRESS" || -z "$RELAY_AUTH_SECRET" ]]; then
bashio::log.error "Relay is enabled, but relay_exposed_address or relay_auth_secret is missing."
bashio::exit.nok
fi
rm -f /etc/services.d/relay/down
RELAY_JSON=$(cat <<RELAY
{
"Addresses": ["${RELAY_EXPOSED_ADDRESS}"],
"CredentialsTTL": "24h",
"Secret": "${RELAY_AUTH_SECRET}"
}
RELAY
)
else
bashio::log.info "Relay service disabled."
touch /etc/services.d/relay/down
RELAY_JSON="null"
fi
if [[ "$DISABLE_DASHBOARD" == "true" ]]; then
bashio::log.info "Dashboard service disabled."
touch /etc/services.d/dashboard/down
else
rm -f /etc/services.d/dashboard/down
fi
# Generate management config if missing
MANAGEMENT_CONFIG="$DATA_DIR/management/management.json"
if [[ ! -f "$MANAGEMENT_CONFIG" ]]; then
bashio::log.info "Generating management config at ${MANAGEMENT_CONFIG}."
cat <<CONFIG > "$MANAGEMENT_CONFIG"
{
"Stuns": [
{
"Proto": "udp",
"URI": "stun:${DOMAIN}:${TURN_LISTEN_PORT}",
"Username": "",
"Password": null
}
],
"TURNConfig": {
"Turns": [
{
"Proto": "udp",
"URI": "turn:${DOMAIN}:${TURN_LISTEN_PORT}",
"Username": "${TURN_USER}",
"Password": "${TURN_PASSWORD}"
}
],
"CredentialsTTL": "12h",
"Secret": "${TURN_SECRET}",
"TimeBasedCredentials": false
},
"Relay": ${RELAY_JSON},
"Signal": {
"Proto": "http",
"URI": "${DOMAIN}:${SIGNAL_PORT}",
"Username": "",
"Password": null
},
"ReverseProxy": {
"TrustedHTTPProxies": [],
"TrustedHTTPProxiesCount": 0,
"TrustedPeers": [
"0.0.0.0/0"
]
},
"DisableDefaultPolicy": ${DISABLE_DEFAULT_POLICY},
"Datadir": "${DATA_DIR}/management",
"DataStoreEncryptionKey": "${DATASTORE_ENC_KEY}",
"StoreConfig": {
"Engine": "sqlite"
},
"HttpConfig": {
"Address": "${MANAGEMENT_LISTEN}",
"AuthIssuer": "${AUTH_AUTHORITY}",
"AuthAudience": "${AUTH_AUDIENCE}",
"AuthKeysLocation": "${AUTH_JWT_CERTS}",
"AuthUserIDClaim": "${AUTH_USER_ID_CLAIM}",
"CertFile": "",
"CertKey": "",
"IdpSignKeyRefreshEnabled": false,
"OIDCConfigEndpoint": "${AUTH_OIDC_CONFIGURATION_ENDPOINT}"
},
"IdpManagerConfig": {
"ManagerType": "${IDP_MANAGER_TYPE}",
"ClientConfig": {
"Issuer": "${AUTH_AUTHORITY}",
"TokenEndpoint": "${AUTH_TOKEN_ENDPOINT}",
"ClientID": "${IDP_CLIENT_ID}",
"ClientSecret": "${IDP_CLIENT_SECRET}",
"GrantType": "client_credentials"
},
"ExtraConfig": {}
}
}
CONFIG
else
bashio::log.info "Using existing management config at ${MANAGEMENT_CONFIG}."
fi
# Generate Coturn config
TURN_CONFIG="$DATA_DIR/turn/turnserver.conf"
TURN_EXTERNAL_IP_LINE=""
if [[ -n "$TURN_EXTERNAL_IP" ]]; then
TURN_EXTERNAL_IP_LINE="external-ip=${TURN_EXTERNAL_IP}"
fi
cat <<CONFIG > "$TURN_CONFIG"
listening-port=${TURN_LISTEN_PORT}
realm=${TURN_REALM}
fingerprint
lt-cred-mech
user=${TURN_USER}:${TURN_PASSWORD}
${TURN_EXTERNAL_IP_LINE}
min-port=${TURN_MIN_PORT}
max-port=${TURN_MAX_PORT}
CONFIG
# Generate dashboard nginx config
sed "s/__DASHBOARD_PORT__/${DASHBOARD_PORT}/g" \
/usr/local/share/netbird-dashboard/default.conf.tmpl \
> /etc/nginx/http.d/default.conf
mkdir -p /run/nginx
chmod +x /usr/local/bin/init_react_envs.sh

View File

@@ -0,0 +1,18 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /dev/stdout;
error_log /dev/stderr warn;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/http.d/*.conf;
}

View File

@@ -0,0 +1,19 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# ==============================================================================
# Home Assistant Add-on: NetBird Server
# Runs Coturn
# ==============================================================================
DATA_DIR=$(bashio::config 'data_dir')
TURN_CONFIG="$DATA_DIR/turn/turnserver.conf"
if [[ ! -f "$TURN_CONFIG" ]]; then
bashio::log.error "Missing Coturn configuration at ${TURN_CONFIG}."
bashio::exit.nok
fi
bashio::log.info "Starting Coturn..."
exec /usr/local/bin/turnserver -c "$TURN_CONFIG" --log-file stdout

View File

@@ -0,0 +1,43 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# ==============================================================================
# Home Assistant Add-on: NetBird Server
# Runs the NetBird Dashboard
# ==============================================================================
DOMAIN=$(bashio::config 'domain')
EXTERNAL_BASE_URL=$(bashio::config 'external_base_url')
MANAGEMENT_LISTEN=$(bashio::config 'management_listen')
AUTH_AUTHORITY=$(bashio::config 'auth_authority')
AUTH_CLIENT_ID=$(bashio::config 'auth_client_id')
AUTH_CLIENT_SECRET=$(bashio::config 'auth_client_secret')
AUTH_AUDIENCE=$(bashio::config 'auth_audience')
AUTH_SUPPORTED_SCOPES=$(bashio::config 'auth_supported_scopes')
USE_AUTH0=$(bashio::config 'use_auth0')
MANAGEMENT_PORT="${MANAGEMENT_LISTEN##*:}"
if [[ -n "$EXTERNAL_BASE_URL" ]]; then
NETBIRD_MGMT_API_ENDPOINT="$EXTERNAL_BASE_URL"
elif [[ -n "$DOMAIN" ]]; then
NETBIRD_MGMT_API_ENDPOINT="http://${DOMAIN}:${MANAGEMENT_PORT}"
else
bashio::log.warning "external_base_url and domain are empty; defaulting NETBIRD_MGMT_API_ENDPOINT to localhost."
NETBIRD_MGMT_API_ENDPOINT="http://127.0.0.1:${MANAGEMENT_PORT}"
fi
export AUTH_AUTHORITY
export AUTH_CLIENT_ID
export AUTH_CLIENT_SECRET
export AUTH_AUDIENCE
export AUTH_SUPPORTED_SCOPES
export USE_AUTH0
export NETBIRD_MGMT_API_ENDPOINT
bashio::log.info "Preparing NetBird Dashboard assets..."
/usr/local/bin/init_react_envs.sh
bashio::log.info "Starting NetBird Dashboard..."
exec nginx -g "daemon off;"

View File

@@ -0,0 +1,23 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# ==============================================================================
# Home Assistant Add-on: NetBird Server
# Runs the NetBird Management service
# ==============================================================================
DATA_DIR=$(bashio::config 'data_dir')
LOG_LEVEL=$(bashio::config 'log_level')
MANAGEMENT_CONFIG="$DATA_DIR/management/management.json"
if [[ ! -f "$MANAGEMENT_CONFIG" ]]; then
bashio::log.error "Missing management configuration at ${MANAGEMENT_CONFIG}."
bashio::exit.nok
fi
bashio::log.info "Starting NetBird Management..."
exec /usr/local/bin/netbird-mgmt management \
--config "$MANAGEMENT_CONFIG" \
--log-level "$LOG_LEVEL" \
--log-file console

View File

@@ -0,0 +1,20 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# ==============================================================================
# Home Assistant Add-on: NetBird Server
# Runs the NetBird Relay (optional)
# ==============================================================================
LOG_LEVEL=$(bashio::config 'log_level')
RELAY_EXPOSED_ADDRESS=$(bashio::config 'relay_exposed_address')
RELAY_AUTH_SECRET=$(bashio::config 'relay_auth_secret')
bashio::log.info "Starting NetBird Relay..."
exec /usr/local/bin/netbird-relay \
--listen-address ":33080" \
--exposed-address "$RELAY_EXPOSED_ADDRESS" \
--auth-secret "$RELAY_AUTH_SECRET" \
--log-level "$LOG_LEVEL" \
--log-file console

View File

@@ -0,0 +1,18 @@
#!/usr/bin/with-contenv bashio
# shellcheck shell=bash
set -euo pipefail
# ==============================================================================
# Home Assistant Add-on: NetBird Server
# Runs the NetBird Signal service
# ==============================================================================
SIGNAL_LISTEN=$(bashio::config 'signal_listen')
LOG_LEVEL=$(bashio::config 'log_level')
SIGNAL_PORT="${SIGNAL_LISTEN##*:}"
bashio::log.info "Starting NetBird Signal on port ${SIGNAL_PORT}..."
exec /usr/local/bin/netbird-signal run \
--port "$SIGNAL_PORT" \
--log-level "$LOG_LEVEL" \
--log-file console

View File

@@ -0,0 +1,27 @@
server {
listen __DASHBOARD_PORT__ default_server;
listen [::]:__DASHBOARD_PORT__ default_server;
root /usr/share/nginx/html;
location = /netbird.wasm {
root /usr/share/nginx/html;
default_type application/wasm;
}
location = /ironrdp-pkg/ironrdp_web_bg.wasm {
root /usr/share/nginx/html;
default_type application/wasm;
}
location / {
try_files $uri $uri.html $uri/ =404;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
expires off;
}
error_page 404 /404.html;
location = /404.html {
internal;
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
expires off;
}
}