Commands¶
Every command is morzer <command> [flags]. The two command groups with their
own subcommands live on their own pages:
secret and release.
Every mutating command takes the deployment lock, journals what it did before
and after each step, and can be planned first with --dry-run. Every command
maps its failure onto a stable exit code.
Global flags¶
These are accepted by every command.
| Flag | Meaning |
|---|---|
--json |
Machine-readable output. stdout carries exactly one JSON object; narration moves to stderr. |
--dry-run |
Plan only; make no changes. Prints the step list and, where applicable, a configuration diff. |
--yes |
Assume yes for confirmations. Destructive actions still need --force. |
--force |
Confirm a destructive operation. It authorises destructive actions, not incorrect ones — a refusal on safety grounds is not overridden by it. |
--timeout |
Overall time budget for the operation, as a Go duration (30m, 2h). |
--verbose, -v |
Verbose output, including per-step detail and the subprocess log. |
--quiet, -q |
Errors only. |
--log-format |
text (default) or json. Logs always go to stderr. |
--no-color |
Disable colour. Equivalent to NO_COLOR or CLICOLOR=0 in the environment; the live renderer still draws, since every state carries a symbol too. |
--plain |
Line-oriented output; no interactive rendering. Already automatic under CI, systemd, TERM=dumb and without a terminal — see Output modes. |
--resume |
Continue an interrupted operation from where its journal left off. |
--wait |
Wait for the deployment lock instead of failing with exit 4. |
--config |
Path to an installation's installation.yaml, which selects that installation: /etc/demo/installation.yaml means the demo layout, and a path with a prefix means that prefix. Equivalent to --product (and --root); naming both is refused when they disagree. |
--product |
Product name. Inferred from the installation when omitted, and required on a host with more than one. |
Index¶
| Command | What it does |
|---|---|
init |
Create a new installation. |
apply |
Converge the system to the installed release. |
update |
Install a new release over the current one. |
rollback |
Return to the previous release. |
status |
Show what is deployed and whether it is working. |
doctor |
Run read-only diagnostics. |
backup |
Back up the database, files, configuration and secret state. |
restore |
Restore from a backup. |
version |
Print version, commit, and supported manifest API versions. |
config |
Read and change the release parameters. |
secret |
Manage the encrypted secret state. |
release |
Inspect and manage release bundles. |
installation |
Export and rebuild an installation's identity. |
init¶
Creates the directory layout, the machine's age identity, the installation configuration, the encrypted secret state and, optionally, the systemd units.
It never overwrites an existing installation, and it does not start the product:
run apply afterwards.
morzer init --release ./bundle --profile embedded --domain example.com \
--recovery-recipient age1...
| Flag | Meaning |
|---|---|
--release |
Release bundle to stage during init. The product name is taken from its manifest. |
--profile |
Deployment profile from the release manifest. |
--domain |
Public domain. Repeat for several; the first is canonical. |
--recovery-recipient |
Offline age public key that can also decrypt the secret state. |
--no-recovery-recipient |
Proceed without one. Losing this machine then loses its secrets. |
--generate-secrets |
Generate every secret the release declares a generator for. Default true. |
--install-units |
Install systemd units when systemd is available. Default true. |
--backup-schedule |
systemd OnCalendar expression for scheduled backups. |
--signing-key |
minisign public key a release signature must verify against. Repeat for several. |
--require-signature |
Refuse any release that is not signed by one of those keys. |
--product |
Product name, when no --release is given to take it from. |
--set |
Set a release parameter, as name=value. Repeat for several. Needs --release to validate against. See Parameters. |
--repair |
Restore missing directories on an existing installation. |
--mode |
What this machine is for: dev for a sandbox, or production (the default). Fixed at creation and never changeable — see unattended updates. |
The interactive first run¶
At a terminal, with something required still missing, init asks for it —
product name, deployment profile (offering what the release declares), domains,
and the recovery key, with an option to generate one on the spot.
It is a front-end over the flags and never a second path. It fills the same options the flags do, and prints the command line that would have produced the same result:
equivalent to:
morzer init \
--product demo \
--profile embedded \
--domain demo.example \
--recovery-recipient age1vm6ncva…
Put that in your provisioning script and you never need the wizard again, which is the point of printing it.
It never runs with --yes, --json or --quiet, without a terminal, or when
the command line already answers everything. A CI job, a systemd unit and a
scripted install all take the flags exactly as given.
--require-signature without --signing-key is refused: no bundle could
satisfy it, and a policy nothing can satisfy is a configuration error rather
than something to discover on the next update. Both are written into
installation.yaml under policy, and can be edited there afterwards.
Keep the recovery key off this machine
A recovery key stored on the machine it is meant to recover protects
nothing. init insists on one, or on --no-recovery-recipient said out
loud.
apply¶
Renders configuration and secrets, pulls images, runs migrations, starts services and waits for health.
Idempotent: applying an unchanged system runs nothing and says so. Each step
answers a Check before it runs, and a satisfied postcondition marks it skipped
rather than repeating the work.
| Flag | Meaning |
|---|---|
--profile |
Override the installation's deployment profile. |
--startup |
Boot-time mode: skip pulls when images are local, skip migrations when the schema is current. |
--startup is what the systemd unit uses. It exists so a machine rebooting
without network connectivity still comes back up.
update¶
Installs a new release over the current one.
Takes a bundle path, or --to <version> for a release already fetched into the
release store. A pre-update backup is taken by default.
morzer update ./bundle-1.3.0
morzer update --to 1.3.0
| Flag | Meaning |
|---|---|
--to |
Install a version already in the release store, instead of a bundle path. |
--digest |
Expected bundle content digest. A mismatch refuses the update. |
--profile |
Override the installation's deployment profile. |
--skip-backup |
Skip the pre-update backup. Requires --force and is recorded in the journal. |
--check |
Report whether a newer release exists, without installing anything. |
--stage |
Follow the configured channel: fetch and verify what it points at, without installing it. |
--unattended |
One scheduled tick: follow the channel, stage, and install only what declares a failure cannot need a database restore. This is what the update timer runs; see unattended updates. |
--check and --stage are alternatives, and both stop short of installing.
See following a channel for what
staging leaves behind and what a poll costs.
A failed update rolls back to the release that was running. The database is
never rolled back automatically: when a migration cannot be undone, the
release says so through compatibility.rollback_safe, and the answer is a
restore from the backup taken here.
rollback¶
Returns to the previous release.
It is not "update in reverse". It assesses three questions first — are the containers reversible, is the schema compatible, is a restore required — and refuses when the answers do not permit a safe return, naming the backup to restore from instead.
| Flag | Meaning |
|---|---|
--to |
Roll back to this installed version rather than the immediate previous one. |
Each rollback promotes the release it displaced to previous, so a second
rollback without --to returns to where the first started. Reaching a release
two steps back means naming it.
--force does not override a refusal. Force authorises destructive actions, not
incorrect ones, and the failure mode here is quiet data corruption rather than a
visible break.
status¶
Shows what is deployed, which services are up, the last backup, the last operation, and anything needing attention.
| Flag | Meaning |
|---|---|
--clear-intervention |
Acknowledge a requires-manual-intervention operation. An empty value selects the only one. |
--watch |
Refresh until interrupted. Needs a terminal. |
--interval |
How often --watch refreshes. Default 2s. |
An operation that ended in exit 12 keeps surfacing in status
and doctor until it is cleared explicitly. That is deliberate: the flag exists
to stop an operator proceeding as though nothing happened.
Watching¶
--watch redraws the status on a timer until you press q. It is the only view
that takes over the screen, and it restores what was there when it exits — there
is nothing in a repeatedly-redrawn table worth keeping in the scrollback.
It observes and never acts. No key restarts a service or clears an intervention: those take the deployment lock and are journaled, which makes them commands rather than keystrokes.
A refresh that fails leaves the last good reading on screen with the error underneath, because a runtime that briefly stops answering is exactly when the previous reading matters most. Refreshes never overlap: if one is still in flight when the timer fires, the tick is skipped rather than queued against a runtime that is already struggling.
It is refused without a terminal, rather than falling back to printing the table
in a loop — a --watch left in a unit file would otherwise fill a journal with
thousands of copies of the same output. For scripts, poll morzer status --json
instead.
doctor¶
Read-only diagnostics, with a suggested remedy for every non-ok result. It checks tool versions against what the release requires, the installation layout, the secret state, service and health status, disk headroom, and the journal.
Exits 3 when any check fails; warnings exit 0.
Three checks are advisory by design, and warn rather than fail:
| Check | What it means |
|---|---|
secrets.rotation |
A secret is older than the rotation_period its release declares. That period is the vendor's recommendation, and failing an exit code monitoring watches over a recommendation is how a team learns to ignore it. Secrets with no declared period are not mentioned at all. |
secrets.ephemeral-storage |
The directory decrypted secrets are written to is not tmpfs, so they touch disk and are not reliably erasable. A container with no tmpfs mounted is a legitimate way to run this. |
runtime.images-local |
Some of the release's pulled images are not present locally, so this machine would not come up without network access. Images that travel in the bundle are not counted here — they are either loaded or the deployment is refused, which is images.bundled below. See Installing without a network. |
The rotation remedy names the command that will actually work: secret rotate
for a secret the release declares a generator for, and secret set for one it
does not — pointing at rotate there would point at a command that fails.
One check about images does fail rather than warn:
| Check | What it means |
|---|---|
images.bundled |
An image the release marks from: bundle is not in the local image store. Fatal, and apply refuses on it: a bundled image is deployed under a tag the manager creates, and letting a converge proceed without it would send the deployment to the vendor's registry for whatever that tag pointed at. morzer release ingest loads it out of the bundle, with no network. |
backup¶
Coordinates the release's backup hook, wraps the result in a self-describing manifest, and verifies the checksums by re-reading what was written.
| Flag | Meaning |
|---|---|
--component |
Limit the backup to these components: database, files, config, secrets, manifest. |
--reason |
Why this backup was taken; recorded in its manifest. Default manual. |
--no-verify |
Skip re-reading the backup to check its checksums. |
--no-prune |
Skip applying the retention policy afterwards. |
--no-push |
Do not copy the backup to the configured targets; it stays only on this machine. |
--no-prune-remote |
Skip applying the retention policy on the targets. |
backup list¶
Lists backups, newest first.
| Flag | Meaning |
|---|---|
--remote |
List what is on the configured backup targets instead. |
--target |
List one target by URL, whether or not this installation configures it. |
--credentials-file |
YAML file holding the target's credentials, for a machine whose secret state is not readable yet. |
backup target¶
Manages where backups are kept besides this machine. See backup target URLs.
morzer backup target add <url> records a target, checking it answers first.
morzer backup target list shows them and whether each is reachable.
morzer backup target remove <url> stops using one and deletes nothing that is
already there.
| Flag | Meaning |
|---|---|
--credentials |
Name of a secret holding this target's credential document. |
backup push¶
Copies an existing backup to every configured target, verifying it again first. Takes a backup id; the most recent when omitted.
This is the retry for a push that failed. A backup whose push failed is still on this machine, verified and correct — what failed was the network or the medium, and the remedy should not be taking another backup.
backup fetch¶
Copies a backup down from a target into this machine's backup store, and verifies it. Takes a backup id; the newest on the target when omitted.
Restoring is a separate command on purpose: a backup that has come back from a bucket is one you should be able to look at before it overwrites a database.
| Flag | Meaning |
|---|---|
--target |
Target URL to fetch from; the installation's targets when omitted. |
--credentials-file |
YAML file holding the target's credentials, for a machine whose secret state is not readable yet. |
backup verify¶
Re-reads a backup and checks its checksums. Takes a backup id; locally, the most recent backup when omitted.
morzer backup verify 01J8ZP...
morzer backup verify --remote
With --remote it checks the copy on the configured targets instead, streaming
each component through a checksum and keeping nothing. A full transfer, and the
only thing that notices rot on a target.
Omitting the id means something different in each mode: locally it verifies the
most recent backup, and with --remote it verifies every backup on every
configured target, which is what a scheduled check wants.
| Flag | Meaning |
|---|---|
--remote |
Check the copy on the configured backup targets; a full transfer. |
--target |
Verify on one target by URL, whether or not this installation configures it. |
--credentials-file |
YAML file holding the target's credentials, for a machine whose secret state is not readable yet. |
restore¶
Restores from a backup.
Destructive: it requires --force and --confirm <installation-id>, typed
out. A restore that could be triggered by one mistyped command is a restore
waiting to destroy a production database.
| Flag | Meaning |
|---|---|
--backup |
Backup id. The most recent when omitted. |
--component |
Limit the restore to these components. |
--confirm |
The installation id, typed to confirm a destructive restore. |
--allow-cross-installation |
Restore a backup that belongs to a different installation. |
--allow-cross-installation is separate from --force because --force is
already required for every restore: using it for both would mean the
cross-installation guard was only ever checked after the one thing that disabled
it. Restoring another deployment's data is a distinct decision and gets its own
answer.
If the machine is a rebuild of the one the backup came from,
installation import is the
right answer instead — it restores the original id, so the guard never fires.
Restore declares that it requires manual intervention on failure: a half-restored database is a state no automatic action can repair, so a failure here exits 12 rather than pretending compensation succeeded.
version¶
Prints the manager version, the commit it was built from, and the manifest API versions it can read.
Under --json the supported API versions are a list, so a bundle author can
check compatibility programmatically rather than by trial and error.