From 6e01d580b2c5372d1b68071492c1b4a26972b55c Mon Sep 17 00:00:00 2001 From: bunker-admin Date: Thu, 16 Apr 2026 12:59:10 -0600 Subject: [PATCH] install: persist generated admin password + Pangolin credential smoke test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- config.sh | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/config.sh b/config.sh index 5b8d1eea..999593ea 100755 --- a/config.sh +++ b/config.sh @@ -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"