Files
oikos/docs/archive/installer-plan.md
T
Ulas Kalayci dd16078f7a docs: archive implemented plans, specs, and design documents
Move completed implementation plans (2026-04-20), design specs,
and audit documents to docs/archive/ for historical reference
while keeping the main docs/ directory focused on active
documentation.

Archived:
- 1 implementation plan (superpowers/plans/)
- 2 design specs (superpowers/specs/)
- 3 design documents (designs/)
- 5 audit/proposal documents (root level)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 20:09:23 +02:00

4.9 KiB

Installer Implementation Plan

Phase 0 Findings Summary

See installer-recon.md for full details.

Key finding: A new POST /api/v1/auth/setup endpoint is required to allow first-admin creation via HTTP when the app runs in Docker. Both installers depend on this.

Dependency Graph

[1] Setup endpoint (server/auth.js)
     ↓
[2a] CLI installer (install.sh)       [2b] Web installer (tools/installer/)
     ↓                                      ↓
[3] .dockerignore update + docs

Steps 2a and 2b are independent and can be built in parallel, but both depend on Step 1.

Deliverables

1. Setup Bootstrap Endpoint (blocking — ~1h, complexity: low)

File: server/auth.js — add new route before the auth guard.

POST /api/v1/auth/setup

Behavior:

  • Query SELECT COUNT(*) FROM users — if > 0, return 403 { error: "Setup already completed", code: 403 }
  • Validate input: username (3-64 chars, alphanumeric + ._-), display_name (1-128 chars), password (min 8 chars)
  • Hash password with bcrypt (cost 12), insert user with role: 'admin'
  • Return 201 { user: { id, username, display_name, avatar_color, role } }
  • Rate-limited (reuse existing loginLimiter or a custom one)
  • No session/CSRF required (unauthenticated endpoint)
  • Mounted at /api/v1/auth/setup in server/index.js (before the requireAuth middleware)

Test: Add test:setup script. Verify: creates admin when no users exist, returns 403 when users exist, validates input.

2a. CLI Installer — install.sh (~3h, complexity: medium)

File: install.sh in repository root.

Wizard steps (7 total):

  1. Prerequisites check: Docker, docker compose, openssl (or /dev/urandom fallback), curl, jq (optional, graceful fallback)
  2. Basic config: domain/IP (default: localhost), port (default: 3000), timezone
  3. Security secrets: SESSION_SECRET + DB_ENCRYPTION_KEY — each with [G]enerate / [M]anual
  4. Weather (optional): ask if wanted, prompt for API key
  5. Calendar (optional): Google OAuth / Apple CalDAV, each skippable
  6. Review & launch: display masked .env, confirm, write .env, run docker compose up -d, poll /health every 2s (120s timeout)
  7. Admin creation: prompt username, display_name, password (read -s), POST to /api/v1/auth/setup

Features:

  • Color output (detect tty, ANSI fallback)
  • --env-file <path> non-interactive mode: skip wizard, use provided .env, run docker + admin creation
  • Ctrl+C trap for clean exit
  • On docker failure: show docker compose logs --tail 50
  • Works on Linux + macOS (bash, no bashisms beyond read -s)

2b. Web Installer — tools/installer/ (~4h, complexity: high)

Files:

  • tools/installer/install-server.js — zero-dependency Node.js HTTP server
  • tools/installer/install.html — single-file SPA (inline CSS + JS)
  • tools/installer/README.md

Server endpoints (port 8090):

Method Path Purpose
GET / Serve install.html
GET /api/defaults Env var catalog with classifications
POST /api/generate-secret crypto.randomBytes(32).toString('hex')
POST /api/save-env Write .env to project root
POST /api/start docker compose up -d
GET /api/status Container health polling
POST /api/create-admin Proxy to Oikos /api/v1/auth/setup

Server features:

  • Node.js built-ins only (http, fs, child_process, crypto, path)
  • Binds to 127.0.0.1:8090
  • Auto-terminates after successful admin creation (or 30min idle)
  • CORS not needed (same origin)

UI design direction: Clean, calm, trustworthy. Dark-mode-aware. Progress bar. Subtle step transitions. Google Fonts (loaded at runtime for installer only — installer is temporary, not part of the Docker image).

Steps mirror CLI: config → secrets → integrations → review → docker start → admin creation → success.

3. Documentation & Housekeeping (~30min, complexity: low)

  • Update docs/installation.md to reference both installer paths
  • Add tools/ to .dockerignore
  • Add install.sh to .dockerignore

Commit Sequence

  1. feat(api): add first-run setup endpoint for admin bootstrap
    • server/auth.js: new /setup route
    • server/index.js: mount before auth guard
    • test-setup.js + package.json test script
  2. feat(installer): add CLI install script
    • install.sh
  3. feat(installer): add web-based installer server and UI
    • tools/installer/install-server.js
    • tools/installer/install.html
    • tools/installer/README.md
  4. chore: add installer files to .dockerignore and update docs
    • .dockerignore additions
    • docs/installation.md updates

Decisions (confirmed)

  1. Fonts: System font stack in web installer. No Google Fonts, no external dependencies.
  2. No Docker-exec fallback: Installer targets current version with setup endpoint only.
  3. TRUST_PROXY: Only via .env. Don't modify docker-compose.yml.