Skip to content

Repository files, collaboration, releases and project activity.

ARCHFORGE HISTORY

Blame · scripts/fix-admin-origin.sh

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

b0c4351f2earchadmin2026-10-111 #!/usr/bin/env bash
b0c4351f2earchadmin2026-10-112 # v1.0.5 one-shot safe repair of admin POST 403 Invalid origin.
b0c4351f2earchadmin2026-10-113 # Does not delete/recreate admin accounts, SQLite, monitoring or Caddy.
b0c4351f2earchadmin2026-10-114 set -Eeuo pipefail
b0c4351f2earchadmin2026-10-115 umask 077
b0c4351f2earchadmin2026-10-116 say(){ printf '[*] %s\n' "$*"; }
b0c4351f2earchadmin2026-10-117 fail(){ printf '[ERROR] %s\n' "$*" >&2; exit 1; }
b0c4351f2earchadmin2026-10-118 [[ $EUID -eq 0 ]] || fail 'Run this fix as root: bash ./fix-admin-origin.sh'
b0c4351f2earchadmin2026-10-119 ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
b0c4351f2earchadmin2026-10-1110 source "$ROOT/scripts/domain-lib.sh"
b0c4351f2earchadmin2026-10-1111 [[ -r "$ROOT/package.json" && -r "$ROOT/src/server.js" ]] || fail 'Missing status project source checkout'
2109dd33b8archadmin2026-10-1212 /usr/bin/node -e 'if(require(process.argv[1]).version!=="1.0.5")process.exit(1)' "$ROOT/package.json" || fail 'Expected ArchForge checkout v1.0.5. Run git pull --ff-only first.'
b0c4351f2earchadmin2026-10-1113 CFG=/etc/archforge-status/status.env
b0c4351f2earchadmin2026-10-1114 [[ -f "$CFG" && ! -L "$CFG" ]] || fail 'Existing status.env not found (or unsafe symlink)'
b0c4351f2earchadmin2026-10-1115 [[ -f /etc/caddy/Caddyfile ]] || fail 'Caddyfile not found'
b0c4351f2earchadmin2026-10-1116 DOMAIN=status.archforge.nl
b0c4351f2earchadmin2026-10-1117 # Verify that this VPS actually has an intended HTTPS site for our domain.
b0c4351f2earchadmin2026-10-1118 if ! grep -Eqs "^[[:space:]]*${DOMAIN//./\\.}[[:space:]]*\\{" /etc/caddy/Caddyfile /etc/caddy/conf.d/*.caddy 2>/dev/null; then
b0c4351f2earchadmin2026-10-1119  fail 'Caddy has no configured site for status.archforge.nl. Refusing to change public URL.'
b0c4351f2earchadmin2026-10-1120 fi
b0c4351f2earchadmin2026-10-1121 if ! curl -fsS --max-time 6 http://127.0.0.1:3000/healthz >/dev/null;then
b0c4351f2earchadmin2026-10-1122  fail 'Installed status app is not running at localhost:3000. No changes made.'
b0c4351f2earchadmin2026-10-1123 fi
b0c4351f2earchadmin2026-10-1124 BACKUP=$(mktemp -d /root/.archforge-origin-fix.XXXXXXXX)
b0c4351f2earchadmin2026-10-1125 cp -a -- "$CFG" "$BACKUP/status.env"
b0c4351f2earchadmin2026-10-1126 say "Configuration backup: $BACKUP/status.env (private)"
b0c4351f2earchadmin2026-10-1127 CHANGED=false
b0c4351f2earchadmin2026-10-1128 CURRENT=$(grep -m1 '^STATUS_PUBLIC_URL=' "$CFG" | cut -d= -f2- || true)
b0c4351f2earchadmin2026-10-1129 if [[ "$CURRENT" != "https://$DOMAIN" && "$CURRENT" != "https://$DOMAIN/" ]]; then
b0c4351f2earchadmin2026-10-1130  say "Synchronizing STATUS_PUBLIC_URL with Caddy's HTTPS domain."
b0c4351f2earchadmin2026-10-1131  af_set_public_domain "$CFG" "$DOMAIN" || fail 'Failed updating STATUS_PUBLIC_URL'
b0c4351f2earchadmin2026-10-1132  CHANGED=true
b0c4351f2earchadmin2026-10-1133 else
b0c4351f2earchadmin2026-10-1134  say 'Configured public hostname already matches the domain.'
b0c4351f2earchadmin2026-10-1135 fi
b0c4351f2earchadmin2026-10-1136 say 'Deploying tested v1.0.5 code with built-in database backup and rollback...'
b0c4351f2earchadmin2026-10-1137 if ! bash "$ROOT/scripts/deploy.sh" "$ROOT";then
b0c4351f2earchadmin2026-10-1138  say 'Code deployment failed. Restoring original status configuration.'
b0c4351f2earchadmin2026-10-1139  cp -a -- "$BACKUP/status.env" "$CFG"
b0c4351f2earchadmin2026-10-1140  systemctl restart archforge-status || true
b0c4351f2earchadmin2026-10-1141  fail 'Deployment failed and configuration restored.'
b0c4351f2earchadmin2026-10-1142 fi
b0c4351f2earchadmin2026-10-1143 say 'Checking login POST through HTTPS without sending any credentials...'
b0c4351f2earchadmin2026-10-1144 # Invalid CSRF MUST be rejected, but valid Origin MUST NOT receive Invalid origin.
b0c4351f2earchadmin2026-10-1145 OUT=$(mktemp "$BACKUP/response.XXXXXXXX")
b0c4351f2earchadmin2026-10-1146 if ! curl -sS --max-time 12 --resolve "$DOMAIN:443:127.0.0.1" \
b0c4351f2earchadmin2026-10-1147  -H "Origin: https://$DOMAIN" \
b0c4351f2earchadmin2026-10-1148  -H 'Content-Type: application/x-www-form-urlencoded' \
b0c4351f2earchadmin2026-10-1149  --data 'csrf=deliberately-invalid' "https://$DOMAIN/admin/login" > "$OUT";then
b0c4351f2earchadmin2026-10-1150  say 'HTTPS local POST could not be verified; inspect Caddy/SSL separately.'
b0c4351f2earchadmin2026-10-1151 elif grep -q 'Invalid origin' "$OUT"; then
b0c4351f2earchadmin2026-10-1152  fail 'Origin check still rejects canonical host; see service journal: journalctl -u archforge-status -n 50'
b0c4351f2earchadmin2026-10-1153 elif grep -q 'Invalid or expired form token' "$OUT"; then
b0c4351f2earchadmin2026-10-1154  say 'PASS: same-origin login form reaches CSRF validation (as intended).'
b0c4351f2earchadmin2026-10-1155 else
b0c4351f2earchadmin2026-10-1156  say 'The HTTPS response was received but its form result was unexpected; inspect the login page.'
b0c4351f2earchadmin2026-10-1157 fi
b0c4351f2earchadmin2026-10-1158 say 'Finished. Open https://status.archforge.nl/admin/login and sign in again.'
b0c4351f2earchadmin2026-10-1159 say 'All admin credentials, SQLite data and Caddy settings were preserved.'