mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-28 17:49:08 +02:00
[infrastructure] Add proxy support to enterprise setup (#7651)
This commit is contained in:
@@ -6,11 +6,19 @@ set -o pipefail
|
||||
# NetBird Enterprise — Getting Started
|
||||
# Single-node bootstrap for a self-hosted NetBird Enterprise stack with the
|
||||
# embedded identity provider. Owner is created via first-login flow.
|
||||
# Add features to an existing install with --enable-proxy or --enable-traffic-events.
|
||||
|
||||
SED_STRIP_PADDING='s/=//g'
|
||||
|
||||
NETBIRD_EULA_URL="https://netbird.io/self-hosted-EULA"
|
||||
|
||||
STACK_FILES=(.env docker-compose.yml config.yaml)
|
||||
|
||||
# Host directory of a custom TLS certificate mounted at /certs, see
|
||||
# https://docs.netbird.io/selfhosted/enterprise/getting-started#appendix-using-a-custom-tls-certificate
|
||||
CUSTOM_TLS_CERTS=""
|
||||
PROXY_TOKEN_ID=""
|
||||
|
||||
# Static IP for Traefik inside the compose bridge network. The management
|
||||
# server trusts X-Forwarded-* headers from this address only.
|
||||
TRAEFIK_IP="172.30.0.10"
|
||||
@@ -44,6 +52,28 @@ check_openssl() {
|
||||
fi
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "$1" > /dev/stderr
|
||||
exit 1
|
||||
}
|
||||
|
||||
# env_get KEY [DEFAULT] prints KEY's value from .env, or DEFAULT if unset.
|
||||
env_get() {
|
||||
local value
|
||||
value=$(sed -n "s/^$1=//p" .env | tail -n 1)
|
||||
echo "${value:-$2}"
|
||||
}
|
||||
|
||||
# merge_env upserts the KEY=VALUE lines from stdin into .env, in place.
|
||||
merge_env() {
|
||||
local merged
|
||||
merged=$(awk -F= 'NR == FNR { v[$1] = $0; o[++n] = $1; next }
|
||||
$1 in v { print v[$1]; delete v[$1]; next }
|
||||
{ print }
|
||||
END { for (i = 1; i <= n; i++) if (o[i] in v) print v[o[i]] }' - .env)
|
||||
printf '%s\n' "$merged" > .env
|
||||
}
|
||||
|
||||
rand_secret() {
|
||||
openssl rand -base64 32 | sed "$SED_STRIP_PADDING"
|
||||
}
|
||||
@@ -171,6 +201,15 @@ read_yes_no() {
|
||||
esac
|
||||
}
|
||||
|
||||
read_crowdsec_option() {
|
||||
echo ""
|
||||
echo "CrowdSec:"
|
||||
echo " Checks client IPs against a community threat intelligence database and"
|
||||
echo " blocks known malicious sources before they reach services exposed through"
|
||||
echo " the proxy. Adds a CrowdSec container to the stack."
|
||||
NETBIRD_CROWDSEC=$(read_yes_no "Enable CrowdSec" "n")
|
||||
}
|
||||
|
||||
# Gate the install on explicit acceptance of the NetBird On-Premise EULA.
|
||||
require_eula_acceptance() {
|
||||
cat > /dev/stderr <<EOF
|
||||
@@ -314,15 +353,100 @@ report_license_verdict() {
|
||||
return 0
|
||||
}
|
||||
|
||||
# up_all_but_proxy skips the proxy, which needs a token from the running server.
|
||||
up_all_but_proxy() {
|
||||
local services
|
||||
services=$($DOCKER_COMPOSE_COMMAND config --services | grep -vx proxy)
|
||||
# shellcheck disable=SC2086
|
||||
$DOCKER_COMPOSE_COMMAND up -d $services
|
||||
}
|
||||
|
||||
wait_crowdsec() {
|
||||
$DOCKER_COMPOSE_COMMAND up -d crowdsec || return 1
|
||||
for _ in {1..60}; do
|
||||
$DOCKER_COMPOSE_COMMAND exec -T crowdsec cscli lapi status &> /dev/null && return 0
|
||||
sleep 2
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
admin_token() {
|
||||
$DOCKER_COMPOSE_COMMAND run --rm --no-deps -T netbird-server admin token "$@" --config /etc/netbird/config.yaml
|
||||
}
|
||||
|
||||
# revoke_proxy_token revokes the token this run minted if the proxy never started.
|
||||
# On failure the ID is kept, so rollback retries it.
|
||||
revoke_proxy_token() {
|
||||
[[ -n "$PROXY_TOKEN_ID" ]] || return 0
|
||||
if admin_token revoke "$PROXY_TOKEN_ID" > /dev/null; then
|
||||
PROXY_TOKEN_ID=""
|
||||
return 0
|
||||
fi
|
||||
echo "Could not revoke the unused proxy token ${PROXY_TOKEN_ID}. Revoke it with:" > /dev/stderr
|
||||
echo " $DOCKER_COMPOSE_COMMAND run --rm netbird-server admin token revoke ${PROXY_TOKEN_ID} --config /etc/netbird/config.yaml" > /dev/stderr
|
||||
}
|
||||
|
||||
# start_proxy mints the proxy token and CrowdSec bouncer key, then starts the proxy.
|
||||
start_proxy() {
|
||||
local out token key
|
||||
echo "Creating the proxy access token ..."
|
||||
out=$(admin_token create --name default-proxy) || true
|
||||
token=$(awk '/^Token:/ {print $2}' <<< "$out")
|
||||
PROXY_TOKEN_ID=$(awk '/^Token ID:/ {print $3}' <<< "$out")
|
||||
[[ -n "$token" ]] || die "Could not create the proxy access token. Check the netbird-server logs, then re-run with --enable-proxy."
|
||||
|
||||
if [[ "$NETBIRD_CROWDSEC" == "yes" ]]; then
|
||||
echo "Registering the CrowdSec bouncer ..."
|
||||
if wait_crowdsec; then
|
||||
# "add" fails if an earlier attempt already registered the bouncer.
|
||||
$DOCKER_COMPOSE_COMMAND exec -T crowdsec cscli bouncers delete netbird-proxy &> /dev/null || true
|
||||
key=$($DOCKER_COMPOSE_COMMAND exec -T crowdsec cscli bouncers add netbird-proxy -o raw) || true
|
||||
fi
|
||||
if [[ -z "$key" ]]; then
|
||||
revoke_proxy_token
|
||||
die "Could not register the CrowdSec bouncer. Check the crowdsec logs, then re-run with --enable-proxy."
|
||||
fi
|
||||
fi
|
||||
|
||||
# A stored token marks the proxy as set up, so it is cleared again on failure.
|
||||
{
|
||||
echo "NETBIRD_PROXY_TOKEN=${token}"
|
||||
if [[ -n "$key" ]]; then echo "NETBIRD_CROWDSEC_BOUNCER_KEY=${key}"; fi
|
||||
} | merge_env
|
||||
if ! $DOCKER_COMPOSE_COMMAND up -d proxy; then
|
||||
revoke_proxy_token
|
||||
echo "NETBIRD_PROXY_TOKEN=" | merge_env
|
||||
die "Could not start the proxy. Check the proxy logs, then re-run with --enable-proxy."
|
||||
fi
|
||||
PROXY_TOKEN_ID=""
|
||||
}
|
||||
|
||||
print_proxy_notes() {
|
||||
echo ""
|
||||
echo "NetBird Proxy:"
|
||||
echo " Every domain other than ${NETBIRD_DOMAIN} is passed through to the proxy,"
|
||||
echo " which issues its own TLS certificates. Point proxy domains at this host:"
|
||||
echo ""
|
||||
echo " *.${NETBIRD_DOMAIN} CNAME ${NETBIRD_DOMAIN}"
|
||||
echo ""
|
||||
echo " Open 51820/udp (optional) for peer-to-peer proxy connections."
|
||||
if [[ "$NETBIRD_CROWDSEC" == "yes" ]]; then
|
||||
echo " CrowdSec is running. Enable it per service in the dashboard under Access Control."
|
||||
fi
|
||||
}
|
||||
|
||||
init_environment() {
|
||||
check_openssl
|
||||
DOCKER_COMPOSE_COMMAND=$(check_docker_compose)
|
||||
|
||||
if [[ -f .env ]] || [[ -f docker-compose.yml ]] || [[ -f config.yaml ]]; then
|
||||
echo "Generated files already exist in $(pwd)."
|
||||
echo "To add the proxy or traffic events to this installation, re-run with"
|
||||
echo "--enable-proxy or --enable-traffic-events."
|
||||
echo ""
|
||||
echo "If you want to reinitialize the environment, please remove them first:"
|
||||
echo " $DOCKER_COMPOSE_COMMAND down --volumes # removes all containers and volumes"
|
||||
echo " rm -f .env docker-compose.yml config.yaml"
|
||||
echo " rm -rf .env docker-compose.yml config.yaml traefik"
|
||||
echo "Be aware this will remove all data from the database."
|
||||
exit 1
|
||||
fi
|
||||
@@ -341,6 +465,16 @@ init_environment() {
|
||||
echo " See https://docs.netbird.io/manage/activity/traffic-events-logging"
|
||||
NETBIRD_TRAFFIC_FLOW=$(read_yes_no "Enable traffic flow" "n")
|
||||
|
||||
echo ""
|
||||
echo "NetBird Proxy:"
|
||||
echo " Exposes selected resources from your NetBird network to the internet."
|
||||
echo " You choose which resources are exposed from the dashboard."
|
||||
NETBIRD_PROXY=$(read_yes_no "Enable the NetBird Proxy" "n")
|
||||
NETBIRD_CROWDSEC="no"
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
read_crowdsec_option
|
||||
fi
|
||||
|
||||
echo ""
|
||||
NETBIRD_DOMAIN=$(read_nb_domain)
|
||||
|
||||
@@ -364,6 +498,8 @@ init_environment() {
|
||||
echo ""
|
||||
echo "Selected:"
|
||||
echo " Traffic flow: ${NETBIRD_TRAFFIC_FLOW}"
|
||||
echo " Proxy: ${NETBIRD_PROXY}"
|
||||
echo " CrowdSec: ${NETBIRD_CROWDSEC}"
|
||||
echo " Domain: ${NETBIRD_DOMAIN}"
|
||||
echo " ACME email: ${NETBIRD_LETSENCRYPT_EMAIL}"
|
||||
echo ""
|
||||
@@ -371,9 +507,9 @@ init_environment() {
|
||||
install -m 600 /dev/null .env
|
||||
render_env >> .env
|
||||
render_docker_compose > docker-compose.yml
|
||||
|
||||
if [[ -z "${NETBIRD_LICENSE_SERVER_BASE_URL:-}" ]]; then
|
||||
sed -i.bak '/NETBIRD_LICENSE_SERVER_BASE_URL/d' docker-compose.yml && rm -f docker-compose.yml.bak
|
||||
mkdir -p traefik
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
render_traefik_proxy > traefik/proxy.yaml
|
||||
fi
|
||||
install -m 600 /dev/null config.yaml
|
||||
render_config_yaml >> config.yaml
|
||||
@@ -390,11 +526,16 @@ init_environment() {
|
||||
|
||||
echo ""
|
||||
echo "Starting remaining services ..."
|
||||
$DOCKER_COMPOSE_COMMAND up -d
|
||||
up_all_but_proxy
|
||||
|
||||
echo ""
|
||||
wait_for_license_verdict
|
||||
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
echo ""
|
||||
start_proxy
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Done."
|
||||
echo ""
|
||||
@@ -402,6 +543,9 @@ init_environment() {
|
||||
echo ""
|
||||
echo "Open the dashboard in a browser to complete the first-login owner setup."
|
||||
echo "All configuration and secrets are stored (mode 600) in $(pwd)/.env"
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
print_proxy_notes
|
||||
fi
|
||||
echo ""
|
||||
echo "Tail logs:"
|
||||
echo " cd $(pwd) && $DOCKER_COMPOSE_COMMAND logs -f netbird-server traefik"
|
||||
@@ -413,6 +557,148 @@ init_environment() {
|
||||
fi
|
||||
}
|
||||
|
||||
# service_block NAME prints a service's definition from the compose file on stdin.
|
||||
service_block() {
|
||||
local name="$1"
|
||||
awk -v s=" ${name}:" '$0 == s { p = 1; print; next } p && (/^[^ ]/ || /^ [^ ]/) { exit } p'
|
||||
}
|
||||
|
||||
# enable_features adds the proxy and/or traffic events to the install in the
|
||||
# current directory, restoring the backed-up files if any step fails.
|
||||
enable_features() {
|
||||
local want_proxy="$1" want_flow="$2" f compose
|
||||
DOCKER_COMPOSE_COMMAND=$(check_docker_compose)
|
||||
|
||||
for f in "${STACK_FILES[@]}"; do
|
||||
[[ -f "$f" ]] || die "$f not found in $(pwd). Run this from an existing installation directory."
|
||||
done
|
||||
grep -q '^# Generated by getting-started-enterprise.sh' .env || die ".env was not generated by getting-started-enterprise.sh."
|
||||
# Installs from before the move to Traefik run Caddy and can't be re-rendered.
|
||||
[[ -n "$(env_get NETBIRD_TRAEFIK_IP)" ]] || die "This installation predates the Traefik layout and can't be updated in place."
|
||||
|
||||
NETBIRD_DOMAIN=$(env_get NETBIRD_DOMAIN)
|
||||
NETBIRD_LICENSE_SERVER_BASE_URL=$(env_get NETBIRD_LICENSE_SERVER_BASE_URL)
|
||||
NETBIRD_TRAFFIC_FLOW=$(env_get NETBIRD_TRAFFIC_FLOW_ENABLED no)
|
||||
NETBIRD_PROXY=$(env_get NETBIRD_PROXY_ENABLED no)
|
||||
NETBIRD_CROWDSEC=$(env_get NETBIRD_CROWDSEC_ENABLED no)
|
||||
# A custom certificate counts only once Traefik mounts it and ACME is already gone,
|
||||
# so the re-render never removes a working Let's Encrypt setup.
|
||||
local traefik_block
|
||||
traefik_block=$(service_block traefik < docker-compose.yml)
|
||||
if ! grep -q certificatesresolvers <<< "$traefik_block"; then
|
||||
CUSTOM_TLS_CERTS=$(awk '/:\/certs:ro$/ { sub(/^ *- /, ""); sub(/:\/certs:ro$/, ""); print; exit }' <<< "$traefik_block")
|
||||
fi
|
||||
|
||||
if [[ "$want_flow" == "yes" && "$NETBIRD_TRAFFIC_FLOW" == "yes" ]]; then
|
||||
echo "Traffic events are already enabled."
|
||||
want_flow="no"
|
||||
fi
|
||||
# No token means an earlier proxy setup failed, so let it run again.
|
||||
if [[ "$want_proxy" == "yes" && -n "$(env_get NETBIRD_PROXY_TOKEN)" ]]; then
|
||||
echo "The NetBird Proxy is already enabled."
|
||||
want_proxy="no"
|
||||
fi
|
||||
if [[ "$want_flow" == "no" && "$want_proxy" == "no" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$want_flow" == "yes" ]]; then
|
||||
NETBIRD_TRAFFIC_FLOW="yes"
|
||||
fi
|
||||
# A retry keeps the CrowdSec choice made at install time.
|
||||
if [[ "$want_proxy" == "yes" && "$NETBIRD_PROXY" != "yes" ]]; then
|
||||
read_crowdsec_option
|
||||
fi
|
||||
if [[ "$want_proxy" == "yes" ]]; then
|
||||
NETBIRD_PROXY="yes"
|
||||
fi
|
||||
|
||||
compose=$(render_docker_compose)
|
||||
echo ""
|
||||
echo "Changes to docker-compose.yml:"
|
||||
printf '%s\n' "$compose" | diff -u docker-compose.yml - || true
|
||||
|
||||
# Lines the new file drops are most likely local edits, so don't default to applying.
|
||||
local lost s restarts="" apply="y"
|
||||
lost=$(printf '%s\n' "$compose" | awk 'NR == FNR { keep[$0]; next } !($0 in keep)' - docker-compose.yml)
|
||||
if [[ -n "$lost" ]]; then
|
||||
echo ""
|
||||
echo "These lines are not in the new docker-compose.yml and will be lost:"
|
||||
printf '%s\n' "$lost"
|
||||
apply="n"
|
||||
fi
|
||||
for s in $($DOCKER_COMPOSE_COMMAND config --services); do
|
||||
if [[ "$(service_block "$s" < docker-compose.yml)" != "$(printf '%s\n' "$compose" | service_block "$s")" ]] \
|
||||
|| [[ "$s" == "netbird-server" && "$want_flow" == "yes" ]]; then
|
||||
restarts+=" $s"
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
if [[ -n "$restarts" ]]; then
|
||||
echo "These services will restart:${restarts}"
|
||||
fi
|
||||
if [[ "$(read_yes_no "Apply these changes?" "$apply")" != "yes" ]]; then
|
||||
echo "Aborted."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
BACKUP_SUFFIX=".bak.$(date -u +%Y%m%d%H%M%S)"
|
||||
for f in "${STACK_FILES[@]}" traefik/proxy.yaml; do
|
||||
if [[ -f "$f" ]]; then cp -p "$f" "$f$BACKUP_SUFFIX"; fi
|
||||
done
|
||||
trap rollback EXIT
|
||||
|
||||
printf '%s\n' "$compose" > docker-compose.yml
|
||||
{
|
||||
echo "NETBIRD_TRAFFIC_FLOW_ENABLED=${NETBIRD_TRAFFIC_FLOW}"
|
||||
echo "NETBIRD_PROXY_ENABLED=${NETBIRD_PROXY}"
|
||||
echo "NETBIRD_CROWDSEC_ENABLED=${NETBIRD_CROWDSEC}"
|
||||
if [[ "$want_flow" == "yes" ]]; then render_env_flow; fi
|
||||
if [[ "$want_proxy" == "yes" ]]; then render_env_proxy; fi
|
||||
} | merge_env
|
||||
if [[ "$want_flow" == "yes" ]] && ! grep -q '^ trafficFlow:' config.yaml; then
|
||||
render_config_flow >> config.yaml
|
||||
fi
|
||||
mkdir -p traefik
|
||||
if [[ "$want_proxy" == "yes" ]]; then
|
||||
render_traefik_proxy > traefik/proxy.yaml
|
||||
fi
|
||||
|
||||
up_all_but_proxy
|
||||
if [[ "$want_flow" == "yes" ]]; then
|
||||
# Compose does not notice changes to the bind-mounted config.yaml.
|
||||
$DOCKER_COMPOSE_COMMAND restart netbird-server
|
||||
fi
|
||||
if [[ "$want_proxy" == "yes" ]]; then
|
||||
start_proxy
|
||||
fi
|
||||
trap - EXIT
|
||||
|
||||
echo ""
|
||||
echo "Done. The previous files are kept with the ${BACKUP_SUFFIX} suffix."
|
||||
if [[ "$want_flow" == "yes" ]]; then
|
||||
echo ""
|
||||
echo "Traffic events still have to be turned on from the dashboard settings."
|
||||
echo " See https://docs.netbird.io/manage/activity/traffic-events-logging"
|
||||
fi
|
||||
if [[ "$want_proxy" == "yes" ]]; then
|
||||
print_proxy_notes
|
||||
fi
|
||||
}
|
||||
|
||||
rollback() {
|
||||
local f
|
||||
echo "" > /dev/stderr
|
||||
echo "Enabling failed. Restoring the previous configuration ..." > /dev/stderr
|
||||
revoke_proxy_token
|
||||
# Files without a backup were created by this run.
|
||||
for f in "${STACK_FILES[@]}" traefik/proxy.yaml; do
|
||||
if [[ -f "$f$BACKUP_SUFFIX" ]]; then cp -p "$f$BACKUP_SUFFIX" "$f"; else rm -f "$f"; fi
|
||||
done
|
||||
$DOCKER_COMPOSE_COMMAND up -d --remove-orphans
|
||||
$DOCKER_COMPOSE_COMMAND restart netbird-server
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Renderers
|
||||
# ------------------------------------------------------------------
|
||||
@@ -427,8 +713,10 @@ NETBIRD_EULA_ACCEPTED=yes
|
||||
NETBIRD_EULA_ACCEPTED_AT=${NETBIRD_EULA_ACCEPTED_AT}
|
||||
NETBIRD_EULA_URL=${NETBIRD_EULA_URL}
|
||||
|
||||
# Features (set by the script; don't edit without re-running)
|
||||
# Features (change with --enable-proxy or --enable-traffic-events, not by hand)
|
||||
NETBIRD_TRAFFIC_FLOW_ENABLED=${NETBIRD_TRAFFIC_FLOW}
|
||||
NETBIRD_PROXY_ENABLED=${NETBIRD_PROXY}
|
||||
NETBIRD_CROWDSEC_ENABLED=${NETBIRD_CROWDSEC}
|
||||
|
||||
# Domain
|
||||
NETBIRD_DOMAIN=${NETBIRD_DOMAIN}
|
||||
@@ -444,10 +732,11 @@ NETBIRD_SERVER_TAG=${NETBIRD_SERVER_TAG:-latest}
|
||||
EOF
|
||||
|
||||
if [[ "$NETBIRD_TRAFFIC_FLOW" == "yes" ]]; then
|
||||
cat <<EOF
|
||||
NETBIRD_ENRICHER_TAG=${NETBIRD_ENRICHER_TAG:-latest}
|
||||
NETBIRD_RECEIVER_TAG=${NETBIRD_RECEIVER_TAG:-latest}
|
||||
EOF
|
||||
render_env_flow
|
||||
fi
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
printf '\n# NetBird Proxy (token and bouncer key are filled in after startup)\n'
|
||||
render_env_proxy
|
||||
fi
|
||||
|
||||
cat <<EOF
|
||||
@@ -483,15 +772,35 @@ NETBIRD_AUTH_SUPPORTED_SCOPES=${NETBIRD_AUTH_SUPPORTED_SCOPES:-openid profile em
|
||||
EOF
|
||||
}
|
||||
|
||||
render_docker_compose() {
|
||||
render_compose_header
|
||||
render_compose_common
|
||||
render_compose_server
|
||||
if [[ "$NETBIRD_TRAFFIC_FLOW" == "yes" ]]; then
|
||||
render_compose_flow
|
||||
render_env_flow() {
|
||||
echo "NETBIRD_ENRICHER_TAG=${NETBIRD_ENRICHER_TAG:-latest}"
|
||||
echo "NETBIRD_RECEIVER_TAG=${NETBIRD_RECEIVER_TAG:-latest}"
|
||||
}
|
||||
|
||||
render_env_proxy() {
|
||||
echo "NETBIRD_PROXY_TAG=${NETBIRD_PROXY_TAG:-latest}"
|
||||
echo "NETBIRD_PROXY_TOKEN="
|
||||
if [[ "$NETBIRD_CROWDSEC" == "yes" ]]; then
|
||||
echo "NETBIRD_CROWDSEC_TAG=${NETBIRD_CROWDSEC_TAG:-v1.7.7}"
|
||||
echo "NETBIRD_CROWDSEC_BOUNCER_KEY="
|
||||
fi
|
||||
render_compose_postgres
|
||||
render_compose_footer
|
||||
}
|
||||
|
||||
render_docker_compose() {
|
||||
{
|
||||
render_compose_header
|
||||
render_compose_common
|
||||
render_compose_server
|
||||
if [[ "$NETBIRD_TRAFFIC_FLOW" == "yes" ]]; then
|
||||
render_compose_flow
|
||||
fi
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
render_compose_proxy
|
||||
fi
|
||||
render_compose_postgres
|
||||
render_compose_footer
|
||||
} | if [[ -n "${NETBIRD_LICENSE_SERVER_BASE_URL:-}" ]]; then cat; else sed '/NETBIRD_LICENSE_SERVER_BASE_URL/d'; fi \
|
||||
| if [[ -n "$CUSTOM_TLS_CERTS" ]]; then sed -e '/certificatesresolvers/d' -e '/certresolver/d'; else cat; fi
|
||||
}
|
||||
|
||||
render_compose_header() {
|
||||
@@ -544,12 +853,20 @@ render_compose_common() {
|
||||
- "--certificatesresolvers.letsencrypt.acme.email=${NETBIRD_LETSENCRYPT_EMAIL}"
|
||||
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
|
||||
- "--certificatesresolvers.letsencrypt.acme.tlschallenge=true"
|
||||
# Dynamic config in ./traefik: the proxy transport and an optional custom certificate
|
||||
- "--providers.file.directory=/etc/traefik/dynamic"
|
||||
ports:
|
||||
- '443:443'
|
||||
- '80:80'
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- netbird_traefik_letsencrypt:/letsencrypt
|
||||
- ./traefik:/etc/traefik/dynamic:ro
|
||||
EOF
|
||||
if [[ -n "$CUSTOM_TLS_CERTS" ]]; then
|
||||
echo " - ${CUSTOM_TLS_CERTS}:/certs:ro"
|
||||
fi
|
||||
cat <<'EOF'
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
# Shared security headers, referenced by every NetBird router below. A
|
||||
@@ -719,6 +1036,69 @@ render_compose_flow() {
|
||||
EOF
|
||||
}
|
||||
|
||||
render_compose_proxy() {
|
||||
cat <<'EOF'
|
||||
# Traefik passes TLS for every other domain through to the proxy, which issues
|
||||
# its own certificates. PROXY protocol v2 preserves the client IP.
|
||||
proxy:
|
||||
<<: *default
|
||||
image: ghcr.io/netbirdio/reverse-proxy:${NETBIRD_PROXY_TAG}
|
||||
container_name: netbird-proxy
|
||||
networks: [netbird]
|
||||
depends_on:
|
||||
netbird-server:
|
||||
condition: service_started
|
||||
ports:
|
||||
- '51820:51820/udp'
|
||||
volumes:
|
||||
- netbird_proxy_certs:/certs
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.tcp.routers.proxy-passthrough.rule=HostSNI(`*`)
|
||||
- traefik.tcp.routers.proxy-passthrough.entrypoints=websecure
|
||||
- traefik.tcp.routers.proxy-passthrough.tls.passthrough=true
|
||||
- traefik.tcp.routers.proxy-passthrough.service=proxy-tls
|
||||
- traefik.tcp.routers.proxy-passthrough.priority=1
|
||||
- traefik.tcp.services.proxy-tls.loadbalancer.server.port=8443
|
||||
- traefik.tcp.services.proxy-tls.loadbalancer.serverstransport=pp-v2@file
|
||||
environment:
|
||||
# Plaintext gRPC over the internal network, not the public address.
|
||||
- NB_PROXY_MANAGEMENT_ADDRESS=http://netbird-server:80
|
||||
- NB_PROXY_ALLOW_INSECURE=true
|
||||
- NB_PROXY_TOKEN=${NETBIRD_PROXY_TOKEN}
|
||||
- NB_PROXY_DOMAIN=${NETBIRD_DOMAIN}
|
||||
- NB_PROXY_ADDRESS=:8443
|
||||
- NB_PROXY_CERTIFICATE_DIRECTORY=/certs
|
||||
- NB_PROXY_ACME_CERTIFICATES=true
|
||||
- NB_PROXY_FORWARDED_PROTO=https
|
||||
- NB_PROXY_PROXY_PROTOCOL=true
|
||||
- NB_PROXY_TRUSTED_PROXIES=${NETBIRD_TRAEFIK_IP}
|
||||
EOF
|
||||
if [[ "$NETBIRD_CROWDSEC" == "yes" ]]; then
|
||||
cat <<'EOF'
|
||||
- NB_PROXY_CROWDSEC_API_URL=http://crowdsec:8080
|
||||
- NB_PROXY_CROWDSEC_API_KEY=${NETBIRD_CROWDSEC_BOUNCER_KEY}
|
||||
|
||||
crowdsec:
|
||||
<<: *default
|
||||
image: crowdsecurity/crowdsec:${NETBIRD_CROWDSEC_TAG}
|
||||
container_name: netbird-crowdsec
|
||||
networks: [netbird]
|
||||
environment:
|
||||
- COLLECTIONS=crowdsecurity/linux
|
||||
volumes:
|
||||
- netbird_crowdsec_config:/etc/crowdsec
|
||||
- netbird_crowdsec_data:/var/lib/crowdsec/data
|
||||
healthcheck:
|
||||
test: ["CMD", "cscli", "lapi", "status"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 15
|
||||
EOF
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
render_compose_postgres() {
|
||||
cat <<'EOF'
|
||||
postgres:
|
||||
@@ -752,6 +1132,12 @@ EOF
|
||||
netbird_enricher:
|
||||
EOF
|
||||
fi
|
||||
if [[ "$NETBIRD_PROXY" == "yes" ]]; then
|
||||
echo " netbird_proxy_certs:"
|
||||
fi
|
||||
if [[ "$NETBIRD_CROWDSEC" == "yes" ]]; then
|
||||
printf ' %s:\n' netbird_crowdsec_config netbird_crowdsec_data
|
||||
fi
|
||||
cat <<'EOF'
|
||||
netbird_postgres:
|
||||
netbird_traefik_letsencrypt:
|
||||
@@ -827,14 +1213,61 @@ server:
|
||||
EOF
|
||||
|
||||
if [[ "$NETBIRD_TRAFFIC_FLOW" == "yes" ]]; then
|
||||
cat <<EOF
|
||||
render_config_flow
|
||||
fi
|
||||
}
|
||||
|
||||
render_config_flow() {
|
||||
cat <<EOF
|
||||
|
||||
trafficFlow:
|
||||
enabled: true
|
||||
address: "https://${NETBIRD_DOMAIN}:443"
|
||||
interval: "60s"
|
||||
EOF
|
||||
}
|
||||
|
||||
render_traefik_proxy() {
|
||||
cat <<'EOF'
|
||||
tcp:
|
||||
serversTransports:
|
||||
pp-v2:
|
||||
proxyProtocol:
|
||||
version: 2
|
||||
EOF
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: $0 [--enable-proxy] [--enable-traffic-events]
|
||||
|
||||
Without flags, bootstraps a new NetBird Enterprise stack in the current
|
||||
directory. With flags, turns the feature on for the existing installation in
|
||||
the current directory.
|
||||
|
||||
--enable-proxy add the NetBird Proxy, optionally with CrowdSec
|
||||
--enable-traffic-events add traffic events logging (NATS, receiver, enricher)
|
||||
-h, --help show this help
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
local enable_proxy="no" enable_flow="no"
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--enable-proxy) enable_proxy="yes" ;;
|
||||
--enable-traffic-events) enable_flow="yes" ;;
|
||||
-h | --help) usage; exit 0 ;;
|
||||
*) usage > /dev/stderr; exit 1 ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [[ "$enable_proxy" == "no" && "$enable_flow" == "no" ]]; then
|
||||
init_environment
|
||||
else
|
||||
enable_features "$enable_proxy" "$enable_flow"
|
||||
fi
|
||||
}
|
||||
|
||||
init_environment
|
||||
main "$@"
|
||||
|
||||
Reference in New Issue
Block a user