The frontend calls the API with relative paths (fetch('/api/...')), so in
production those requests hit the nginx frontend container on :8080 — which
previously only served the SPA and would 404 every API call and WebSocket
route. nginx.conf now proxies /api/ to the archnest-backend service with
WebSocket upgrade support, long timeouts for terminals/tunnels/transfers, and
a 1GB body limit matching the backend's upload cap.
The backend Dockerfile now installs python3/make/g++ in both the build and
runtime stages so the native modules (better-sqlite3, ssh2, node-pty) compile
on alpine instead of crashing the container at startup.
The deploy workflow gains a validate job (type-check + build both apps before
touching the host), a pre-flight check that refuses to deploy without the
host-side .env, and a post-deploy health check against /api/health and the
frontend, with concurrency guarding.
- Single-user JWT auth with a first-run /api/setup endpoint, gated by
GET /api/system/setup-status, to back an upcoming enrollment page
- SQLite schema for users, integrations, secrets (AES-256-GCM encrypted),
bookmarks, and bookmark categories
- Integration adapter registry with real health-check adapters for
Uptime Kuma and Docker, stubs for the rest, wired to
POST /api/integrations/:id/test
- CRUD routes for integrations and bookmarks
- backend/ as its own Docker service in docker-compose.yml, Vite dev
proxy for /api, .env.example for required secrets
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BbJV5nm8KPVH1oNJYKpnoF