Resolves Safety scan DoS advisories SFTY-20260626-04169 (socketio) and
SFTY-20260626-60054 / SFTY-20260626-39072 (engineio). Verified compatible
with Flask-SocketIO 5.6.1 under async_mode='threading'.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerate the pre-bundled frontend/src/plugins copy from its
builtin-extensions source (node scripts/sync-builtin-frontends.mjs) to clear the
builtin-frontend drift CI check. Content-identical re-serialization; no
behavior change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add manifest UI: the repo-import wizard shows a multi-service summary when a
version:1 serverkit.yaml is detected; Service detail Settings gains a Manifest
section (managed-by badge, status pill, scaffold download, Plan/Apply); the
project view shows a manifest status strip. New api/manifests.js client module.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Route manifest-created apps to a fleet server via top-level/per-service server:
(sets Application.server_id; unknown server = plan issue). Clone the
manifest-resolved config (env + per-preview overrides + domain) into non-WP PR
previews via ManifestPreviewService. Add 'serverkit manifest plan|apply|diff'
CLI verbs against the manifests API.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both webhook receivers now re-read serverkit.yaml after a deploy: unchanged hash
is a no-op, a changed manifest auto-applies its autoDeploy services and flips the
rest to pending with an admin notification. Register a 'manifest' drift check
that projects live state onto the declared surface (in_sync iff declared items
match; repair re-applies). Emit manifest.applied/pending/drifted/error events.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add EnvironmentVariable.value_from (migration 055) so an env var can resolve from
a vault secret or a sibling service's connection property at injection time — the
value never lands in the row, masking stays intact, and a rotated secret
propagates on next deploy. EnvReferenceResolver handles both; the apply engine
plans set_env_ref steps, flags missing secrets as plan-time issues, and generates
a random vault secret for generate:true (idempotently).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add manifest_apply_service (resolve -> ordered plan -> idempotent apply inside a
manifest.apply DeploymentJob with before/after snapshots), covering app create/
update, env, volumes, managed databases, backup policies and domain attach.
Extract the WordPress one-call domain+SSL pattern into a core DomainAttachService
(DNS -> vhost -> best-effort cert, each stage degrading to a warning). Wire the
/api/v1/manifests blueprint with get/plan/apply (admin-gated, audit-logged).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stop dropping what import already detects. Add Application.healthcheck_path
(migration 054) and an application_manifests table (one row per project) storing
the normalized manifest, hash and provenance. Import now seeds non-secret env
values and records the health-check path, and the zero-downtime restart gate
polls that path instead of a blind sleep.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the declarative serverkit.yaml v1 spec: JSON Schema + reference doc, a pure
parse/validate/normalize service, version:1 recognition in the repo manifest
detector (legacy flat files unchanged), and a scaffold endpoint that renders a
manifest from a live app.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Validated the engine against a real public box (DO, port-25 egress open) in
addition to WSL. Documents two findings for the next iteration:
- setup can be completed programmatically: in bootstrap GET /api/account grants
sysBootstrapGet/sysBootstrapUpdate, so the panel could auto-finish Stalwart's
one-time setup rather than requiring the web wizard
- the management vocabulary (principal/dkim/queue/mailbox/domain) was confirmed
against Stalwart's own config schema, so the EP_* nouns are correct
No behavior change — comment only.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ran the real container and drove its API; corrected what only a live box
reveals:
- image is stalwartlabs/stalwart:latest — the assumed stalwartlabs/mail-server
no longer resolves on Docker Hub (404 on pull)
- config lives at /etc/stalwart/config.json and data at /opt/stalwart, so
install() now bind-mounts two host dirs instead of one /opt/stalwart-mail
- admin credential is pinned via a single STALWART_RECOVERY_ADMIN=user:secret
env var (not FALLBACK_ADMIN_USER/SECRET)
- a fresh container boots into BOOTSTRAP mode: only the /account setup UI is up
and every /api/* returns 404 (RFC-7807 problem+json) until the one-time setup
completes. get_status now probes /api/session and reports needs_setup +
setup_url; the Overview UI shows a "finish setup" banner. Verified live:
GET /api/session -> 404 problem+json.
- _api parses the problem+json detail/title error shape
Tests updated to the real install argv + two new cases (bootstrap needs_setup,
problem+json parsing): 58 pass. Post-setup CRUD sub-paths (/api/principal etc.)
remain best-effort constants until confirmed against a fully-initialized
instance on a real box.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
56 hermetic tests (docker/HTTP/socket/DNS-provider all stubbed; pass on
Windows). Cover: manifest validity + lifecycle-key/jobs wiring (guards the
loader-key bug), models + no mailbox-password column, Stalwart install argv
(admin API loopback-only, mail ports, generated+persisted admin secret) and
Windows gating, preflight pass/block + persistence, the sending-activation
gate (refused without a passing preflight, force override audited), DKIM
keygen + exact SPF/DKIM/DMARC/MX/A record push with source='mail', fail2ban
jail, and blueprint auth/validation/503 paths.
CHANGELOG: document the Mail Server extension under Unreleased.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Self-contained multi-tab Mail Server page mirroring the serverkit-dns-server
plugin shape (named MailPage export, no default export; own PageTopbar tabs;
generic api.request calls). Tabs: Overview (status/install/service + a
prominent deliverability preflight banner that makes clear sending is blocked
until PTR/port-25/RBL pass), Domains, Mailboxes (+ autoresponder), Forwarders,
DNS & DKIM (generate/deploy records + copy-to-clipboard + LE cert), Queue.
Canonical source under builtin-extensions/serverkit-mail/frontend/ with a
byte-identical synced copy (+ manifest) under frontend/src/plugins/serverkit-mail/.
SCSS-only, host components reused, no inline styles. Verified: eslint 0 errors,
npm run build succeeds (Vite compiles the plugin).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- plugin.json: lifecycle hooks were keyed on_install/on_uninstall, but the
loader reads lifecycle.get('install')/('uninstall') — the hooks (notify-event
registration, container teardown) would have silently never fired. The
manifest validator only vets the values, not the keys, so this slipped past.
- stalwart_service.get_status: read the engine version from a dedicated
read-only /status endpoint instead of GET-ing the /reload endpoint.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A missing route used to surface as a bare "Request failed" toast; now
it reads e.g. "Request failed (405): /api/v1/email/dns-providers" so
the broken endpoint is diagnosable from the UI.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The /api/v1/email/dns-providers routes lived only in the serverkit-email
extension, so panels without it (email is gated to mail users) got a
404/405 from the Settings -> Connections DNS tiles. The service was
already core; the routes now are too, at the same historical paths.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Regenerated via scripts/sync-builtin-frontends.mjs; fixes the Extensions CI
drift check that failed after plan 15 added these extensions without
re-running the sync.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Blueprint/model/job registrations and schedule seeding for drift,
doctor, support bundle, bandwidth, FIM, malware-scan and htaccess
tools; API module aggregation, SCSS imports and CHANGELOG for the
batch. Full backend suite: 1793 passed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
serverkit-dns-server runs PowerDNS (SQLite) in a managed container:
zones, records, DNSSEC with DS records for the registrar, and a
delegation check. Complements the provider integrations; for homelab
and air-gapped boxes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paste-in translator for common rewrite/redirect/auth/access rules with
per-line unsupported flags, launched from the Import wizard (no core
custom-rules editor exists yet — output is copy/insert).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Opt-in 10s FastCGI/proxy micro-cache per site (migration 053) with safe
bypasses for logged-in/admin/cart cookies and paths, X-SK-Cache header
for verification, and a shared-zone purge. Flows through the drift-safe
vhost render seam so detection and writes always agree.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Daily nginx access-log aggregation (migration 052) into per-site
transfer stats with 30-day sparklines on the Services list and a
monthly figure on the service Overview. Streaming parser handles
combined and vhost-prefixed formats plus rotation spillover.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
serverkit-crowdsec surfaces decisions/alerts, ban/unban and allowlists
via cscli with feature detection and graceful degradation when CrowdSec
is absent. Installs from Marketplace Browse; no core changes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Baseline-and-diff over managed paths (nginx config, serverkit systemd
units, opt-in app docroots) on a six-hourly sweep, feeding the
Notifications Bus; Integrity tab gains baseline/check/accept controls
and a what-changed view.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Malware scans run as jobs and can target an app's docroot; a curated
web-shell rule set (yara CLI when present, pure-Python fallback) runs
alongside ClamAV with custom .yar upload; quarantine gains restore via
original-path metadata. Note: api/security.py also carries the FIM
routes of the next commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
serverkit status / services / apps / doctor [--repair] / repair /
update / login-url / support-bundle. Break-glass auth mints a 10-minute
admin JWT in-process (audit-logged) — root on the box already implies
full control. The support bundle exports a secret-scrubbed zip of
versions, service states, setting shapes and recent job failures.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Daily read-only drift sweep re-renders expected nginx vhosts and compose
overrides from panel state (via extracted pure render seams) and diffs
against disk; drift notifies admins. Doctor tab on Monitoring runs the
full diagnosis (drift, services, certs, disk, DB) with diff-confirmed
per-item and batch repair. Nothing auto-repairs. The nginx render seam
also carries the micro-cache blocks used by the next commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Blueprint/model/job registrations for the migration pipeline, speed
test, metadata guard, login-link + SSO reapers (seeded with the
builtin schedules), demo-mode middleware, /imports route, API module
aggregation and SCSS imports; CHANGELOG for the batch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Probe with host-key pinning, tar-stream the docroot, dump the DB
through the tunnel and rebuild via the existing import/URL-swap path;
3-step UI at /wordpress/ssh-import. Password auth needs sshpass;
secrets never hit argv or logs.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Format-pluggable analyse->plan->run pipeline (migration 051) that maps
legacy panel backups to ServerKit apps, managed DBs (preserving MySQL
password hashes where portable) and cron entries, as resumable jobs
with per-step logs, SSRF/tar-traversal guards, and a 5-step Import a
Site wizard at /imports.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
managed_database_users rows (migration 050) track users/grants so they
survive restarts; SSO launches an on-demand Adminer container
pre-authenticated with a single-use, 5-minute shadow credential scoped
to one database, reaped on schedule. Also mounts the config tuner in
the explorer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Vetted MySQL/PostgreSQL settings with RAM-aware suggestions, applied
via a ServerKit-owned drop-in (MySQL) or ALTER SYSTEM (PostgreSQL) with
timestamped backups, verified restart and clean rollback. Never
auto-applies.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
SHOW FULL PROCESSLIST / pg_stat_activity normalized per server or
container, with admin-only kill/terminate and 5s auto-refresh tabs in
the Database Explorer.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Single-use, short-TTL, optionally IP-bound login URLs (hash-at-rest,
migration 049, hourly reap job) minted from Settings > Users; plus a
config-gated demo mode that 403s mutating API calls and seeds read-only
credentials on the login page.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cpu_limit/memory_limit on Application (migration 048), emitted into the
generated compose and the ServerKit override for live re-apply, with a
Resource Limits panel (usage vs limit) in Service Settings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Job-backed speed test (Ookla/speedtest-cli when present, pure-Python
fallback) with download/upload/latency surfaced on the Monitoring
overview; last result persisted in settings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Default-on (opt-out) DOCKER-USER drop rule for 169.254.169.254 with an
nftables fallback, toggleable from Security > Firewall. Kills the
SSRF-to-cloud-IAM credential-theft class on cloud VPSes.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>