The release workflow builds linux/amd64,linux/arm64 via buildx + QEMU on
an amd64 runner, so the frontend-builder stage ran `npm ci`/`npm run
build` under emulation for arm64 -- 20-40 minutes when it did not hang
outright. Its output (frontend/dist) is static, arch-independent assets,
so pin the stage to $BUILDPLATFORM: buildx runs it natively, once, shared
by both platform images. Final images are unchanged.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The app runs flask-socketio with async_mode='threading' (the backend
is real-thread based: jobs scheduler, queue bus, agent registry), where
engineio serves WebSocket via simple-websocket on the raw socket. The
systemd unit template and Dockerfile still launched gunicorn with the
GeventWebSocketWorker, which ALSO answers the upgrade — the client got
HTTP/1.1 101 twice and read the second one as a frame ('Invalid frame
header'), so every panel silently degraded to polling. Proven by
hexdump (double 101, first 'frame' byte 0x48 'H') and fixed live:
single 101 + 0x81 text frame, socket.io connects through Cloudflare.
- unit template + Dockerfile: gunicorn -w 1 --threads 100 (single
PROCESS stays mandatory — in-memory agent gateway)
- requirements: pin simple-websocket explicitly (was transitive-only)
- CLAUDE.md / ARCHITECTURE.md / SECURITY.md single-worker notes updated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The About page's /system/version (and check-update's current-version
read) hardcoded /opt/serverkit first, duplicated in three places:
- app/utils/version.py is now the single resolver: explicit
SERVERKIT_INSTALL_DIR override -> the running code's own tree ->
/opt/serverkit last (a box moved to a custom dir may still have a
stale tree there); system.py's two inline copies now call it
- the systemd unit template renders SERVERKIT_INSTALL_DIR from the
installer's SERVERKIT_DIR (deliberately not the bare SERVERKIT_DIR
env name, which app/paths.py already uses for the /var/serverkit
data root); flows to existing installs via the updater's re-render
- crypto's .env discovery gains the same install-dir hint
- Docker image now ships VERSION (/app/VERSION) — containers showed
the 1.0.0 fallback because no candidate path existed in the image
- 4 proving tests in backend/tests/test_panel_version.py
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Introduce fallback audit logging and enrich audit tooling; add builtin extension discovery/install; and update default launcher ports and related docs/config.
Key changes:
- New middleware app.middleware.audit registers an after-request fallback that records authenticated mutating API requests when routes don't emit explicit audit logs.
- Audit model/action constants extended and AuditService enhanced (request context handling, redaction for sensitive settings, optional commit flag, sets g.audit_logged, emits events).
- Routes/services updated to create explicit audit entries for marketplace and plugin operations (create/update/publish/install/uninstall/enable/disable) and SSO/settings flows switched to use AuditService.
- Added tests for audit logging behavior and redaction (backend/tests/test_audit_log.py).
- Plugin service: added BUILTIN_EXTENSIONS_DIR, list_builtin_extensions and install_builtin_extension; plugin API endpoints to list/install builtin extensions.
- Contribution system extended to support layouts and route layout metadata; frontend wiring updated to surface standalone/custom layouts and extension routes.
- Launcher port defaults changed (backend -> 47927, frontend -> 41921). Updated backend .env.example, config CORS defaults, Dockerfiles and docker-compose to use SERVERKIT_BACKEND_PORT, and many docs/README files and frontend envs to reflect new ports.
- Minor frontend cleanups and new builtin extension example (serverkit-git) plus associated manifest and frontend re-export.
These changes improve observability/security for mutating APIs, enable opt-in builtin plugins, and align local dev/run ports with the launcher defaults.
Introduce a full Services UI and detailed service pages: add Services list page and ServiceDetail page, plus many service-detail components (CommandsTab, EventsTab, GitConnectModal, GunicornTab, LogsTab, MetricsTab, PackagesTab, SettingsTab, ShellTab). Add hooks (useService, useDeployments), serviceTypes utility, and page-specific styles. Update App routing and Sidebar to use /services and wire routes for service list/detail. Minor UI style update in main.less. Update Dockerfiles to create /var/serverkit/apps directory for app storage. Fix backend analytics endpoint decorator by calling @auth_required() to correctly apply authentication.
Add backup dirs in Dockerfiles and adjust ownership. Change server routes to use a dynamic tab param and update components to support tabbed ServerDetail pages. Improve metrics handling by adding serverId support, more resilient field parsing, and server-specific metrics API calls. Revamp ServerDetail: introduce token modal and AgentRegistrationSection, reorganize Metrics, Settings and Security areas (IP allowlist, API key rotation, security alerts), move delete/generate token flows and wire up navigation. Update Servers and Docker pages to handle different API response shapes (Array checks) and tweak install modal copy/UX. Rename backend API call for registration token to /regenerate-token. Add many UI/Icon/CSS adjustments to support the new layouts and interactions, and fix various small bugs and data-shape assumptions.
Introduces a production-ready Dockerfile, a comprehensive CONTRIBUTING.md, and new documentation files (API, installation, roadmap). Updates .env.example with improved comments and structure, enhances .gitignore, and refines the README with expanded features, requirements, and setup instructions. Roadmap and planning files are reorganized, and obsolete HTML is removed.