install: persist generated admin password + Pangolin credential smoke test

config.sh: two more pieces of first-time-user UX polish surfaced
during fresh-install testing.

- When configure_admin() auto-generates the admin password (no
  --admin-password given), also write a locked-down
  data/admin-credentials.txt (mode 0600) containing email + password
  + timestamp. Users who pipe config.sh output or miss the single
  stdout print no longer lose the password forever. The file is only
  written on the auto-generate path — explicit --admin-password
  leaves it alone.

- configure_pangolin() now smoke-tests --pangolin-api-key +
  --pangolin-org-id against /org/:id/resources before writing them to
  .env. Catches typos, revoked keys, or wrong org IDs while recovery
  is cheap (rather than later, when Newt fails to connect and
  symptoms look like a tunnel outage). New flag:
  --skip-pangolin-check for offline bootstrap scenarios.

Bunker Admin
This commit is contained in:
bunker-admin 2026-04-16 12:59:10 -06:00
parent dbbff8adc9
commit 6e01d580b2

View File

@ -20,6 +20,7 @@ NI_ADMIN_PASSWORD=""
NI_PRODUCTION=true
NI_ENABLE_ALL=false
SKIP_PORT_CHECK=false
SKIP_PANGOLIN_CHECK=false
# Systemd unit install opt-in ("", "yes", "no")
# Empty means "use default for this mode": skipped in NI unless --enable-all.
@ -59,6 +60,7 @@ while [[ $# -gt 0 ]]; do
--development) NI_PRODUCTION=false; shift ;;
--enable-all) NI_ENABLE_ALL=true; shift ;;
--skip-port-check) SKIP_PORT_CHECK=true; shift ;;
--skip-pangolin-check) SKIP_PANGOLIN_CHECK=true; shift ;;
--install-watcher) NI_INSTALL_WATCHER="yes"; shift ;;
--no-install-watcher) NI_INSTALL_WATCHER="no"; shift ;;
--install-backup-timer) NI_INSTALL_BACKUP="yes"; shift ;;
@ -93,6 +95,7 @@ while [[ $# -gt 0 ]]; do
echo " --development Set NODE_ENV=development (default: production)"
echo " --enable-all Enable all optional features + install systemd units"
echo " --skip-port-check Skip host port availability check (not recommended)"
echo " --skip-pangolin-check Skip Pangolin credential smoke test (for offline bootstrap)"
echo ""
echo "Systemd Units (default in -y mode: skipped, unless --enable-all):"
echo " --install-watcher Install upgrade watcher systemd unit"
@ -451,8 +454,10 @@ configure_admin() {
local admin_password="${NI_ADMIN_PASSWORD:-}"
# Generate a password if not provided
local password_was_generated=false
if [[ -z "$admin_password" ]]; then
admin_password="CmLite$(openssl rand -base64 12 | tr -dc 'a-zA-Z0-9' | head -c 12)1"
password_was_generated=true
info "Generated admin password: $admin_password"
info "SAVE THIS — it will not be shown again."
fi
@ -466,6 +471,26 @@ configure_admin() {
update_env_var "INITIAL_ADMIN_PASSWORD" "$admin_password"
update_env_var "N8N_USER_EMAIL" "$admin_email"
CONFIGURED_ADMIN_EMAIL="$admin_email"
# Persist auto-generated password to a locked-down file so users piping
# config.sh output (or missing the scroll) don't lose it forever.
# Only written when we generated it — if the user supplied --admin-password,
# they already have it.
if [[ "$password_was_generated" == "true" ]]; then
mkdir -p "$SCRIPT_DIR/data"
local creds_file="$SCRIPT_DIR/data/admin-credentials.txt"
umask 077
cat > "$creds_file" << CREDS_EOF
# Changemaker Lite — auto-generated admin credentials
# Written by config.sh on $(date -u +%Y-%m-%dT%H:%M:%SZ)
# DELETE THIS FILE after you have saved the password elsewhere.
email=$admin_email
password=$admin_password
CREDS_EOF
chmod 600 "$creds_file"
info "Credentials saved to: $creds_file (mode 0600)"
fi
success "Admin credentials configured ($admin_email)"
else
local default_email="admin@${CONFIGURED_DOMAIN:-cmlite.org}"
@ -1036,6 +1061,24 @@ configure_pangolin() {
local pang_org="$NI_PANGOLIN_ORG_ID"
local pang_endpoint="${NI_PANGOLIN_ENDPOINT:-https://pangolin.bnkserve.org}"
# Smoke-test credentials before committing to .env. Catches typos,
# revoked keys, or wrong org IDs while recovery is still cheap.
if [[ "$SKIP_PANGOLIN_CHECK" != "true" ]] && command -v curl &>/dev/null; then
info "Verifying Pangolin credentials..."
local smoke_status
smoke_status=$(curl -s -o /dev/null -w "%{http_code}" -m 10 \
-H "Authorization: Bearer $pang_key" \
"$pang_url/org/$pang_org/resources" 2>/dev/null) || smoke_status="000"
if [[ "$smoke_status" != "200" ]]; then
error "Pangolin credentials rejected (HTTP $smoke_status)."
error " Check --pangolin-api-url, --pangolin-api-key, --pangolin-org-id."
error " URL tested: $pang_url/org/$pang_org/resources"
error " Pass --skip-pangolin-check to bypass (not recommended)."
exit 1
fi
success "Pangolin credentials verified"
fi
update_env_var "PANGOLIN_API_URL" "$pang_url"
update_env_var "PANGOLIN_API_KEY" "$pang_key"
update_env_var "PANGOLIN_ORG_ID" "$pang_org"