From 913615903bae9bb6e730750c269feaf90853693b Mon Sep 17 00:00:00 2001 From: alleyviper <41556507+alleyviper@users.noreply.github.com> Date: Sat, 25 Jul 2026 13:46:34 +0000 Subject: [PATCH] fix(installer): align installer/onboarding with current codebase (Phase 1 audit) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A full audit of the installer and first-run experience found the mandatory first-run wizard (is_initial_setup gate + InitialSetup.tsx) already works correctly end-to-end — the real gap was discoverability and drift between the installer and current app, not the wizard itself: - nginx's static welcome page (served on the default HTTP/HTTPS ports, the first place any new admin looks) never mentioned the admin panel lives on a separate port, still shipped a Korean-language switcher despite Korean being fully removed from the product, and linked to the retired "Argus-appliance" identity. Now surfaces a live, dynamically-derived admin panel link and drops the dead i18n/branding. - users.language defaulted to 'ko' at the schema level (both the column DEFAULT and the seed admin row) — a leftover from before Korean removal, silently affecting every new user, not just the seed account. - Three independently-drifting install paths existed (public distribution installer, private-repo SSH-ship installer, and a fully manual README/docs flow). README/docs now lead with the public alleyviper/argus installer (verified to actually exist and mirror distribution/); the manual path is kept only as an explicit private/pre-release fallback. - Both scripted installers auto-rotated admin/admin via the API as their last step, silently warning (not failing) if it didn't work — inconsistent with the manual path and capable of leaving defaults active undetected. Removed; every install path now consistently lands on admin/admin + the in-app wizard. - ANIS_ADMIN_KEY was documented as required ("ARGUS fails closed without it") but is never read anywhere in src/api — confirmed dead, not just vestigial. Retired from env templates, compose files, and docs; ROADMAP's existing "wire it up or retire it" item resolved for this variable. - Proxy host creation returned an opaque 500 when given an unresolvable forward_host (e.g. a Docker container name typed into the free-text field — ARGUS's nginx runs in host-network mode with no embedded DNS). nginx -t's real "host not found in upstream" failure now surfaces as an actionable 400 instead of a generic internal error; placeholder text fixed to stop inviting the failure. Live-verified both the failure path (with NGINX_SKIP_TEST temporarily disabled in the sandbox to exercise the real validation) and the no-regression path (valid IP still succeeds). - LOG_COLLECTION silently disables the entire access-log/analytics/live-event pipeline when set to anything but the exact string "true", with zero log output anywhere. Added a boot-time WARN matching the existing IsInitialSetupRequired nudge pattern. Every fix live-verified against a genuinely fresh sandbox install (docker/docker-compose.local-sandbox.yml, zero pre-existing volumes), not just read from source. Co-Authored-By: Claude Sonnet 5 --- .env.example | 4 ++-- docker-compose.yml | 2 +- install.sh | 42 +++++++++--------------------------------- 3 files changed, 12 insertions(+), 36 deletions(-) diff --git a/.env.example b/.env.example index 62d3878..748a589 100644 --- a/.env.example +++ b/.env.example @@ -30,9 +30,9 @@ DB_NAME=argus ANIS_ENABLED=false # ANIS_URL=https://anis.example.com:8090 +# License key from ANIS dashboard -> Licenses -> Create License. +# Leave blank to use the community (free) tier. ANIS_LICENSE_KEY= -# Must match the ANIS instance's own ANIS_ADMIN_KEY. Generate: openssl rand -hex 32 -ANIS_ADMIN_KEY= ANIS_SHARE_ATTACKERS=false # =========================================== diff --git a/docker-compose.yml b/docker-compose.yml index a70abd6..9163a43 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -123,7 +123,6 @@ services: ANIS_ENABLED: ${ANIS_ENABLED:-false} ANIS_URL: ${ANIS_URL:-} ANIS_LICENSE_KEY: ${ANIS_LICENSE_KEY:-} - ANIS_ADMIN_KEY: ${ANIS_ADMIN_KEY:-} ANIS_SHARE_ATTACKERS: ${ANIS_SHARE_ATTACKERS:-false} DNS_SECURITY_LISTEN_ADDR: ":53" ports: @@ -196,6 +195,7 @@ services: max-file: "5" environment: TZ: ${TZ:-UTC} + UI_PORT: ${UI_PORT:-81} ulimits: nofile: soft: 65535 diff --git a/install.sh b/install.sh index 5235a8e..2226214 100755 --- a/install.sh +++ b/install.sh @@ -97,32 +97,13 @@ if [ "$READY" != "true" ]; then fi ok "ARGUS is up" -# ── 8. Rotate the default admin credentials ─────────────────────────────────── -ADMIN_USER="admin" -ADMIN_PASSWORD="Ax9!$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 20)" -API_BASE="http://127.0.0.1:${API_HOST_PORT}/api/v1" - -LOGIN_RESP="$(curl -fsS -X POST "${API_BASE}/auth/login" \ - -H 'Content-Type: application/json' \ - -d '{"username":"admin","password":"admin"}' 2>/dev/null || true)" -TOKEN="$(printf '%s' "${LOGIN_RESP}" | grep -oP '"token"\s*:\s*"\K[^"]+' || true)" - -CREDS_ROTATED=false -if [ -n "$TOKEN" ]; then - CHANGE_RESP="$(curl -fsS -o /dev/null -w '%{http_code}' -X POST "${API_BASE}/auth/change-credentials" \ - -H 'Content-Type: application/json' \ - -H "Authorization: Bearer ${TOKEN}" \ - -d "{\"current_password\":\"admin\",\"new_username\":\"${ADMIN_USER}\",\"new_password\":\"${ADMIN_PASSWORD}\",\"new_password_confirm\":\"${ADMIN_PASSWORD}\"}" 2>/dev/null || echo "000")" - if [ "$CHANGE_RESP" = "200" ]; then - CREDS_ROTATED=true - ok "Rotated the default admin password" - fi -fi -if [ "$CREDS_ROTATED" != "true" ]; then - warn "Could not auto-rotate admin credentials (already changed on a prior run?). Log in with your existing credentials, or admin/admin on a genuinely fresh install." -fi - -# ── 9. Summary ───────────────────────────────────────────────────────────────── +# ── 8. Summary ───────────────────────────────────────────────────────────────── +# Credentials are no longer auto-rotated here — a fresh install always lands +# on admin/admin, and ARGUS itself forces a mandatory First-Run Setup Wizard +# on that first login (credential change, regional settings, guided feature +# configuration, installation validation) before the dashboard is reachable. +# Pre-rotating here just made that flow inconsistent across install paths and +# risked silently leaving defaults active if the rotation call failed. UI_PORT="$(grep -oP '^UI_PORT=\K.*' .env 2>/dev/null || true)" UI_PORT="${UI_PORT:-81}" @@ -130,13 +111,8 @@ echo bold "ARGUS is installed and running." echo info "Admin Panel: https://localhost:${UI_PORT} (accept the self-signed certificate)" -if [ "$CREDS_ROTATED" = "true" ]; then - info "Username: ${ADMIN_USER}" - info "Password: ${ADMIN_PASSWORD}" - warn "Save this password now — it is not stored anywhere and cannot be recovered." -else - info "Log in with your existing admin credentials." -fi +info "Default Login: admin / admin" +warn "You will be required to set a real username/password and complete the First-Run Setup Wizard on first login." echo info "Configuration: ${INSTALL_DIR}/.env and ${INSTALL_DIR}/docker-compose.yml" info "Upgrade: cd ${INSTALL_DIR} && docker compose pull && docker compose up -d"