Repository navigation
v0.5.0
Changelog
Most of this release is about the data the manager decides to remove. A failed
update no longer deletes a secret the running release still reads,
backup --no-push no longer prunes the backup targets, and an operation queued
behind the deployment lock refuses a plan made for a release that has since
moved. Only the newest three pre-update backups are kept past retention, where
every one was, which filled the disk of a machine that updates often. A manifest that names an operation the manager
never runs, or gives a runtime-service step to anything but migrate, is
refused when it loads instead of doing nothing or failing at apply.
Notification targets are set with notify target add, and a migrate step is
told which operation is running it.
Upgrading moves the installation schema 11 → 12 on the first read and converts
nothing. Going back is not automatic, because a 0.4.x manager declines the
installation rather than dropping update.randomized_delay and
retention.pre_update_backups. Three more things change on upgrade:
- The first backup or update after upgrading prunes the pre-update backups
beyond the newest three, locally and on backup targets. To keep more, run
morzer config set retention.pre_update_backups=<n>straight after
upgrading, before the next scheduled backup or update. - A bundle that loaded under 0.4.0 may now be refused.
operationsmay name
onlymigrate,smoke_test,backupandrestore, and onlymigratemay
be aruntime-servicestep. Either mistake was a step that never ran or one
that failed every time it was reached. - A migrate step or smoke test that branched on
OPERATION_TYPE=applynow
seesupdateorrollbackon those operations, withPREVIOUS_VERSIONset.
Added
- A migration service is told what is running it. A
runtime-servicemigrate step received none of the hook ABI's variables, so it could not tell an update from a re-apply or learn the version it was migrating to. It now gets the ones that mean the same inside a container: the product, installation and operation ids,OPERATION_TYPE,PHASE,RELEASE_VERSION,PREVIOUS_VERSION,LOG_LEVELandDRY_RUN. Host paths andRESULT_FDare left out, so a service still reports its schema throughdatabase_schema_produces. backup.before_update: a dev-mode machine can stop taking pre-update backups. The installation'sskip_backup_before_updatewas honoured byupdatebut no command could set it, so a sandbox following a channel every ten minutes took a full backup before every update.morzer config set backup.before_update=falseturns it off on a dev-mode machine. A production machine refuses, because that backup is what a failed migration is recovered from;update --skip-backup --forcestill skips it for one update.update.randomized_delaysets how late an update tick may run. A production update timer always waited up to 1800 seconds at random, whateverupdate.schedulesaid, and a dev-mode one never did. Set a duration in whole seconds, such as10m, or0for none; unset keeps those defaults.morzer statusshows the delay beside the schedule.
Changed
- Only the newest pre-update backups are kept past retention. Every pre-update backup was exempt from pruning forever, so a machine that updates every few minutes kept a full backup per update until its disk filled. Now the newest three are exempt, and older ones are pruned like any other backup, locally and on backup targets. A successful update now applies retention too, after its pre-update backup, so a machine that only updates is pruned as well. The first backup or update after upgrading prunes the older ones already there, unless it is a backup run with
--no-prune. Change the three withmorzer config set retention.pre_update_backups=<n>; the newest is never pruned. Installation state moves to schema 12, so an older manager refuses it rather than dropping either setting. morzer notify target add|remove|list: notification targets are set by a command. The notifications page said to configure them ininstallation.yaml, which is a report the manager rewrites, and nothing else wrote them. A target is checked when it is added, and nothing is sent to it: the URL must behttpswith no password in it, and every secret it names must be set and well formed. A URL kept in a secret is named by the target's--namewherever it is shown.statusnames the targets, anddoctorwarns about one whose secret has gone, which was dropped with only a log line.
Fixed
morzer execpassed a stopped service's failure off as the command's. The check that the service is running and the exec itself are two calls, so a container could stop between them. Compose then exited 1 withservice "db" is not running, andexecexited 1 as if the command had failed. A failed command now checks the service again, and a service that is no longer running is refused with exit 7 and its state, as it is before the command runs. Whatever the command printed is still printed.morzer execrefused a scaled service whose first instance was down. The check read only the first instance listed, so a stoppedapp-1refused the command althoughapp-2was up and Compose would have run it there. A scaled service is now refused only when none of its instances is running.- A failed update could delete a secret the running release still reads. An update that failed before starting anything, on an image pull for example, left the old release's containers running against the new release's rendered secrets. Rendering removes any secret the release does not declare, so one only the old release declares was gone, and an old container that restarted could not read it. The update now renders the old release's secrets back as it rolls back. If that fails, the update stops at exit 12 instead of 11.
- An operation that waited for the deployment lock ran a plan made for a release no longer installed.
apply,update,rollback,backupandrestoreread the current release before taking the lock. With--wait, the operation they queued behind could move it, so an update queued behind another update to 1.3.0 journalledfrom 1.2.0and told its hooksPREVIOUS_VERSION=1.2.0, and anapplyqueued behind a rollback re-converged the release just rolled off. Each now reads the release again once it holds the lock, and refuses with exit 2 if it changed, naming the release now installed. So does a change to the database schema the release recorded, and, for a rollback without--to, a change to the previous release. Run the command again to plan against what is there now. - A migrate step and the smoke test were always told the operation was
apply.OPERATION_TYPEwasapplyandPREVIOUS_VERSIONwas absent on every run, so an update from 1.2.0 looked like a re-apply. They are now toldupdateorrollbackand the version being replaced. A first install is stillapply, as the hook ABI reference now says. backup --no-pushpruned the backup targets. A local-only backup copied nothing to the targets but still applied retention there, removing their oldest backups to make room for one that never arrived. Retention on a target now runs only when this run's backup reached it, as an update's already did.- A backport release would have replaced the installer at the site root with its older copy. Every docs release published
install.sh, and nowschemas/, at the site root, so tagging 0.3.5 after 0.4.0 would have served 0.3.5's installer and schemas to everyone. Only a release that moves the documentation'slatestalias publishes them now. The nightly check compares the published schemas with the newest release, as it already didinstall.sh. - The update timer fetched a private
oci://channel without credentials. systemd sets noHOMEfor the manager's units, and the registry client looked for the Docker configuration only underHOME, so it went anonymous and the registry refused it, whiledocker compose pullin the same run found root's login through the password database. The manager now finds the configuration the way thedockerCLI does:DOCKER_CONFIG, thenHOME, then the password database. - An operation under a name the manager never runs is refused.
operationsaccepted any name, so a misspelledsmoke-test:or an inventedpost_migrate:loaded cleanly and never ran, and the bundle's customer got no smoke test and no error.preflight, which the manifest reference listed as looked up, was never run either. A manifest may now declare onlymigrate,smoke_test,backupandrestore, and a bundle declaring any other operation,preflightincluded, is now refused with the field named and the four listed. The published manifest schema closes the names the same way, so an editor underlines one before the manager sees it. - The schema URL in every scaffolded manifest returned 404.
release newwrites ayaml-language-servermodeline naminghttps://morzecrew.github.io/morzer/schemas/selfhost-v1alpha1-manifest.json, which is also the schema's own$id, and nothing published the schemas there: the documentation site is versioned, and they lived only in the repository. Each docs release now publishesschemas/at the site root besideinstall.sh, so an editor following the modeline gets the schema. - The publishing page told you to configure signing keys by editing
installation.yaml. That file is a report the manager writes, and an edit to it changes nothing, so a machine set up from the page required no signature from your key. The page now showsinit --signing-key … --require-signatureandmorzer release trust add. The updating, backups, parameters and release-command pages treated the same file as configuration and are corrected too, and the hook ABI page no longer listspreflight,pre-updateandpost-updateas phases a hook runs in: they are reserved, and no release runs one. - A
runtime-servicesmoke test, backup or restore is refused when the bundle loads. Onlymigratecan run a one-shot container. The other three handed the step to the hook runner, which aruntime-servicestep gives no command, so aruntime-servicesmoke test failed everyapplythat reached it with an internal error, a restore failed the same way, and a backup was refused only once one ran. The manifest now refuses aruntime-serviceunder any operation butmigrate, naminghookas what the others support.
Security
- A refusal no longer sends a bundle's control characters to the terminal. A manifest, installation or secrets refusal names the field at fault, and a field under a map, such as an operation, a runtime or an extension, is named by its key as the bundle wrote it. A key carrying an escape sequence reached the terminal raw, so a release could clear the screen or rewrite what the operator read. A refusal holding a character that is not printable is now written escaped,
\x1brather than the character itself.
Installing this release
curl -fsSL https://morzecrew.github.io/morzer/install.sh | sh -s -- --version 0.5.0The script verifies the checksum always and the signature whenever
minisign is present; --require-signature makes a missing minisign fatal,
which is what a production runbook sets. --print-only shows everything it
detected and would do, and changes nothing. install.sh is an asset of this
release and is covered by SHA256SUMS below.
Verifying this release by hand
ARCHIVE=morzer_0.5.0_linux_amd64.tar.zst # the one you downloaded
curl -fsSLO https://raw.githubusercontent.com/morzecrew/morzer/main/morzer.pub
minisign -Vm SHA256SUMS -p morzer.pub
grep " ${ARCHIVE}$" SHA256SUMS | sha256sum -c -SHA256SUMS covers every architecture, so checking it whole fails on the
archives you did not download — and --ignore-missing, the usual way
around that, reports OK when no archive is present at all. Pulling out
the line for the file you have fails when there is nothing to check.
The signing key is the same for every release. If you have verified a
morzer release before, use the copy you already have rather than fetching
it again — a key that changes between releases is the thing worth noticing.
Release bundles are a separate artifact with their own signature and their
own key; see
https://morzecrew.github.io/morzer/reference/release-commands/#verification