Skip to content

Repository files, collaboration, releases and project activity.

ARCHFORGE HISTORY

Blame · scripts/repair-admin-login.sh

Branch main · the Commit author is not necessarily a verified ArchForge account.

299229ecf6archadmin2026-10-121 #!/usr/bin/env bash
2109dd33b8archadmin2026-10-122 # ArchForge External Status 1.0.6 - ArchForge-based admin login recovery.
299229ecf6archadmin2026-10-123 # Never resets admin accounts, sessions, tokens, Caddy or SQLite data.
299229ecf6archadmin2026-10-124 set -Eeuo pipefail
299229ecf6archadmin2026-10-125 umask 077
299229ecf6archadmin2026-10-126 log(){ printf '[*] %s\n' "$*"; }
299229ecf6archadmin2026-10-127 fail(){ printf '[ERROR] %s\n' "$*" >&2; exit 1; }
299229ecf6archadmin2026-10-128 [[ $EUID -eq 0 ]] || fail 'Run as root: bash ./repair-admin-login.sh'
299229ecf6archadmin2026-10-129 ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
2109dd33b8archadmin2026-10-1210 [[ -f "$ROOT/package.json" && -f "$ROOT/src/server.js" ]] || fail 'Start from your ArchForge checkout'
2109dd33b8archadmin2026-10-1211 [[ "$(/usr/bin/node -p 'require(process.argv[1]).version' "$ROOT/package.json")" == '1.0.6' ]] || fail 'ArchForge checkout is not 1.0.6; commit/push/pull the update first'
2109dd33b8archadmin2026-10-1212 [[ "$ROOT" != '/opt/archforge-status/app' ]] || fail 'Run this from the ArchForge checkout, not from /opt'
299229ecf6archadmin2026-10-1213 CFG=/etc/archforge-status/status.env
299229ecf6archadmin2026-10-1214 [[ -f "$CFG" && ! -L "$CFG" ]] || fail 'Missing /etc/archforge-status/status.env'
299229ecf6archadmin2026-10-1215 [[ -r "$ROOT/scripts/domain-lib.sh" ]] || fail 'Missing domain configuration helper'
299229ecf6archadmin2026-10-1216 source "$ROOT/scripts/domain-lib.sh"
299229ecf6archadmin2026-10-1217 DOMAIN='status.archforge.nl'
299229ecf6archadmin2026-10-1218 if ! grep -Eqs "^[[:space:]]*${DOMAIN//./\\.}[[:space:]]*\\{" /etc/caddy/Caddyfile /etc/caddy/conf.d/*.caddy 2>/dev/null; then
299229ecf6archadmin2026-10-1219  fail 'Caddy is not configured for status.archforge.nl; no changes made'
299229ecf6archadmin2026-10-1220 fi
299229ecf6archadmin2026-10-1221 if ! curl --fail --silent --show-error --max-time 5 http://127.0.0.1:3000/healthz >/dev/null;then
299229ecf6archadmin2026-10-1222  fail 'Status service unavailable on 127.0.0.1:3000; check systemctl status archforge-status'
299229ecf6archadmin2026-10-1223 fi
299229ecf6archadmin2026-10-1224 SNAP=$(mktemp -d /root/.archforge-login-repair.XXXXXXXX)
299229ecf6archadmin2026-10-1225 cp -a -- "$CFG" "$SNAP/status.env"
299229ecf6archadmin2026-10-1226 log "Private .env backup created ($SNAP/status.env)"
299229ecf6archadmin2026-10-1227 CURRENT=$(grep -m1 '^STATUS_PUBLIC_URL=' "$CFG" | cut -d= -f2- || true)
299229ecf6archadmin2026-10-1228 if [[ "$CURRENT" != "https://$DOMAIN" && "$CURRENT" != "https://$DOMAIN/" ]];then
299229ecf6archadmin2026-10-1229  log 'Synchronizing public URL with the Caddy HTTPS domain'
299229ecf6archadmin2026-10-1230  af_set_public_domain "$CFG" "$DOMAIN" || fail 'Cannot safely update public URL'
299229ecf6archadmin2026-10-1231 fi
299229ecf6archadmin2026-10-1232 log 'Deploying version 1.0.6 via the existing backup/rollback installer'
299229ecf6archadmin2026-10-1233 if ! bash "$ROOT/scripts/deploy.sh" "$ROOT";then
299229ecf6archadmin2026-10-1234  log 'Deployment failed; restoring the previous status.env'
299229ecf6archadmin2026-10-1235  cp -a -- "$SNAP/status.env" "$CFG"
299229ecf6archadmin2026-10-1236  systemctl restart archforge-status || true
299229ecf6archadmin2026-10-1237  fail 'Deployment was rolled back. The old release should still be in service.'
299229ecf6archadmin2026-10-1238 fi
299229ecf6archadmin2026-10-1239 version=$(curl --fail --silent --show-error --max-time 5 http://127.0.0.1:3000/healthz | /usr/bin/node -p 'try { JSON.parse(require("fs").readFileSync(0,"utf8")).version } catch { "" }')
299229ecf6archadmin2026-10-1240 [[ "$version" == '1.0.6' ]] || fail "Installed version verification failed (${version:-unknown}); inspect journalctl -u archforge-status"
299229ecf6archadmin2026-10-1241 log 'Running safe login tests locally (no passwords or 2FA codes needed)'
299229ecf6archadmin2026-10-1242 # Reuse a freshly issued double-submit cookie, with a dummy username.
299229ecf6archadmin2026-10-1243 curl --silent --show-error --max-time 5 -D "$SNAP/headers" -o /dev/null http://127.0.0.1:3000/admin/login
299229ecf6archadmin2026-10-1244 CSRF=$(sed -nE 's/^[Ss]et-[Cc]ookie: af_csrf=([^;]+).*/\1/p' "$SNAP/headers" | tr -d '\r' | head -n 1)
299229ecf6archadmin2026-10-1245 [[ "$CSRF" =~ ^[A-Za-z0-9_-]{32,100}$ ]] || fail 'Could not obtain form token from local status app'
299229ecf6archadmin2026-10-1246 post_login(){
299229ecf6archadmin2026-10-1247  local output_name=$1 site=$2 origin=$3 expected=$4 code
299229ecf6archadmin2026-10-1248  code=$(curl --silent --show-error --max-time 6 -o "$SNAP/$output_name" -w '%{http_code}' \
299229ecf6archadmin2026-10-1249  -H "Cookie: af_csrf=$CSRF" \
299229ecf6archadmin2026-10-1250  -H "Origin: $origin" \
299229ecf6archadmin2026-10-1251  -H "Sec-Fetch-Site: $site" \
299229ecf6archadmin2026-10-1252  -H 'Content-Type: application/x-www-form-urlencoded' \
299229ecf6archadmin2026-10-1253  --data-urlencode "csrf=$CSRF" \
299229ecf6archadmin2026-10-1254  --data-urlencode 'username=__archforge_test_nonexistent__' \
299229ecf6archadmin2026-10-1255  --data-urlencode 'password=never-a-valid-password' \
299229ecf6archadmin2026-10-1256  --data-urlencode 'totp=000000' \
299229ecf6archadmin2026-10-1257  http://127.0.0.1:3000/admin/login)
299229ecf6archadmin2026-10-1258  [[ "$code" == "$expected" ]] || fail "Login $output_name returned HTTP $code (expected $expected); inspect installed version and logs"
299229ecf6archadmin2026-10-1259 }
299229ecf6archadmin2026-10-1260 post_login canonical 'same-origin' "https://$DOMAIN" 401
299229ecf6archadmin2026-10-1261 post_login privacy 'same-origin' 'null' 401
299229ecf6archadmin2026-10-1262 post_login blocked 'cross-site' "https://$DOMAIN" 403
299229ecf6archadmin2026-10-1263 log 'PASS: canonical and privacy-protected same-origin login reach credential validation'
299229ecf6archadmin2026-10-1264 log 'PASS: cross-site login is still blocked; CSRF verification remains mandatory'
299229ecf6archadmin2026-10-1265 log 'Installed release: 1.0.6. Refresh https://status.archforge.nl/admin/login and try again.'
299229ecf6archadmin2026-10-1266 log 'No credentials, monitoring database or Caddy configuration changed.'