#!/bin/bash set -e # NetBird Getting Started with Embedded IdP (Dex) # This script sets up NetBird with the embedded Dex identity provider # No separate Dex container or reverse proxy needed - IdP is built into management server # Sed pattern to strip base64 padding characters SED_STRIP_PADDING='s/=//g' check_docker_compose() { if command -v docker-compose &> /dev/null then echo "docker-compose" return fi if docker compose --help &> /dev/null then echo "docker compose" return fi echo "docker-compose is not installed or not in PATH. Please follow the steps from the official guide: https://docs.docker.com/engine/install/" > /dev/stderr exit 1 } check_jq() { if ! command -v jq &> /dev/null then echo "jq is not installed or not in PATH, please install with your package manager. e.g. sudo apt install jq" > /dev/stderr exit 1 fi return 0 } get_main_ip_address() { if [[ "$OSTYPE" == "darwin"* ]]; then interface=$(route -n get default | grep 'interface:' | awk '{print $2}') ip_address=$(ifconfig "$interface" | grep 'inet ' | awk '{print $2}') else interface=$(ip route | grep default | awk '{print $5}' | head -n 1) ip_address=$(ip addr show "$interface" | grep 'inet ' | awk '{print $2}' | cut -d'/' -f1) fi echo "$ip_address" return 0 } check_nb_domain() { DOMAIN=$1 if [[ "$DOMAIN-x" == "-x" ]]; then echo "The NETBIRD_DOMAIN variable cannot be empty." > /dev/stderr return 1 fi if [[ "$DOMAIN" == "netbird.example.com" ]]; then echo "The NETBIRD_DOMAIN cannot be netbird.example.com" > /dev/stderr return 1 fi return 0 } read_nb_domain() { READ_NETBIRD_DOMAIN="" echo -n "Enter the domain you want to use for NetBird (e.g. netbird.my-domain.com): " > /dev/stderr read -r READ_NETBIRD_DOMAIN < /dev/tty if ! check_nb_domain "$READ_NETBIRD_DOMAIN"; then read_nb_domain fi echo "$READ_NETBIRD_DOMAIN" return 0 } get_turn_external_ip() { TURN_EXTERNAL_IP_CONFIG="#external-ip=" IP=$(curl -s -4 https://jsonip.com | jq -r '.ip') if [[ "x-$IP" != "x-" ]]; then TURN_EXTERNAL_IP_CONFIG="external-ip=$IP" fi echo "$TURN_EXTERNAL_IP_CONFIG" return 0 } wait_management() { set +e echo -n "Waiting for Management server to become ready" counter=1 while true; do # Check the embedded IdP endpoint if curl -sk -f -o /dev/null "$NETBIRD_HTTP_PROTOCOL://$NETBIRD_DOMAIN/oauth2/.well-known/openid-configuration" 2>/dev/null; then break fi if [[ $counter -eq 60 ]]; then echo "" echo "Taking too long. Checking logs..." $DOCKER_COMPOSE_COMMAND logs --tail=20 caddy $DOCKER_COMPOSE_COMMAND logs --tail=20 management fi echo -n " ." sleep 2 counter=$((counter + 1)) done echo " done" set -e return 0 } init_environment() { CADDY_SECURE_DOMAIN="" NETBIRD_PORT=80 NETBIRD_HTTP_PROTOCOL="http" NETBIRD_RELAY_PROTO="rel" TURN_USER="self" TURN_PASSWORD=$(openssl rand -base64 32 | sed "$SED_STRIP_PADDING") NETBIRD_RELAY_AUTH_SECRET=$(openssl rand -base64 32 | sed "$SED_STRIP_PADDING") # Note: DataStoreEncryptionKey must keep base64 padding (=) for Go's base64.StdEncoding DATASTORE_ENCRYPTION_KEY=$(openssl rand -base64 32) TURN_MIN_PORT=49152 TURN_MAX_PORT=65535 TURN_EXTERNAL_IP_CONFIG=$(get_turn_external_ip) if ! check_nb_domain "$NETBIRD_DOMAIN"; then NETBIRD_DOMAIN=$(read_nb_domain) fi if [[ "$NETBIRD_DOMAIN" == "use-ip" ]]; then NETBIRD_DOMAIN=$(get_main_ip_address) else NETBIRD_PORT=443 CADDY_SECURE_DOMAIN=", $NETBIRD_DOMAIN:$NETBIRD_PORT" NETBIRD_HTTP_PROTOCOL="https" NETBIRD_RELAY_PROTO="rels" fi check_jq DOCKER_COMPOSE_COMMAND=$(check_docker_compose) if [[ -f management.json ]]; then echo "Generated files already exist, if you want to reinitialize the environment, please remove them first." echo "You can use the following commands:" echo " $DOCKER_COMPOSE_COMMAND down --volumes # to remove all containers and volumes" echo " rm -f docker-compose.yml Caddyfile dashboard.env turnserver.conf management.json relay.env" echo "Be aware that this will remove all data from the database, and you will have to reconfigure the dashboard." exit 1 fi echo Rendering initial files... render_docker_compose > docker-compose.yml render_caddyfile > Caddyfile render_dashboard_env > dashboard.env render_management_json > management.json render_turn_server_conf > turnserver.conf render_relay_env > relay.env echo -e "\nStarting NetBird services\n" $DOCKER_COMPOSE_COMMAND up -d # Wait for management (and embedded IdP) to be ready sleep 3 wait_management echo -e "\nDone!\n" echo "You can access the NetBird dashboard at $NETBIRD_HTTP_PROTOCOL://$NETBIRD_DOMAIN" echo "Follow the onboarding steps to set up your NetBird instance." return 0 } render_caddyfile() { cat <