Skip to content

Applying changes

Applying is two steps: compile your Emet to a manifest, then ship it to the agent. golemctl apply does both — carrying on from the web.emet you wrote in The config.

Terminal window
golemctl apply web.emet http://127.0.0.1:7474

That address is a local agent. A deployed one binds loopback and is named ssh://[user@]host[:port] instead — golemctl opens the SSH forward and carries the shared bearer token from GOLEM_AUTH_TOKEN or GOLEM_AUTH_TOKEN_FILE. Every command on this page takes either shape. See Trust model.

Read the diff first

golemctl plan asks the agent what an apply would do and writes nothing:

Terminal window
golemctl plan web.emet http://127.0.0.1:7474

It answers with one collapsed line per action and a change count; --detail expands every group to one glyph per line with content ids. A plan is safe to run while an apply is in flight.

What golemctl apply does

  1. Compiles (if given .emet). For a .emet source, golemctl shells out to emetc build and captures the binary manifest — a content-addressed artifact carrying every host’s scroll. Hand it a prebuilt .manifest instead and it ships those bytes directly.

  2. Posts it. POST /manifest to the agent. The manifest is the whole fleet; the agent picks out its own host.

  3. Follows the reconcile. The POST comes back at once with a reconcile_id; golemctl then polls that reconcile and draws the units as they settle, ending on the report.

You can also split compile from ship:

Terminal window
emetc build web.emet -o web.manifest # compile
emetc build web.emet --text # eyeball the plan
golemctl apply web.manifest http://127.0.0.1:7474

What the agent does on receipt

POST /manifest returns 202 Accepted with {"reconcile_id": N} as soon as the manifest is ingested; the reconcile runs detached from the request. A reconcile can take tens of minutes — an apt update, a cold image pull — and a held-open request loses its report the moment the connection drops. Progress is read back instead from GET /reconciles/:id (or /reconciles/latest), which takes ?after=<seq> so a follower resumes where it left off.

On the request itself:

  1. Decode + check format_version.
  2. Select the AddressedScroll whose scroll.name matches its --host. Every other host’s scroll is ignored.

Then, detached:

  1. Diff the desired scroll’s glyphs against its journal, by glyph key and content id, into ordered ops: Install, Remove, Replace, Noop.
  2. Enact each op through a reversible reconciler, capturing the prior host state so the edit can be undone.
  3. Journal the ordered outcomes as a Reconcile revision.

Because the diff is content-addressed, re-applying an unchanged fleet is all no-ops. See Reversible reconcile for the mechanism.

Inspecting a node

Terminal window
# The applied scroll and its content id.
golemctl state http://127.0.0.1:7474
# The revision journal.
golemctl history http://127.0.0.1:7474
# One revision — its ops and reversal receipts.
golemctl show http://127.0.0.1:7474 1

More than one host

Naming an address per host stops scaling at about two. golemctl fleet reads a TOML inventory instead and fans the same verbs out concurrently, one connection per host:

Terminal window
golemctl fleet status
golemctl fleet plan web.emet --hosts web-1,web-2
golemctl fleet apply web.emet

One host’s failure never stops the others, and a host the manifest names no scroll for is skipped rather than emptied. The inventory’s fields are in the CLI reference.

Rolling forward

Edit your Emet, re-apply. The changed glyphs get new content ids and are replaced (reverse the old version, apply the new); everything unchanged is a no-op. There is no version number to type — content ids are the version axis.

Terminal window
# Bump an image tag in your Emet, then:
golemctl apply web.emet http://127.0.0.1:7474

Taking it back

Remove a glyph (or a whole abstraction) from your Emet and re-apply. The glyphs no longer in the scroll become Remove ops — each the exact recorded uninstaller. A package golem installed is removed; a package that was already on the box is left alone. “Remove everything” is applying a scroll with no glyphs.

Where to next