Repository navigation
v0.7.0
Changelog
Fixes found by rehearsing the whole lifecycle on rebuilt and unattended
machines. An unattended update now takes its pre-update backup, a timer runs
when it is installed rather than at the next boot, and a networked machine
pulls the image its backups read volumes through. A rebuilt machine needs no
init --repair after its import. A release that migrates with a service now
has a known database schema, and keeps a failed migration's last lines of
output in the error.
Upgrading changes no schema: the installation stays at 12, and a bundle built
for 0.6.0 installs unchanged. Five things behave differently:
installation importinstalls the systemd units, asinitdoes. On a host
running systemd where the manager does not run as root, it now fails at that
step;--install-units=falseopts out.- An
applyorupdatethat pulls the release's images from a registry also
pulls the pinned volume helper image, and anupdatepulls it before its
pre-update backup. A registry or mirror that does not carry it is a warning,
not a failure. - A release that migrates with a service and declares
database_schema_produceshas that schema recorded after its next
successful converge. The schema checks ofrollback,updateand the
unattended gate, skipped until now, then run against it, so an unattended
update that went ahead on 0.6.0 can now be held for a person. - Timers installed by 0.6.0 or earlier are enabled and not started, and
config setdoes not start them.morzer init --repair, or a reboot, does. release verifyprints a warning, and still exits 0, for a release that
migrates with a service and declares nodatabase_schema_produces.
No JSON output changed.
Fixed
- A release that migrates with a service never had a known database schema. A migration run as a one-shot container cannot report the schema it leaves, so the installed schema stayed 0, and
rollback,updateand the unattended gate skipped their schema checks. When a migration service succeeds and no step reported a schema, the release'sdatabase_schema_producesis now recorded as the schema it left. A schema a hook reports still wins over the declaration.release verifywarns, and still exits 0, when a release migrates with a service and declares nodatabase_schema_produces. (#143, RFC 0033) - A re-apply reset a known database schema to 0. The schema recorded after a converge came from that run's migrations alone, and a migration that reported none, such as one run as a service, recorded 0. So an
apply, including the one at every boot, could forget the schema an earlier migration had reported, androllback,updateand the unattended gate then skipped their schema checks. A converge of the installed release that reports no schema now keeps the recorded one. An update still records only what its migrations report, because a new release's migrations may have moved the schema. How a migration service reports the schema it leaves is proposed in RFC 0033. - A networked machine's first backup could refuse for want of the volume helper image. Backups read volumes through a pinned
busybox, and nothing pulled it:applypulled only the release's images, and a backup refuses rather than pulls on purpose. So unless somebody had acted ondoctor's warning, the first backup failed withthe volume helper image … is not on this machine, the pre-update backup included. Anapplyorupdatethat pulls the release's images from a registry now pulls the helper as well, and anupdatepulls it before its pre-update backup, so a machine that lost it, todocker image prune -afor example, is not refused. A failed helper pull is a warning and does not fail the operation. A release whose images all travel in the bundle pulls nothing, so an offline machine still preloads it by hand, asdoctorsays. - A failed migration service's output was lost unless
--verbosewas passed. Aruntime-servicemigrate step that exited non-zero reported only its exit code, and the hint sent the operator to a log that did not hold the output. The container is removed when it exits and the journal keeps no output, so a unit started by systemd, which runs without--verbose, lost the migration's error entirely. The error now quotes the last lines the container printed, as a failed hook's does, taken from both streams in the order they arrived, so a migration that reports its failure on stdout is not quoted as Compose's own progress on stderr. secret setexited 6 before the firstapply, though the value was stored.initmakes the release current, so the restart after a secret change rendered every secret the release declares, and refused over a required one the operator had not set yet. A release needing two values only the operator has could not be given the first without exit 6, which a script underset -ereads as the value not being saved.set,generate,rotateandeditnow restart nothing, and render nothing, when the deployment has no containers at all. When the render or the restart fails on a deployment that has them, the error now says the change was stored, and the exit code still says which failed.- A timer that
initorconfig setinstalled did not fire until the next reboot. The backup, update and fleet timers were enabled and never started, sosystemctl list-timersshowed no next run and the schedule an operator had just set waited for a boot. A timer is now started when it is enabled. The product's own service is still only enabled, because starting it runsapply --startup. A timer an operator disabled stays stopped. On a machine set up by an earlier version,morzer init --repairstarts its timers, and so does a reboot. - A failed
init --repairremoved the units it had found installed. When installing the units failed, the undo removed every unit the product manages rather than only what the failed install had created, so a timer that would not start, or anenablethat failed, took the product's service file with it. Only a completed install is undone now; a failed one already reverses its own changes. Separately, an install interrupted part-way now still stops and disables what it had started and enabled before removing the files it wrote. update --checkrefused on a machine installed from a registry until its first update.init --release oci://…recorded no release source, so the bare check saidthis installation has no recorded release source, even withupdate.channelset.initnow records the ref it installed from, asupdatedoes. A machine with no recorded source, or one that cannot list versions such as a local path, now checks the repository ofupdate.channelwhen one is set. A ref passed to--checkis still used as given. A machine installed before this change still has no recorded source; settingupdate.channel, or one update from a ref, gives it one.- Attestation counts mixed two units with more than one target.
doctorandattest pushcounted each statement once per target that lacked it, and reported that against a total of statements, so two targets after five operations read10 of 5 attestation(s) are only on this machine, and the push that closed the gap reported ten. Every count is now of statements:5 of 5 attestation(s) are missing from at least one of 2 targets, thenpushed 5 attestation(s) to 2 targets. With one target,doctorstill saysonly on this machine. The per-targetmissingandpushedfields ofattest push --jsonwere already per target and are unchanged. attest verify --against-livereported a migration service's image as missing. A release that migrates with one-shot services,flywayin a container for example, attests their images, and those services exit by design once the migrations are done. So the check failed with exit 3 on every healthy machine running such a release, and could not serve as a cron or CI gate. An image that only the release'smigrateservices run is no longer expected to be running. An image that a service the deployment starts also runs is still reported when nothing runs it.- A machine rebuilt by
installation importneeded aninit --repairnobody was told to run, and the remedydoctorprinted for it failed as printed. The import minted no signing key, so the firstupdateorrestoreminted one that installation state never recorded, and it installed no systemd units, so the service and the timers stayed missing. It now mints and records the signing key, keeping the lost machine's as its predecessor, and installs the units asinitdoes;--install-units=falseopts out. Separately,init --repairnow finds the installation the way every other command does, so--productis needed only on a machine with several, and secret state that already has a recovery recipient needs neither--recovery-recipientnor--no-recovery-recipient. (#135) - An unattended update could never take its pre-update backup.
update --unattended, which the update timer runs, did not wire the backup engine that a manualupdatewires. Withupdate.auto_applyon and the pre-update backup left on, every tick that found a release to install failed at that step withno backup engine is configured, exit 10. A tick now takes the same pre-update backup a manualupdatedoes.
Installing this release
curl -fsSL https://morzecrew.github.io/morzer/install.sh | sh -s -- --version 0.7.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.7.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