v0.18.17.
Complete release notes · 2026-11-03. Read upgrade instructions and runtime limits before deploying.
Added
- Automatic node sleep after continuously verified idle traffic, guarded demand wake through immutable runtime identities, readiness-held route restoration and panel restart recovery. Requires the node traffic capability and configured sleep policy; the automation flag can pause automatic actions. Public status reports observation, held and waking states without exposing execution credentials.
- Real single-manager Swarm acceptance for Docker migration, pinned artifact promotion after source HEAD advances, panel restart recovery on the original deployment and recorded rollback. Require this cohort and public manual/automatic node wake plus lost-routing-acknowledgement recovery on the pushed release image before promotion.
- Internal PostgreSQL restore-verification foundation using isolated networkless helpers, strict SQL/archive restore, known-data probes and confirmed cleanup. Public restore verification controls, other-engine verification and PITR remain unfinished; ordinary backup checks still validate dump structure.
Changed
- A compose stack's domain now picks its service in its own row under Service → Network → Domains, next to the domain's other settings. The separate card under Service → Settings is gone. Save appears only once the choice differs from the stored one (G2.1).
- The autoscale status (
GET /v1/services/:id/autoscale) lists supportedMetrics, the metrics that act where the service runs. A node service set to rps now shows why it holds, with no value, instead of "waiting for node autoscale evaluation". The panel marks a metric that does not act as "not available here", and the CLI lists the metrics under "Metrics here" and warns when autoscale set stores one that does not act (R2). - Node services can autoscale on requests per second (
rps). The node agent must run with NINEDEPLOY_AGENT_PROXY_TRAFFIC=on and serve a routed domain. The autoscaler counts the requests the node proxy served to the replicas in a 10 s window every 30 s. A lost measurement holds the current count; it is never read as zero. Before, a node service set to rps never scaled (R2).
Fixed
- Route manual node wake through durable remote Start rather than starting a same-name panel container. Report pending lifecycle work in the API, SDK, CLI and panel until readiness and routing settle.
- Preserve the healthy application when a pre-Stop routing acknowledgement is lost, recover staged catcher retirement through ordered barriers, and refuse stale routing writes after retirement. Serialize managed database transactions across users of the same database handle.
- Clean partially fetched remote drill files after a failed download. Restore-verification history retains coarse verdicts and timings without persisting SQL probes, expected values or restored results.
- A service cannot move to a node or gain a fan-out node while its maintenance mode, custom error pages or panel sign-in are on. Node proxies do not route what the panel serves. After a move, the setting stayed stored where its card no longer showed, and came back on a move back to the panel host. A protected domain went dark on the node (G2.2, G2.3).
- Maintenance mode and custom error pages are refused for a service that also runs on fan-out nodes. Those nodes kept serving the app while the panel host showed the maintenance page (G2.2).
- A deploy that builds on a node or a build server is refused up front when the service has an inline Dockerfile, with a reason that names Build on: panel. The file is written only into the panel's checkout. The node cloned the repository again and the build failed on a missing
.ninedeploy.Dockerfile, and the docs claimed node builds worked (G1.1). - Cloning a service now copies its inline Dockerfile. The copy built the repository's own Dockerfile instead, or had nothing to build for a "Dockerfile only" service (G1.1).
- The restart-loop limit can no longer be turned on for a node service or a Swarm service, and its card is hidden there. The panel never samples those containers, so the saved limit never acted. A service with the limit on cannot move to a node (G1.3).
- Accepting a domain transfer clears the domain's compose route and panel sign-in. The route still named a service of the old stack, so the recipient's stack sent the domain to its own service of that name, or to nothing (G2.1, G2.3).
- Node serving-traffic receipts are pruned by housekeeping. After 7 days a receipt is deleted unless it is the newest for its node source, which still refuses a replayed interval. Before, the table grew without bound (R2).
Security
- The Hub now says when an app is open before it is set up. The first visitor may become its admin, it may start with a publicly known login, anyone may be able to sign up, or it may have no login at all. 174 templates carry the new
openFirstRun field, and the deploy wizard and the template detail show the warning. The Hub list marks those cards "open until set up". It is stronger when the app also has the Docker socket. - The Coolify Portainer, Authentik and Glances templates are withdrawn from the bundled Hub. Each combines host Docker access with an open first run. Stacks already installed from them keep working (docs/TEMPLATE_MIRRORS.md §4).
Source CHANGELOG.md at 6046cfe8