punix service¶
Deploy and roll back service stacks.
Subcommands¶
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.
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— wheregen-NNN.jsonlives (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 usesfrom_vault.--activate— after the flip,systemctl daemon-reload+ restart the deployed units (an effect; ignored under--dry-run). Off ⇒ config only. See Activation.
Output¶
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;currentflipped.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.
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¶
Exit codes¶
0— flipped;currentnow points at gen-(prev).1—[E12]: no previous generation (currentis 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_switch → Transport.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:
→ 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
Related¶
- Composing a stack — how to write the PCL.
- The systemd service surface —
serviceConfig, timers, users. - Web & config generators · TLS · Stateful services.
- Activation — the
--activateflag. - Deploy over SSH · Deploying a fleet.
- Rollback · Secrets at deploy.