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-12
1 #!/usr/bin/env bash2109dd33b8archadmin2026-10-12
2 # ArchForge External Status 1.0.6 - ArchForge-based admin login recovery.299229ecf6archadmin2026-10-12
3 # Never resets admin accounts, sessions, tokens, Caddy or SQLite data.299229ecf6archadmin2026-10-12
4 set -Eeuo pipefail299229ecf6archadmin2026-10-12
5 umask 077299229ecf6archadmin2026-10-12
6 log(){ printf '[*] %s\n' "$*"; }299229ecf6archadmin2026-10-12
7 fail(){ printf '[ERROR] %s\n' "$*" >&2; exit 1; }299229ecf6archadmin2026-10-12
8 [[ $EUID -eq 0 ]] || fail 'Run as root: bash ./repair-admin-login.sh'299229ecf6archadmin2026-10-12
9 ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)2109dd33b8archadmin2026-10-12
10 [[ -f "$ROOT/package.json" && -f "$ROOT/src/server.js" ]] || fail 'Start from your ArchForge checkout'2109dd33b8archadmin2026-10-12
11 [[ "$(/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-12
12 [[ "$ROOT" != '/opt/archforge-status/app' ]] || fail 'Run this from the ArchForge checkout, not from /opt'299229ecf6archadmin2026-10-12
13 CFG=/etc/archforge-status/status.env299229ecf6archadmin2026-10-12
14 [[ -f "$CFG" && ! -L "$CFG" ]] || fail 'Missing /etc/archforge-status/status.env'299229ecf6archadmin2026-10-12
15 [[ -r "$ROOT/scripts/domain-lib.sh" ]] || fail 'Missing domain configuration helper'299229ecf6archadmin2026-10-12
16 source "$ROOT/scripts/domain-lib.sh"299229ecf6archadmin2026-10-12
17 DOMAIN='status.archforge.nl'299229ecf6archadmin2026-10-12
18 if ! grep -Eqs "^[[:space:]]*${DOMAIN//./\\.}[[:space:]]*\\{" /etc/caddy/Caddyfile /etc/caddy/conf.d/*.caddy 2>/dev/null; then299229ecf6archadmin2026-10-12
19 fail 'Caddy is not configured for status.archforge.nl; no changes made'299229ecf6archadmin2026-10-12
20 fi299229ecf6archadmin2026-10-12
21 if ! curl --fail --silent --show-error --max-time 5 http://127.0.0.1:3000/healthz >/dev/null;then299229ecf6archadmin2026-10-12
22 fail 'Status service unavailable on 127.0.0.1:3000; check systemctl status archforge-status'299229ecf6archadmin2026-10-12
23 fi299229ecf6archadmin2026-10-12
24 SNAP=$(mktemp -d /root/.archforge-login-repair.XXXXXXXX)299229ecf6archadmin2026-10-12
25 cp -a -- "$CFG" "$SNAP/status.env"299229ecf6archadmin2026-10-12
26 log "Private .env backup created ($SNAP/status.env)"299229ecf6archadmin2026-10-12
27 CURRENT=$(grep -m1 '^STATUS_PUBLIC_URL=' "$CFG" | cut -d= -f2- || true)299229ecf6archadmin2026-10-12
28 if [[ "$CURRENT" != "https://$DOMAIN" && "$CURRENT" != "https://$DOMAIN/" ]];then299229ecf6archadmin2026-10-12
29 log 'Synchronizing public URL with the Caddy HTTPS domain'299229ecf6archadmin2026-10-12
30 af_set_public_domain "$CFG" "$DOMAIN" || fail 'Cannot safely update public URL'299229ecf6archadmin2026-10-12
31 fi299229ecf6archadmin2026-10-12
32 log 'Deploying version 1.0.6 via the existing backup/rollback installer'299229ecf6archadmin2026-10-12
33 if ! bash "$ROOT/scripts/deploy.sh" "$ROOT";then299229ecf6archadmin2026-10-12
34 log 'Deployment failed; restoring the previous status.env'299229ecf6archadmin2026-10-12
35 cp -a -- "$SNAP/status.env" "$CFG"299229ecf6archadmin2026-10-12
36 systemctl restart archforge-status || true299229ecf6archadmin2026-10-12
37 fail 'Deployment was rolled back. The old release should still be in service.'299229ecf6archadmin2026-10-12
38 fi299229ecf6archadmin2026-10-12
39 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-12
40 [[ "$version" == '1.0.6' ]] || fail "Installed version verification failed (${version:-unknown}); inspect journalctl -u archforge-status"299229ecf6archadmin2026-10-12
41 log 'Running safe login tests locally (no passwords or 2FA codes needed)'299229ecf6archadmin2026-10-12
42 # Reuse a freshly issued double-submit cookie, with a dummy username.299229ecf6archadmin2026-10-12
43 curl --silent --show-error --max-time 5 -D "$SNAP/headers" -o /dev/null http://127.0.0.1:3000/admin/login299229ecf6archadmin2026-10-12
44 CSRF=$(sed -nE 's/^[Ss]et-[Cc]ookie: af_csrf=([^;]+).*/\1/p' "$SNAP/headers" | tr -d '\r' | head -n 1)299229ecf6archadmin2026-10-12
45 [[ "$CSRF" =~ ^[A-Za-z0-9_-]{32,100}$ ]] || fail 'Could not obtain form token from local status app'299229ecf6archadmin2026-10-12
46 post_login(){299229ecf6archadmin2026-10-12
47 local output_name=$1 site=$2 origin=$3 expected=$4 code299229ecf6archadmin2026-10-12
48 code=$(curl --silent --show-error --max-time 6 -o "$SNAP/$output_name" -w '%{http_code}' \299229ecf6archadmin2026-10-12
49 -H "Cookie: af_csrf=$CSRF" \299229ecf6archadmin2026-10-12
50 -H "Origin: $origin" \299229ecf6archadmin2026-10-12
51 -H "Sec-Fetch-Site: $site" \299229ecf6archadmin2026-10-12
52 -H 'Content-Type: application/x-www-form-urlencoded' \299229ecf6archadmin2026-10-12
53 --data-urlencode "csrf=$CSRF" \299229ecf6archadmin2026-10-12
54 --data-urlencode 'username=__archforge_test_nonexistent__' \299229ecf6archadmin2026-10-12
55 --data-urlencode 'password=never-a-valid-password' \299229ecf6archadmin2026-10-12
56 --data-urlencode 'totp=000000' \299229ecf6archadmin2026-10-12
57 http://127.0.0.1:3000/admin/login)299229ecf6archadmin2026-10-12
58 [[ "$code" == "$expected" ]] || fail "Login $output_name returned HTTP $code (expected $expected); inspect installed version and logs"299229ecf6archadmin2026-10-12
59 }299229ecf6archadmin2026-10-12
60 post_login canonical 'same-origin' "https://$DOMAIN" 401299229ecf6archadmin2026-10-12
61 post_login privacy 'same-origin' 'null' 401299229ecf6archadmin2026-10-12
62 post_login blocked 'cross-site' "https://$DOMAIN" 403299229ecf6archadmin2026-10-12
63 log 'PASS: canonical and privacy-protected same-origin login reach credential validation'299229ecf6archadmin2026-10-12
64 log 'PASS: cross-site login is still blocked; CSRF verification remains mandatory'299229ecf6archadmin2026-10-12
65 log 'Installed release: 1.0.6. Refresh https://status.archforge.nl/admin/login and try again.'299229ecf6archadmin2026-10-12
66 log 'No credentials, monitoring database or Caddy configuration changed.'