Node settings
A Node has one setting,apps.path: the apps root under which the Gateway creates development Instance checkouts. Set it with node:add or node:settings. node lists the commands.
Set the apps root
Both commands take repeatable--setting=<setting-path>:<value> options. The only setting path is apps.path.
--setting=apps.path: sends null. The CLI does not trim a value. node:settings needs at least one --setting option.
POST /api/v1/nodes accepts an optional settings member:
PATCH /api/v1/nodes/{node}/settings takes the settings object directly, without a settings wrapper:
apps as an object or null, with path as a string or null. Both the settings object and the nested apps object reject unknown fields. A patch needs the apps member; its path member is optional. "path": null, "apps": null, or "apps": {} removes the path. A patch changes only the members it names. Other stored keys stay, such as the t3 connection that annotations use. The API never returns them. Node responses return the stored value only. They return settings: null when nothing is set, never the default. orbit node:show shows the path, or an em dash when none is set.
Derive the effective root
The apps root isapps.path, or <managed-user-home>/apps when the path is not set. The Gateway computes the default each time and does not store it.
A new development Instance checkout is <apps-root>/<project-slug>/<instance-name>. The Gateway stores that path on the Instance. A later change to apps.path never moves, rewrites, or deletes an existing checkout. Doctor accepts a development checkout under the apps root or under the managed user’s home.
Validation
The Gateway checks the path before it stores it. A path must:- be absolute and normalized: not
/, with no trailing or repeated/, no.or..part, and no control character; - not be the managed user’s home or an ancestor of it;
- not overlap
/boot,/dev,/etc,/proc,/run,/sys,/usr,/opt/orbit,/var/lib/orbit,/var/www, or the Gateway checkout; - not overlap the Gateway release layout: its current link,
releases, andshareddirectories; - not be inside a hidden directory of the managed user’s home; and
- not equal, or lie inside, an existing Instance checkout on the Node.
app-dev role, it prepares the path: it creates each missing directory, owned by the managed user and group with mode 0755. Otherwise the path must already exist. app-dev convergence prepares the apps root in the same way. Caddy must still reach each development Web root under the apps root; Caddy access explains how.
An existing directory must be a real directory, not a symlink, owned by the managed user and group. The owner must have read, write, and execute access, and group and others must not have write access. The Gateway never changes the owner or mode of an existing directory. When a check fails, the stored setting stays unchanged. A directory that the Gateway created before the failure can remain.
Failure codes
The CLI refuses a bad option before it sends a request.
The Gateway refuses an invalid value without changing the stored setting.
Why it works this way
These reasons explain the design. Check them before you propose a change.One typed setting
A generic settings map would make any key part of the public contract. A column for each setting would make each new setting a schema change. Sosettings is one closed, typed value that grows only through reviewed code. instance.path and worktree.path are unknown paths.
Only intent is stored
Storing the computed default would go stale when the managed user’s home changes. So the Gateway stores only the path you set and derives the default when it needs it.Settings never move checkouts
Moving source on a settings change would be a hidden, risky migration. So each checkout keeps the path it got at creation. Move or remove old checkouts with explicit commands.No ownership changes to existing directories
The path can be outside the managed user’s home, so a broadchown could damage unrelated data. The Gateway only creates missing directories and refuses an existing one that does not already fit.