setup.sh: add OBMP_AUTH_MODE for local vs authelia bootstrap
The bootstrap previously hard-required OBMP_DOMAIN and OBMP_COOKIE_DOMAIN even when a user just wanted a local lab deployment with Grafana's built-in login -- those vars only feed Authelia's session-cookie domain and the public URL it lives behind. On a fresh host with no FQDN this made ./setup.sh impossible to pass without inventing dummy values. New OBMP_AUTH_MODE=local|authelia in .env (default local) gates the FQDN validation, Authelia secret generation, Authelia config rendering, and the auth-profile image pull/build. setup.sh also writes GF_SERVER_ROOT_URL into .env -- http://HOST_IP:3000/grafana/ for local, https://OBMP_DOMAIN/grafana/ for authelia -- and docker-compose.yml now reads ${GF_SERVER_ROOT_URL} instead of hardcoding the apodacalab.com fallback. Back-compat: an existing .env with no OBMP_AUTH_MODE but a real OBMP_DOMAIN or an existing AUTHELIA_SESSION_SECRET is inferred as 'authelia' and the mode is persisted -- a re-run on a live Authelia host won't silently flip it to local and break the next docker compose up. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
ef932fe1e8
commit
4bcf368af0
20
.env.example
20
.env.example
@ -12,12 +12,26 @@ OBMP_DATA_ROOT=/var/openbmp
|
|||||||
# (Kafka external listener, BMP source, ExaBGP peering).
|
# (Kafka external listener, BMP source, ExaBGP peering).
|
||||||
HOST_IP=changeme
|
HOST_IP=changeme
|
||||||
|
|
||||||
|
# Auth mode:
|
||||||
|
# local — Grafana built-in login (admin / openbmp). Lab default.
|
||||||
|
# OBMP_DOMAIN / OBMP_COOKIE_DOMAIN below can stay blank.
|
||||||
|
# authelia — Authelia in front (docker compose --profile auth).
|
||||||
|
# OBMP_DOMAIN and OBMP_COOKIE_DOMAIN must be set, and a
|
||||||
|
# reverse proxy must terminate TLS at OBMP_DOMAIN.
|
||||||
|
OBMP_AUTH_MODE=local
|
||||||
|
|
||||||
# Public domain fronting Grafana / Authelia / portal (TLS terminates upstream).
|
# Public domain fronting Grafana / Authelia / portal (TLS terminates upstream).
|
||||||
OBMP_DOMAIN=changeme.example.com
|
# Only required when OBMP_AUTH_MODE=authelia.
|
||||||
|
OBMP_DOMAIN=
|
||||||
|
|
||||||
# Authelia session-cookie domain — the parent domain of OBMP_DOMAIN so the
|
# Authelia session-cookie domain — the parent domain of OBMP_DOMAIN so the
|
||||||
# cookie is valid across subpaths/subdomains.
|
# cookie is valid across subpaths/subdomains. Only required when
|
||||||
OBMP_COOKIE_DOMAIN=example.com
|
# OBMP_AUTH_MODE=authelia.
|
||||||
|
OBMP_COOKIE_DOMAIN=
|
||||||
|
|
||||||
|
# Grafana self-generated URL (alerts, share links). setup.sh writes this
|
||||||
|
# automatically based on OBMP_AUTH_MODE — leave blank, it will be filled in.
|
||||||
|
GF_SERVER_ROOT_URL=
|
||||||
|
|
||||||
# Container memory limits. Lab defaults shown; raise for production
|
# Container memory limits. Lab defaults shown; raise for production
|
||||||
# (see docs/production-sizing.md). psql-app's limit must exceed its MEM heap.
|
# (see docs/production-sizing.md). psql-app's limit must exceed its MEM heap.
|
||||||
|
|||||||
@ -115,7 +115,11 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- GF_SECURITY_ADMIN_PASSWORD=openbmp
|
- GF_SECURITY_ADMIN_PASSWORD=openbmp
|
||||||
- GF_AUTH_ANONYMOUS_ENABLED=false
|
- GF_AUTH_ANONYMOUS_ENABLED=false
|
||||||
- GF_SERVER_ROOT_URL=https://${OBMP_DOMAIN:-bmp.apodacalab.com}/grafana/
|
# setup.sh writes GF_SERVER_ROOT_URL into .env based on OBMP_AUTH_MODE
|
||||||
|
# (http://HOST_IP:3000/grafana/ for local, https://OBMP_DOMAIN/grafana/
|
||||||
|
# for authelia). The fallback only matters if compose is run before
|
||||||
|
# setup.sh — keeps Grafana up at a sane URL.
|
||||||
|
- GF_SERVER_ROOT_URL=${GF_SERVER_ROOT_URL:-http://localhost:3000/grafana/}
|
||||||
- GF_SERVER_SERVE_FROM_SUB_PATH=true
|
- GF_SERVER_SERVE_FROM_SUB_PATH=true
|
||||||
- GF_AUTH_PROXY_ENABLED=true
|
- GF_AUTH_PROXY_ENABLED=true
|
||||||
- GF_AUTH_PROXY_HEADER_NAME=Remote-User
|
- GF_AUTH_PROXY_HEADER_NAME=Remote-User
|
||||||
|
|||||||
95
setup.sh
95
setup.sh
@ -4,10 +4,14 @@
|
|||||||
# deployment: every step is guarded and never overwrites live config.
|
# deployment: every step is guarded and never overwrites live config.
|
||||||
#
|
#
|
||||||
# cp .env.example .env # first run only
|
# cp .env.example .env # first run only
|
||||||
# $EDITOR .env # fill in HOST_IP, OBMP_DOMAIN, ...
|
# $EDITOR .env # at minimum fill in HOST_IP
|
||||||
# ./setup.sh
|
# ./setup.sh # local-auth mode by default
|
||||||
# docker compose up -d # collector core
|
# docker compose up -d # collector core
|
||||||
# docker compose --profile test --profile auth up -d # full stack
|
# docker compose --profile test up -d # + lab feeders (ExaBGP, gobgp, ...)
|
||||||
|
#
|
||||||
|
# For Authelia mode, set OBMP_AUTH_MODE=authelia plus OBMP_DOMAIN and
|
||||||
|
# OBMP_COOKIE_DOMAIN in .env before running setup.sh, then bring up with
|
||||||
|
# docker compose --profile test --profile auth up -d
|
||||||
#
|
#
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
cd "$(dirname "$0")"
|
cd "$(dirname "$0")"
|
||||||
@ -18,7 +22,8 @@ AUTHELIA_IMAGE="authelia/authelia:4.38"
|
|||||||
if [ ! -f .env ]; then
|
if [ ! -f .env ]; then
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
echo "Created .env from .env.example."
|
echo "Created .env from .env.example."
|
||||||
echo "Edit it (HOST_IP, OBMP_DOMAIN, OBMP_COOKIE_DOMAIN, credentials), then re-run ./setup.sh"
|
echo "Edit it (set HOST_IP at minimum; OBMP_DOMAIN/OBMP_COOKIE_DOMAIN only"
|
||||||
|
echo "if OBMP_AUTH_MODE=authelia), then re-run ./setup.sh"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -42,10 +47,40 @@ OBMP_DATA_ROOT="${OBMP_DATA_ROOT:-/var/openbmp}"
|
|||||||
OBMP_DOMAIN="$(get_env OBMP_DOMAIN)"
|
OBMP_DOMAIN="$(get_env OBMP_DOMAIN)"
|
||||||
OBMP_COOKIE_DOMAIN="$(get_env OBMP_COOKIE_DOMAIN)"
|
OBMP_COOKIE_DOMAIN="$(get_env OBMP_COOKIE_DOMAIN)"
|
||||||
HOST_IP="$(get_env HOST_IP)"
|
HOST_IP="$(get_env HOST_IP)"
|
||||||
|
OBMP_AUTH_MODE="$(get_env OBMP_AUTH_MODE)"
|
||||||
|
if [ -z "$OBMP_AUTH_MODE" ]; then
|
||||||
|
# Back-compat: existing deployments predate OBMP_AUTH_MODE. If Authelia was
|
||||||
|
# ever initialized (session secret present) or a real OBMP_DOMAIN is set,
|
||||||
|
# this is an Authelia host — default to that mode rather than flipping it
|
||||||
|
# to local and breaking the next `docker compose up`. Fresh .env from
|
||||||
|
# .env.example explicitly sets OBMP_AUTH_MODE=local, so this branch only
|
||||||
|
# triggers for pre-existing installs.
|
||||||
|
if [ -n "$(get_env AUTHELIA_SESSION_SECRET)" ] || \
|
||||||
|
{ [ -n "$OBMP_DOMAIN" ] && [[ "$OBMP_DOMAIN" != changeme* ]]; }; then
|
||||||
|
OBMP_AUTH_MODE="authelia"
|
||||||
|
echo "OBMP_AUTH_MODE not set; inferred 'authelia' from existing .env"
|
||||||
|
else
|
||||||
|
OBMP_AUTH_MODE="local"
|
||||||
|
echo "OBMP_AUTH_MODE not set; defaulting to 'local'"
|
||||||
|
fi
|
||||||
|
set_env OBMP_AUTH_MODE "$OBMP_AUTH_MODE"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- validate ---------------------------------------------------------------
|
# --- validate ---------------------------------------------------------------
|
||||||
|
# HOST_IP is always required. OBMP_DOMAIN / OBMP_COOKIE_DOMAIN are only
|
||||||
|
# required when OBMP_AUTH_MODE=authelia (Authelia needs a real cookie domain
|
||||||
|
# and the public URL it lives behind).
|
||||||
fail=0
|
fail=0
|
||||||
for var in HOST_IP OBMP_DOMAIN OBMP_COOKIE_DOMAIN; do
|
required=(HOST_IP)
|
||||||
|
case "$OBMP_AUTH_MODE" in
|
||||||
|
local) ;;
|
||||||
|
authelia) required+=(OBMP_DOMAIN OBMP_COOKIE_DOMAIN) ;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: OBMP_AUTH_MODE='$OBMP_AUTH_MODE' (must be 'local' or 'authelia')" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
for var in "${required[@]}"; do
|
||||||
val="$(get_env "$var")"
|
val="$(get_env "$var")"
|
||||||
if [ -z "$val" ] || [[ "$val" == changeme* ]]; then
|
if [ -z "$val" ] || [[ "$val" == changeme* ]]; then
|
||||||
echo "ERROR: $var is unset or still 'changeme' in .env" >&2
|
echo "ERROR: $var is unset or still 'changeme' in .env" >&2
|
||||||
@ -53,6 +88,7 @@ for var in HOST_IP OBMP_DOMAIN OBMP_COOKIE_DOMAIN; do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
[ "$fail" -eq 0 ] || { echo "Fix .env and re-run." >&2; exit 1; }
|
[ "$fail" -eq 0 ] || { echo "Fix .env and re-run." >&2; exit 1; }
|
||||||
|
echo "Auth mode: $OBMP_AUTH_MODE"
|
||||||
|
|
||||||
# --- privilege helper -------------------------------------------------------
|
# --- privilege helper -------------------------------------------------------
|
||||||
# $OBMP_DATA_ROOT is often root-owned (e.g. /var/openbmp). Use sudo only if the
|
# $OBMP_DATA_ROOT is often root-owned (e.g. /var/openbmp). Use sudo only if the
|
||||||
@ -77,8 +113,23 @@ $SUDO chmod -R 777 "$OBMP_DATA_ROOT" 2>/dev/null || true
|
|||||||
echo "Syncing Grafana provisioning ..."
|
echo "Syncing Grafana provisioning ..."
|
||||||
$SUDO cp -r obmp-grafana/provisioning/. "$OBMP_DATA_ROOT/grafana/provisioning/"
|
$SUDO cp -r obmp-grafana/provisioning/. "$OBMP_DATA_ROOT/grafana/provisioning/"
|
||||||
|
|
||||||
# --- Authelia secrets -------------------------------------------------------
|
# --- Grafana root URL -------------------------------------------------------
|
||||||
# Generate only if blank/absent; never overwrite an existing value.
|
# In local mode Grafana is hit directly on :3000; in authelia mode the public
|
||||||
|
# URL is https://OBMP_DOMAIN/grafana/. setup.sh writes the right value into
|
||||||
|
# .env so docker-compose just references ${GF_SERVER_ROOT_URL}.
|
||||||
|
case "$OBMP_AUTH_MODE" in
|
||||||
|
local) desired_root_url="http://${HOST_IP}:3000/grafana/" ;;
|
||||||
|
authelia) desired_root_url="https://${OBMP_DOMAIN}/grafana/" ;;
|
||||||
|
esac
|
||||||
|
current_root_url="$(get_env GF_SERVER_ROOT_URL)"
|
||||||
|
if [ "$current_root_url" != "$desired_root_url" ]; then
|
||||||
|
set_env GF_SERVER_ROOT_URL "$desired_root_url"
|
||||||
|
echo "Set GF_SERVER_ROOT_URL=$desired_root_url"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --- Authelia setup (authelia mode only) ------------------------------------
|
||||||
|
if [ "$OBMP_AUTH_MODE" = "authelia" ]; then
|
||||||
|
# Generate secrets only if blank/absent; never overwrite an existing value.
|
||||||
for key in AUTHELIA_SESSION_SECRET AUTHELIA_JWT_SECRET AUTHELIA_STORAGE_ENCRYPTION_KEY; do
|
for key in AUTHELIA_SESSION_SECRET AUTHELIA_JWT_SECRET AUTHELIA_STORAGE_ENCRYPTION_KEY; do
|
||||||
cur="$(get_env "$key")"
|
cur="$(get_env "$key")"
|
||||||
if [ -z "$cur" ]; then
|
if [ -z "$cur" ]; then
|
||||||
@ -90,7 +141,7 @@ AUTHELIA_SESSION_SECRET="$(get_env AUTHELIA_SESSION_SECRET)"
|
|||||||
AUTHELIA_JWT_SECRET="$(get_env AUTHELIA_JWT_SECRET)"
|
AUTHELIA_JWT_SECRET="$(get_env AUTHELIA_JWT_SECRET)"
|
||||||
AUTHELIA_STORAGE_ENCRYPTION_KEY="$(get_env AUTHELIA_STORAGE_ENCRYPTION_KEY)"
|
AUTHELIA_STORAGE_ENCRYPTION_KEY="$(get_env AUTHELIA_STORAGE_ENCRYPTION_KEY)"
|
||||||
|
|
||||||
# --- Authelia config (fresh-deploy only — never clobber a live config) ------
|
# Config files: fresh-deploy only — never clobber a live config.
|
||||||
export AUTHELIA_SESSION_SECRET AUTHELIA_JWT_SECRET AUTHELIA_STORAGE_ENCRYPTION_KEY \
|
export AUTHELIA_SESSION_SECRET AUTHELIA_JWT_SECRET AUTHELIA_STORAGE_ENCRYPTION_KEY \
|
||||||
OBMP_DOMAIN OBMP_COOKIE_DOMAIN
|
OBMP_DOMAIN OBMP_COOKIE_DOMAIN
|
||||||
SUBST='${AUTHELIA_SESSION_SECRET} ${AUTHELIA_JWT_SECRET} ${AUTHELIA_STORAGE_ENCRYPTION_KEY} ${OBMP_DOMAIN} ${OBMP_COOKIE_DOMAIN}'
|
SUBST='${AUTHELIA_SESSION_SECRET} ${AUTHELIA_JWT_SECRET} ${AUTHELIA_STORAGE_ENCRYPTION_KEY} ${OBMP_DOMAIN} ${OBMP_COOKIE_DOMAIN}'
|
||||||
@ -110,6 +161,9 @@ if [ ! -f "$OBMP_DATA_ROOT/authelia/users_database.yml" ]; then
|
|||||||
else
|
else
|
||||||
echo "authelia/users_database.yml exists — left untouched"
|
echo "authelia/users_database.yml exists — left untouched"
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
echo "Skipping Authelia setup (OBMP_AUTH_MODE=$OBMP_AUTH_MODE)"
|
||||||
|
fi
|
||||||
|
|
||||||
# --- gobgpd.conf rendering (host-side -- gobgp image is distroless) ---------
|
# --- gobgpd.conf rendering (host-side -- gobgp image is distroless) ---------
|
||||||
# Render gobgp{,-evpn}/gobgpd.conf from gobgpd.conf.tmpl, substituting
|
# Render gobgp{,-evpn}/gobgpd.conf from gobgpd.conf.tmpl, substituting
|
||||||
@ -122,16 +176,39 @@ for d in gobgp gobgp-evpn; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# --- images -----------------------------------------------------------------
|
# --- images -----------------------------------------------------------------
|
||||||
|
# Always pull / build the `test` profile (ExaBGP, traffic-gen, gobgp -- the
|
||||||
|
# lab feeder bits). Pull `auth` images only when that mode is selected so a
|
||||||
|
# local-mode bootstrap on a fresh host doesn't drag in Authelia + portal.
|
||||||
echo "Pulling and building images ..."
|
echo "Pulling and building images ..."
|
||||||
docker compose pull --quiet
|
if [ "$OBMP_AUTH_MODE" = "authelia" ]; then
|
||||||
|
docker compose --profile test --profile auth pull --quiet
|
||||||
docker compose --profile test --profile auth build
|
docker compose --profile test --profile auth build
|
||||||
|
else
|
||||||
|
docker compose --profile test pull --quiet
|
||||||
|
docker compose --profile test build
|
||||||
|
fi
|
||||||
|
|
||||||
# --- done -------------------------------------------------------------------
|
# --- done -------------------------------------------------------------------
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
Setup complete.
|
Setup complete.
|
||||||
|
|
||||||
|
EOF
|
||||||
|
if [ "$OBMP_AUTH_MODE" = "authelia" ]; then
|
||||||
|
cat <<EOF
|
||||||
docker compose up -d # BMP collector core
|
docker compose up -d # BMP collector core
|
||||||
docker compose --profile test --profile auth up -d # full stack (lab + auth)
|
docker compose --profile test --profile auth up -d # full stack (lab + auth)
|
||||||
|
|
||||||
|
Grafana: https://${OBMP_DOMAIN}/grafana/ (behind Authelia)
|
||||||
EOF
|
EOF
|
||||||
|
else
|
||||||
|
cat <<EOF
|
||||||
|
docker compose up -d # BMP collector core
|
||||||
|
docker compose --profile test up -d # collector + lab feeders (ExaBGP, gobgp, traffic-gen)
|
||||||
|
|
||||||
|
Grafana: http://${HOST_IP}:3000/grafana/ (login: admin / openbmp)
|
||||||
|
|
||||||
|
To switch on Authelia later: set OBMP_AUTH_MODE=authelia + OBMP_DOMAIN +
|
||||||
|
OBMP_COOKIE_DOMAIN in .env, re-run ./setup.sh, then add --profile auth.
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user