Deploying checked three things — the name is free, the server row exists, the
directory isn't taken. Nothing asked whether the box could carry the thing, so
a 2 GB app landed on a 1 GB VPS at full speed and the first sign of trouble was
the OOM killer.
Every piece was already here and unconnected: templates describe what they cost
(`requirements: memory / storage`), servers report what they have
(Server.total_memory / total_disk) and what they are using (the newest
ServerMetrics sample). This is the join, answering in the shape a person asks
it — does it fit, will it be tight, or can't we tell?
Advisory on purpose. It reports; it never refuses. An estimate is an estimate,
real usage depends on configuration and traffic, so the operator keeps the
final say and "tight" is a sentence to read rather than a wall to argue with.
A full server still returns valid:true, and a test asserts that so this cannot
quietly become a gate.
Three judgements worth stating:
- The reserve is a floor-and-fraction pair (10% of the box, at least 256 MB RAM
/ 2 GB disk). A bare percentage is wrong at both ends: 10% of 1 GB is
nothing, 10% of 64 GB is more than most apps need.
- `unknown` outranks `ok`. No recent sample, or a template that declares
nothing, says so — a confident wrong answer is worse than no answer.
- Free memory comes from psutil's `available`, not `free`: cache and buffers
are reclaimable, and counting them as used calls every healthy Linux box
full.
Catalog coverage goes from 52/106 to 106/106. The 54 estimates are each app's
typical idle-to-light-use footprint, taken from the project's own documented
minimum where it publishes one and rounded to the values the existing 52
already use — sonarqube 4 GB because that is its documented heap floor, immich
4 GB for the ML models, prometheus 20 GB because retention dominates, traefik
256 MB.
Surfaced two ways: a capacity block alongside (never inside) `errors` on
validate-install, and a read-only GET the deploy drawer can poll while the
operator is still choosing a target, so the answer updates as they switch
servers instead of waiting for a submit.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Switched all template icon URLs to use local /serverkit.ai/imgs/template-icons/ assets for consistency and reliability. Improved the Sidebar component with a new user context menu featuring theme switching, settings navigation, and logout, along with conditional display of the WordPress pipeline link. Added and updated related styles for the sidebar, user menu, and page headers, and introduced new theme variables for code/terminal backgrounds.
Port variables in templates are now hidden and always auto-generated, never using user-supplied values. The TemplateService's port assignment checks both database and Docker for used ports, and removes obsolete Docker Compose version fields. Adds new CLI commands for cleaning up all applications, performing a factory reset, and listing applications. Minor update to AuthContext to mark setup as complete after registration.