Deploying over HTTP
The direct route: the agent’s REST API. Best for local work, debugging, and a fleet manager that can reach devices directly.
The whole cycle
sequenceDiagram
autonumber
actor OP as Operator
participant AG as Agent
participant C as Components
OP->>AG: POST /v1/plan/apply?dry=true
AG-->>OP: 202 (validated, nothing changed)
OP->>AG: POST /v1/plan/apply
AG->>C: install and start, in order
AG-->>OP: 202 Accepted
OP->>AG: GET /v1/components
AG-->>OP: state, pid, healthTwo ways to ship recipes
Recipe files on the device. The plan points at paths, and each recipe file needs
a .sig next to it:
The recipe store. Upload recipes through the API, then refer to them by
name:version. Recipes arriving this way are trusted through API authentication
rather than a file signature, so nothing needs to be signed on disk:
The store is the better fit for a fleet: a controller pushes recipes once and then sends small plans that reference them.
The commands
planPath is rejected
Sending {"planPath": "/etc/keystone/plan.toml"} returns 400. The body must be
the plan content: naming a path would let anyone who can reach the API read
arbitrary files off the device. This applies to HTTP; the messaging adapters still
accept a path.
Same thing with keystonectl
keystonectl stop-plan stops everything; keystonectl stop api stops one
component. They are different commands — see the
keystonectl reference.
Scripting a rollout
Because applying an unchanged plan is a no-op, a rollout script can be blunt:
No “is it already deployed?” check is needed. That property is what reconcile buys you.