Air-gapped deployment
Run a backend on a machine the platform cannot reach, and manage it once it is there.
TL;DR
- A pack is a whole deployment in a file: images, worker graphs, plan, and the commands to run it.
- You build it for a runtime, the same thing you deploy a backend to. Enrolling a machine creates the runtime that holds it.
- It is issued for one machine and expires with that machine's approval. The machine checks that before it places anything.
- On the machine,
./ppl-offlineis the whole management surface, and./ppl-offline consoleserves a browser UI on loopback. - The platform learns nothing on its own. It knows what you carry back.
Mental model
Everything else in the platform assumes the node can call home. Here it cannot, so the connection is a person walking between two machines, and each direction carries one artifact:
connected machine air-gapped machine
----------------- ------------------
node offline fingerprint ──tar.gz──▶ ./extract-fingerprint.sh
node enroll offline ◀──env──── node-info.env
│
(operator approves)
│
backend pack ──tar.gz──▶ ./scripts/deploy.sh
./ppl-offline …
node offline import-status ◀──json── runtime/exports/status-*.json
The fingerprint is what binds them. It is a digest of the machine's hardware, taken by a probe image; the pack is issued against it, the probe ships inside the pack, and the deploy re-runs it and refuses to place anything if the answer differs.
Walkthrough
Identify the machine, register it, and wait for a platform operator to approve it:
ppl --agent=general node offline fingerprint --platform linux/amd64 --out node-fingerprint.tar.gzppl --agent=general node enroll offline node-info.envppl --agent=general node offline list
Build the pack and carry it over:
ppl --agent=general backend pack --backend *backend-id* --runtime *runtime* --out pack.tar.gz
On the machine, deploy and manage it:
./scripts/deploy.sh./ppl-offline status./ppl-offline console
The console serves on http://127.0.0.1:9099; its bearer is in runtime/console.token. Export a status from its maintenance page, carry the file back, and record it:
ppl --agent=general node offline import-status *node* ./status-20260809T101500Z.jsonppl --agent=general node offline status *node*
Variations
- Staged pack build —
--skeleton-only,--images-only,--files-onlywhen the transfer medium is smaller than the pack. - Pre-seeded machine —
PPL_OFFLINE_SKIP_LOAD_IMAGES=1when the images are already present. - No supervisor —
PPL_OFFLINE_NO_WATCHDOG=1when you want failures to stay failed while you look at them.
Next steps
- /flows/deploy-and-monitor
- /concepts/runtimes-and-nodes
For exact flag tables, JSON contracts, and error matrices, see the page in the CLI:
ppl --agent=general docs get flows/air-gapped-deployment