Skip to content

punix service

Deploy and roll back service stacks.

Subcommands

punix service deploy STACK --file PCL [flags...]
punix service rollback STACK [flags...]

A stack is a PCL module with a backend field (see Composing a stack).

punix service deploy

Compose a stack PCL module, realise its closure, render the backend's config files, atomically flip current. The full deploy pipeline.

punix service deploy MyStack --file stack.pcl

Flags

  • --file PCL (required) — PCL file or directory containing the stack.
  • --dry-run — full pipeline against a scratch dir; no real I/O. Writes to <deployments_root>/.dry-run/.
  • --store-root PATH — store location (default ~/.punix/store).
  • --deployments-root PATH — where gen-NNN.json lives (default ~/.punix/deployments).
  • --transport-root PATH — rebase the filesystem surface under PATH. Mutually exclusive with --target. Used for hermetic tests.
  • --target ssh://user@host[:port] — deploy to a remote host. Mutually exclusive with --transport-root.
  • --key /path/to/private_key — SSH private key (default: ssh-agent).
  • --known-hosts /path/to/known_hosts — pin the target's host key (default: user's ~/.ssh/known_hosts).
  • --scenario NAME — evaluate under the given scenario.
  • --tls-certs DIR — provision TLS from a directory of pre-supplied certs (<dir>/<domain>/{fullchain,privkey}.pem); skipped under --dry-run. See TLS.
  • --vault-secrets FILE — resolve {from_vault="REF"} secrets from a JSON {ref: value} export. Required if the stack uses from_vault.
  • --activate — after the flip, systemctl daemon-reload + restart the deployed units (an effect; ignored under --dry-run). Off ⇒ config only. See Activation.

Output

deployed: stack MyStack → gen-002 (3 config file(s), 2 store path(s) pinned, 1 pushed/1 cached)

The summary line reports:

  • generation number,
  • count of config files written (stack-declared + backend-generated),
  • count of store paths pinned,
  • (non-dry-run only) closure-push counts: N pushed/M cached.

Exit codes

  • 0 — deployed; current flipped.
  • 1 — located [E#] (parse/type/build-closure/E11 missing secret/E12 pinned-path-missing).
  • 2 — usage error (missing --file, malformed --target, mutually exclusive flags).
  • 3 — realise or transport failure.

punix service rollback

Re-apply gen-(current-1): verify pinned paths still exist, atomically flip current backwards. O(1) — no rebuild.

punix service rollback MyStack

Flags

Same --store-root, --deployments-root, --transport-root, --target, --key, --known-hosts as deploy. No --file (rollback re-uses the already-pinned previous-gen manifest).

Output

rolled back: stack MyStack → gen-001 (was gen-002)

Exit codes

  • 0 — flipped; current now points at gen-(prev).
  • 1[E12]: no previous generation (current is at gen-001), OR a pinned store path is missing (typically a GC contamination).

Deploy: rollback for triage + recovery.

SSH deploys

--target ssh://user@host[:port] swaps LocalTransport for SshTransport. The rest of the deploy code is unchanged (Manifest.atomic_switchTransport.atomic_symlink_switch).

The closure push step (Stage 5b) walks stack.store_paths and rsyncs anything the target doesn't already have. Content-addressed: existence on the target IS the cache check.

Deploy over SSH for the full recipe.

Secrets

If a service's environment declares a {from_env=…}, {from_file=…}, or {from_vault=…} reference, service deploy resolves it at deploy time. Missing references ⇒ [E11] with the full list:

error: [E11] secret(s) not set: from_env:DB_PWD, from_file:/run/secrets/jwt

Secrets at deploy for the operator recipe; Concepts: secrets for the hash-exclusion property.

Deploying many hosts

To deploy a whole fleet from one command, use punix fleet apply — it runs one per-host deploy per Fleet entry, isolating failures. See Deploying a fleet.

Examples

# Local dry-run (safe to run anywhere)
punix service deploy WebStack --file pkgs/ --dry-run

# Real local deploy (needs root for /etc/systemd/system writes)
sudo punix service deploy WebStack --file pkgs/

# Remote deploy
punix service deploy WebStack \
  --file pkgs/ \
  --target ssh://deploy@prod.example.com \
  --key ~/.ssh/punix-deploy

# Rollback after a bad deploy
punix service rollback WebStack