Official-image wrapper of netboxcommunity/netbox v4.6.10 (netbox-docker 5.0.2, Granian), digest-pinned. OIDC via python-social-auth wired to the platform provider; RQ worker backgrounded behind a web-port gate; addon waits cover the 30s upstream DB timeout. Full-stack verified: migrations, Granian, worker, login page + SSO button. 16/~57. Detail + verification: https://projects.knownelement.com/issues/648#note-4976
107 lines
4.7 KiB
Bash
Executable File
107 lines
4.7 KiB
Bash
Executable File
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
# NetBox runtime setup for Cloudron:
|
|
# 1. create the persistent data dirs (media / reports / scripts — the
|
|
# image paths are build-time symlinks into /app/data)
|
|
# 2. persist the Django SECRET_KEY (>= 50 chars; rotating it invalidates
|
|
# sessions and encrypted values)
|
|
# 3. map the Cloudron addon + platform env onto the image's env-driven
|
|
# configuration (netbox-docker configuration/configuration.py):
|
|
# DB_* from postgresql, REDIS[_CACHE]_* from redis, OIDC from the
|
|
# platform OIDC provider
|
|
# 4. background the RQ worker (gated on the web port so it only starts
|
|
# after the entrypoint's migrations), then exec the upstream
|
|
# entrypoint chain, which waits for the DB, migrates, and hands over
|
|
# to Granian on :8080
|
|
#
|
|
# Authentication: SSO via the Cloudron platform OIDC provider
|
|
# (REMOTE_AUTH_BACKEND = OpenIdConnectAuth + SOCIAL_AUTH_OIDC_*). The
|
|
# local Django login stays available on /login/ for admin bootstrap;
|
|
# SSO-registered users are created WITHOUT privileges (see README).
|
|
|
|
DATA_DIR="/app/data"
|
|
SECRET_FILE="${DATA_DIR}/.secret_key"
|
|
|
|
# --- 1. persistent data directories -------------------------------------------
|
|
mkdir -p "${DATA_DIR}/media" "${DATA_DIR}/reports" "${DATA_DIR}/scripts"
|
|
|
|
# --- 2. persistent SECRET_KEY --------------------------------------------------
|
|
# hex on purpose: 64 chars, comfortably over NetBox's 50-char minimum
|
|
if [[ ! -s "${SECRET_FILE}" ]]; then
|
|
( umask 077; head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "${SECRET_FILE}" )
|
|
echo "Generated new NetBox secret key"
|
|
fi
|
|
export SECRET_KEY="$(cat "${SECRET_FILE}")"
|
|
|
|
# --- 3. Cloudron -> netbox-docker environment -----------------------------------
|
|
export DB_HOST="${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1}"
|
|
export DB_PORT="${CLOUDRON_POSTGRESQL_PORT:-5432}"
|
|
export DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE:-netbox}"
|
|
export DB_USER="${CLOUDRON_POSTGRESQL_USERNAME:-netbox}"
|
|
export DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD:-}"
|
|
|
|
# one Cloudron redis instance, two logical databases (upstream convention:
|
|
# tasks on 0, caching on 1)
|
|
export REDIS_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}"
|
|
export REDIS_PORT="${CLOUDRON_REDIS_PORT:-6379}"
|
|
export REDIS_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}"
|
|
export REDIS_DATABASE=0
|
|
export REDIS_CACHE_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}"
|
|
export REDIS_CACHE_PORT="${CLOUDRON_REDIS_PORT:-6379}"
|
|
export REDIS_CACHE_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}"
|
|
export REDIS_CACHE_DATABASE=1
|
|
|
|
# hosts / CSRF: Cloudron terminates TLS at the platform proxy
|
|
export ALLOWED_HOSTS="${CLOUDRON_APP_DOMAIN:-localhost} localhost"
|
|
export CSRF_TRUSTED_ORIGINS="${CLOUDRON_APP_ORIGIN:-http://localhost}"
|
|
|
|
# first admin is created by the operator via the Cloudron terminal
|
|
# (README): the entrypoint's own superuser seeding is skipped
|
|
export SKIP_SUPERUSER=true
|
|
|
|
# operator knobs (see .env.example)
|
|
export TIME_ZONE="${NETBOX_TIME_ZONE:-UTC}"
|
|
export GRANIAN_WORKERS="${NETBOX_GRANIAN_WORKERS:-4}"
|
|
export METRICS_ENABLED="${NETBOX_METRICS_ENABLED:-false}"
|
|
|
|
# --- 3b. platform OIDC provider -> python-social-auth ---------------------------
|
|
# social-core needs the issuer base URL WITH a trailing slash for
|
|
# .well-known/openid-configuration discovery
|
|
OIDC_ISSUER="${CLOUDRON_OIDC_ISSUER:-}"
|
|
OIDC_ISSUER="${OIDC_ISSUER%/}/"
|
|
export REMOTE_AUTH_BACKEND='social_core.backends.open_id_connect.OpenIdConnectAuth'
|
|
export SOCIAL_AUTH_OIDC_OIDC_ENDPOINT="${OIDC_ISSUER}"
|
|
export SOCIAL_AUTH_OIDC_KEY="${CLOUDRON_OIDC_CLIENT_ID:-}"
|
|
export SOCIAL_AUTH_OIDC_SECRET="${CLOUDRON_OIDC_CLIENT_SECRET:-}"
|
|
export SOCIAL_AUTH_OIDC_SCOPE='openid profile email'
|
|
export LOGOUT_REDIRECT_URL="${CLOUDRON_APP_ORIGIN:-/}"
|
|
|
|
# --- 4. RQ worker + upstream entrypoint -----------------------------------------
|
|
# wait for the addons FIRST: netbox-docker's entrypoint gives up on the DB
|
|
# after only DB_WAIT_TIMEOUT=30s, which can lose the race with a cold
|
|
# Cloudron postgres addon
|
|
wait_tcp() {
|
|
local host="$1" port="$2" name="$3"
|
|
echo "Waiting for ${name} at ${host}:${port} ..."
|
|
until (exec 3<>"/dev/tcp/${host}/${port}") 2>/dev/null; do
|
|
echo "${name} is unavailable - sleeping"
|
|
sleep 2
|
|
done
|
|
echo "${name} is up"
|
|
}
|
|
|
|
wait_tcp "${DB_HOST}" "${DB_PORT}" "PostgreSQL"
|
|
wait_tcp "${REDIS_HOST}" "${REDIS_PORT}" "Redis"
|
|
|
|
# The worker must not run before the schema exists; Granian answering on
|
|
# 8080 is the signal that docker-entrypoint.sh finished migrating.
|
|
(
|
|
until (exec 3<>/dev/tcp/127.0.0.1/8080) 2>/dev/null; do sleep 2; done
|
|
echo "web port is up - starting RQ worker"
|
|
exec python3 /opt/netbox/netbox/manage.py rqworker
|
|
) &
|
|
|
|
echo "Starting NetBox (migrations run automatically, then Granian binds :8080) ..."
|
|
exec /opt/netbox/docker-entrypoint.sh /opt/netbox/launch-netbox.sh
|