From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from atuin.qyliss.net (localhost [IPv6:::1]) by atuin.qyliss.net (Postfix) with ESMTP id 5F0269A4E; Wed, 29 Oct 2025 15:48:47 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id 392449A44; Wed, 29 Oct 2025 15:48:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on atuin.qyliss.net X-Spam-Level: X-Spam-Status: No, score=-0.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DMARC_MISSING,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS autolearn=unavailable autolearn_force=no version=4.0.1 Received: from fout-b5-smtp.messagingengine.com (fout-b5-smtp.messagingengine.com [202.12.124.148]) by atuin.qyliss.net (Postfix) with ESMTPS id B872999D8 for ; Wed, 29 Oct 2025 15:48:41 +0000 (UTC) Received: from phl-compute-06.internal (phl-compute-06.internal [10.202.2.46]) by mailfout.stl.internal (Postfix) with ESMTP id BB4C01D00151; Wed, 29 Oct 2025 11:48:39 -0400 (EDT) Received: from phl-mailfrontend-02 ([10.202.2.163]) by phl-compute-06.internal (MEProxy); Wed, 29 Oct 2025 11:48:39 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=alyssa.is; h=cc :cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm2; t=1761752919; x=1761839319; bh=3pseeStqwC XJfJJguL9LF+pFrIiPS1vOCgItySaHxbM=; b=dVcc36qls3TjAvKWG7TMuyuKiN HUMCWWZ25Fg1ur02vk9bzTIW0lN6gNzG3vOU11KsILdC23AzmeQIk1qAIl4Tvj7p KGVmza5DiaVbkJgiYVAwAt/PXeVgYFkBadGGle3t3WRLLz5IYQhdPsTY1ZKoyvsA sTkAEKYCOMeky0snP553y5YUXVPgmuvcEGx3CkQKtFVyedaWVQGeCYxVnEwGErtt J/GEj4NgbApxwogQOrq8bO5qlb1SUqYN8J0vzRE2sqSOYe4znN/heCP82nCTsZJc rhAJXozmXwY/m3RDKDSx/KX2AY5QmfrI+jlJJIiGYSbsdH19xoY/O8VsnnWQ== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t= 1761752919; x=1761839319; bh=3pseeStqwCXJfJJguL9LF+pFrIiPS1vOCgI tySaHxbM=; b=2MNLGPaccWtGUfuGA7dBkHg494K7aQKcnTAMXDdrWMQ0vcCBPH3 exKJG6g4z6ojBi268Yp/G94wY5tb3toDOV1OZBReLFIQ8iTxDvROCEPBM1IvB58K jKCwav/BPs8lrbK+j6PoYN0SkNefpb7fE3Vbe0lGtMhASEoalmwQNlfbJUtDWJy2 cnwSyFW+O4QJUHM186YPAQPyrXktXZbQpSEwvT6RWr4suhwoUeq2I8Xwqw4ead6L qfCOnH53thCUaibKhebYVauKpUlgmQwnrOuOute708dLhqd6m4XM06DpW0FqkQRu Zthk5aP7+PRAGLGJsDYiQXMA9eMUamLQZsA== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeffedrtdeggdduieegudefucetufdoteggodetrf dotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfurfetoffkrfgpnffqhgenuceu rghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujf gurhephffvvefujghffffkgggtsehgtderredttdejnecuhfhrohhmpeetlhihshhsrgcu tfhoshhsuceohhhisegrlhihshhsrgdrihhsqeenucggtffrrghtthgvrhhnpeevtdelud duueejtedvkeefudetjeefheduueejffdtudeuveevudektddttdehleenucffohhmrghi nhepnhhonhdqvgigvggtuhhtrggslhgvrdhhohhsthdpshhpvggtthhruhhmqdhoshdroh hrghdpphhrohhvihguvghrshdrnhgvthenucevlhhushhtvghrufhiiigvpedtnecurfgr rhgrmhepmhgrihhlfhhrohhmpehhihesrghlhihsshgrrdhishdpnhgspghrtghpthhtoh epvddpmhhouggvpehsmhhtphhouhhtpdhrtghpthhtohepuggvmhhiohgsvghnohhurhes ghhmrghilhdrtghomhdprhgtphhtthhopeguvghvvghlsehsphgvtghtrhhumhdqohhsrd horhhg X-ME-Proxy: Feedback-ID: i12284293:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Wed, 29 Oct 2025 11:48:38 -0400 (EDT) Received: by fw12.qyliss.net (Postfix, from userid 1000) id 0D988521C5D; Wed, 29 Oct 2025 16:48:27 +0100 (CET) From: Alyssa Ross To: Demi Marie Obenour Subject: Re: [PATCH 7/7] Support updates via systemd-sysupdate In-Reply-To: <20251029-updates-v1-7-401c1be2a11b@gmail.com> References: <20251029-updates-v1-0-401c1be2a11b@gmail.com> <20251029-updates-v1-7-401c1be2a11b@gmail.com> Date: Wed, 29 Oct 2025 16:48:25 +0100 Message-ID: <87ikfxaeuu.fsf@alyssa.is> MIME-Version: 1.0 Content-Type: multipart/signed; boundary="=-=-="; micalg=pgp-sha512; protocol="application/pgp-signature" Message-ID-Hash: QDNJSD7BYJOFD2GHGUKRRQPETOWYLLYG X-Message-ID-Hash: QDNJSD7BYJOFD2GHGUKRRQPETOWYLLYG X-MailFrom: hi@alyssa.is X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-devel.spectrum-os.org-0; header-match-devel.spectrum-os.org-1; header-match-devel.spectrum-os.org-2; header-match-devel.spectrum-os.org-3; header-match-devel.spectrum-os.org-4; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Spectrum OS Development X-Mailman-Version: 3.3.9 Precedence: list List-Id: Patches and low-level development discussion Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Demi Marie Obenour writes: > Include a new 'update' command to update the system. This works as > follows: > > 1. Take a global, system-wide lock. > 2. Create a BTRFS subvolume for the sys.updates VM to write the updates. > 3. Bind-mount this subvolume into the VM's shared directory. > 4. Start sys.updates to get the updates. > 5. Wait for the VM to shut down. > 6. Take a BTRFS snapshot of the subvolume. > 7. Call syncfs() to flush all of the data on the subvolume. Why do we need to do this? > 8. Inspect the contents of the subvolume. > Check that everything is a regular file and that the names are reasona= ble. > Check that SHA256SUMS and SHA256SUMS.gpg are present. > 9. Call systemd-sysupdate to run the actual update. > > Signed-off-by: Demi Marie Obenour > --- > host/rootfs/Makefile | 8 ++- > host/rootfs/default.nix | 17 ++++--- > host/rootfs/file-list.mk | 5 ++ > host/rootfs/image/etc/fstab | 1 + > .../image/etc/sysupdate.d/50-verity.transfer | 21 ++++++++ > host/rootfs/image/etc/sysupdate.d/60-root.transfer | 21 ++++++++ > .../image/etc/sysupdate.d/70-kernel.transfer | 25 ++++++++++ > host/rootfs/image/usr/bin/run-update | 54 ++++++++++++++++= ++++ This doesn't seem to be used anywhere, and is an exact copy of run-appimage aside from being non-executable. > host/rootfs/image/usr/bin/update | 56 ++++++++++++++++= +++++ > host/rootfs/image/usr/bin/vm-start | 25 +++++++++- > host/rootfs/os-release.in | 13 +++++ > host/rootfs/os-release.in.license | 2 + > host/rootfs/shell.nix | 2 +- > update-signing-keys.gpg | 1 + > update-signing-keys.gpg.license | 2 + > update-url | 1 + > update-url.license | 2 + > vm/app/sysupdate.d/50-verity.transfer | 18 +++++++ > vm/app/sysupdate.d/60-root.transfer | 18 +++++++ > vm/app/sysupdate.d/70-kernel.transfer | 18 +++++++ > vm/app/updates.nix | 57 ++++++++++++++++= ++++++ This should be vm/app/updates/default.nix and vm/app/updates/sysupdate.d. > 21 files changed, 356 insertions(+), 11 deletions(-) > > diff --git a/host/rootfs/Makefile b/host/rootfs/Makefile > index 4712d9063e9f2e3c9b8b7b4fb2a7e54d119c6840..2faa1e46c1a3bbbdf31baf1e9= 72d9b4ecb389ae5 100644 > --- a/host/rootfs/Makefile > +++ b/host/rootfs/Makefile > @@ -10,6 +10,7 @@ include file-list.mk > dest =3D build/rootfs.erofs >=20=20 > DIRS =3D \ > + boot \ > dev \ > etc/s6-linux-init/env \ > etc/s6-linux-init/run-image/configs \ > @@ -47,11 +48,13 @@ DIRS =3D \ >=20=20 > FIFOS =3D etc/s6-linux-init/run-image/service/s6-svscan-log/fifo >=20=20 > -BUILD_FILES =3D build/etc/s6-rc > +BUILD_FILES =3D build/etc/s6-rc build/etc/os-release >=20=20 > $(dest): ../../scripts/make-erofs.sh $(PACKAGES_FILE) $(FILES) $(BUILD_F= ILES) build/empty build/fifo file-list.mk > + set -euo pipefail; \ > { \ > cat $(PACKAGES_FILE) ;\ > + printf '%s\n%s\n' ../../update-signing-keys.gpg /etc/systemd/import= -pubring.gpg; \ Probably should just be a normal file in image/etc. > for file in $(FILES) $(LINKS); do printf '%s\n%s\n' $$file "$${file= #image/}"; done ;\ > for file in $(BUILD_FILES); do printf '%s\n%s\n' $$file $${file#bui= ld/}; done ;\ > printf 'build/empty\n%s\n' $(DIRS) ;\ > @@ -99,6 +102,9 @@ debug: > $(VMLINUX) > .PHONY: debug >=20=20 > +build/etc/os-release: os-release.in build/etc > + sed 's#@VERSION@#$(VERSION)#g' < os-release.in > $@ > + > run: build/live.img $(EXT_FS) build/rootfs.verity.roothash ../../lib/kcm= dline-utils.mk > @set -x && \ > ext=3D"$$(mktemp build/spectrum-rootfs-extfs.XXXXXXXXXX.img)" && \ > diff --git a/host/rootfs/default.nix b/host/rootfs/default.nix > index cb39f0d77b6640198da3ab840a2c8ca7cc1c91a1..c412fe17f45bde79f1efa42ca= db29cfd5fbc3991 100644 > --- a/host/rootfs/default.nix > +++ b/host/rootfs/default.nix > @@ -8,10 +8,10 @@ import ../../lib/call-package.nix ( > }: > pkgsStatic.callPackage ( >=20=20 > -{ busybox, cloud-hypervisor, cryptsetup, dbus, erofs-utils, execline > -, inkscape, inotify-tools, iproute2, jq, lib, mdevd, nixos > -, runCommand, s6, s6-linux-init, s6-rc, socat, spectrum-host-tools > -, stdenvNoCC, util-linux, virtiofsd, writeClosure > +{ btrfs-progs, bash, busybox, cloud-hypervisor, cryptsetup, dbus > +, erofs-utils, execline, inkscape, inotify-tools, iproute2, jq, lib > +, mdevd, nixos, runCommand, s6, s6-linux-init, s6-rc, socat > +, spectrum-host-tools, stdenvNoCC, util-linux, virtiofsd, writeClosure > , xdg-desktop-portal-spectrum-host, xorg > }: > let > @@ -40,8 +40,8 @@ let > no_pgo_foot =3D foot.override { allowPgo =3D false; }; >=20=20 > packages =3D [ > - cloud-hypervisor crosvm cryptsetup dbus execline inotify-tools > - iproute2 jq mdevd s6 s6-linux-init s6-rc socat > + btrfs-progs cloud-hypervisor crosvm cryptsetup dbus execline > + inotify-tools iproute2 jq mdevd s6 s6-linux-init s6-rc socat > spectrum-host-tools virtiofsd xdg-desktop-portal-spectrum-host >=20=20 > (busybox.override { > @@ -90,6 +90,7 @@ let > appvm-firefox =3D callSpectrumPackage ../../vm/app/firefox.nix {}; > appvm-foot =3D callSpectrumPackage ../../vm/app/foot.nix {}; > appvm-gnome-text-editor =3D callSpectrumPackage ../../vm/app/gnome-t= ext-editor.nix {}; > + appvm-updates =3D callSpectrumPackage ../../vm/app/updates.nix {}; > }; >=20=20 > packagesSysroot =3D runCommand "packages-sysroot" { > @@ -135,13 +136,15 @@ stdenvNoCC.mkDerivation { > ../../lib/common.mk > ../../lib/kcmdline-utils.mk > ../../lib/verity.mk > + ../../lib/kcmdline-utils.mk Duplicate. > ../../scripts/make-erofs.sh > ../../version > + ../../update-signing-keys.gpg > ]); > }; > sourceRoot =3D "source/host/rootfs"; >=20=20 > - nativeBuildInputs =3D [ erofs-utils spectrum-build-tools s6-rc ]; > + nativeBuildInputs =3D [ erofs-utils spectrum-build-tools s6-rc bash bt= rfs-progs ]; What are these used for at build time? > diff --git a/host/rootfs/image/etc/sysupdate.d/50-verity.transfer b/host/= rootfs/image/etc/sysupdate.d/50-verity.transfer > new file mode 100644 > index 0000000000000000000000000000000000000000..07a698f3956e19f9f55efff52= db51128c16a5b56 > --- /dev/null > +++ b/host/rootfs/image/etc/sysupdate.d/50-verity.transfer > @@ -0,0 +1,21 @@ > +# SPDX-License-Identifier: CC0-1.0 > +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour > + > +# Uses example code from systemd man pages which is under MIT-0 > +# (no attribution required). > +[Transfer] > +ProtectVersion=3D%A > +Verify=3Dyes Defaults to yes, and is unlikely to change. > + > +[Source] > +Type=3Durl-file > +Path=3Dfile:///run/updater The docs for url-file say "referenced via a HTTP or HTTPS URL". Should we submit a PR to clarify file:// is also supported? AIUI Lennart is basically on board with our approach here. > +MatchPattern=3DSpectrum_OS_@v.verity > + > +[Target] > +Type=3Dpartition > +Path=3Dauto > +MatchPattern=3DSpectrum_OS_@v.verity > +MatchPartitionType=3Droot-verity > +PartitionFlags=3D0 > +ReadOnly=3D1 > diff --git a/host/rootfs/image/etc/sysupdate.d/70-kernel.transfer b/host/= rootfs/image/etc/sysupdate.d/70-kernel.transfer > new file mode 100644 > index 0000000000000000000000000000000000000000..6f75dfb04abf5ae911be3ae95= 318685321a86f5f > --- /dev/null > +++ b/host/rootfs/image/etc/sysupdate.d/70-kernel.transfer > @@ -0,0 +1,25 @@ > +# SPDX-License-Identifier: CC0-1.0 > +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour > + > +# Uses example code from systemd man pages which is under MIT-0 > +# (no attribution required). > +[Transfer] > +ProtectVersion=3D%A > +Verify=3Dyes > + > +[Source] > +Type=3Durl-file > +Path=3Dfile:///run/updater > +MatchPattern=3DSpectrum_OS_@v.efi > + > +[Target] > +Type=3Dregular-file > +Path=3D/EFI/Linux > +PathRelativeTo=3Dboot > +MatchPattern=3DSpectrum_OS_@v+@l-@d.efi \ > + Spectrum_OS_@v+@l.efi \ > + Spectrum_OS_@v.efi > +Mode=3D0644 > +TriesLeft=3D3 > +TriesDone=3D0 Boot counting would be cool, but maybe we should leave it out for now and implement it all at once later? (Or is this a complete implementation?) > diff --git a/host/rootfs/image/usr/bin/update b/host/rootfs/image/usr/bin= /update > new file mode 100755 > index 0000000000000000000000000000000000000000..8e147929cecbef5873cd02c94= 6adf1355da444c6 > --- /dev/null > +++ b/host/rootfs/image/usr/bin/update > @@ -0,0 +1,56 @@ > +#!/bin/execlineb -WS1 Oh TIL execlineb -W. We should probably set that in more places. > +# SPDX-License-Identifier: EUPL-1.2+ > +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour > + > +# Steps: > +# > +# 1. Take a global, system-wide lock. > +# 2. Create a BTRFS subvolume for the sys.updates VM to write the update= s. > +# 3. Bind-mount this subvolume into the VM's shared directory. > +# 4. Start sys.updates to get the updates. > +# 5. Wait for the VM to shut down. > +# 6. Take a BTRFS snapshot of the subvolume. > +# 7. Call syncfs() to flush all of the data on the subvolume. > +# 8. Inspect the contents of the subvolume. > +# Check that everything is a regular file and that the names are reas= onable. > +# Check that SHA256SUMS and SHA256SUMS.gpg are present. > +# 9. Call systemd-sysupdate to run the actual update. > + > +if { mkdir -p -m 0700 /run/updater } > +if { > + case $1 { > + /[0-9A-Za-z._/-]+ { true } > + } > + foreground { fdmove -c 1 2 echo 'Update directory path has forbidden c= haracters or is not absolute' } > + exit 1 > +} Why are we trying to protect against the user here? > +execline-cd $1 Just cd is fine. > +s6-setlock /run/update-lock > +foreground { > + # This might fail with a "File exists" error, but that is fine. > + foreground { redirfd -w 2 /dev/null btrfs subvolume create -- shared } > + if { umask 0022 mkdir -p shared/etc/systemd shared/update-destination } > + # TODO: use a safe copy program that is not vulnerable to symlink atta= cks. > + # This should be okay as the directory has not been shared yet, but be= tter > + # safe than sorry. Also nosymfollow should be a mitigation, but still, > + # better safe than sorry. If we think it's currently safe, I'd rather not have the comment. I don't like TODOs that end up sticking around forever. > + if { cp /etc/systemd/import-pubring.gpg shared/etc/systemd } Might as well bind mount this and save the copy? If we run in a namespace it'll be cleaned up when we exit. (Maybe I'm over-enthusiastic about bind mounts=E2=80=A6) > + if { Unnecessary if I think? > + if { > + backtick -E update_vm_id { > + backtick -E id_path { readlink /run/vm/by-name/sys.appvm-updates= } > + basename -- $id_path > + } > + vm-start $update_vm_id shared Okay, so I guess run-update is unused and included by default? > + } > + if { btrfs subvolume snapshot -- shared private } Can I suggest "snapshot" as the name? And a comment about why we do it would be nice. > + if { sync -- private } > + if { updates-dir-check private/update-destination } > + unshare --mount > + if { mount --bind -o ro -- private/update-destination /run/updater } > + /usr/lib/systemd/systemd-sysupdate update > + } > +} > +importas -i sysupdate_exit_status "?" No need to quote ? in execline. > diff --git a/host/rootfs/image/usr/bin/vm-start b/host/rootfs/image/usr/b= in/vm-start > index 67480e5215d8a8260ce3f03c67f71ba8f210c291..8ae8d94203345c4f3e8b6e46d= e0d139fda6c11d6 100755 > --- a/host/rootfs/image/usr/bin/vm-start > +++ b/host/rootfs/image/usr/bin/vm-start > @@ -1,6 +1,24 @@ > -#!/bin/execlineb -S1 > +#!/bin/execlineb -Ws0 > # SPDX-License-Identifier: EUPL-1.2+ > # SPDX-FileCopyrightText: 2022-2023, 2025 Alyssa Ross > +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour > + > +if { > + case "${#}" { > + 1 { true } > + 2 { > + multisubstitute { > + define sourcedir ${2} > + define fsdir /run/vm/by-id/${1}/fs/user > + } > + if { mkdir -p ${fsdir} } > + foreground { redirfd -w 2 /dev/null umount ${fsdir} } > + mount --bind -- ${sourcedir} ${fsdir} > + } > + } > + foreground { fdmove -c 1 2 echo "Bad number of arguments ${#} (expecte= d 1 or 3)" } > + exit 100 > +} >=20=20 > foreground { s6-rc -bu change vm-env } >=20=20 > @@ -20,4 +38,7 @@ foreground { > redirfd -w 2 /dev/null > s6-svwait -U /run/service/vmm/instance/${1} > } > -ch-remote --api-socket /run/vm/by-id/${1}/vmm boot > +if { ch-remote --api-socket /run/vm/by-id/${1}/vmm boot } > +case "${#}" { > + 2 { s6-svwait -D /run/service/vmm/instance/${1} } > +} Hmm. I don't think this belongs in vm-start. You should be able to interact with the fs directory before starting the VM, outside of vm-start. > diff --git a/host/rootfs/os-release.in b/host/rootfs/os-release.in > new file mode 100644 > index 0000000000000000000000000000000000000000..8a167a39366dedc6ff9024efd= b98383ec84618ec > --- /dev/null > +++ b/host/rootfs/os-release.in > @@ -0,0 +1,13 @@ > +NAME=3D"Spectrum OS" > +ID=3D"spectrum" The os-release(5) examples don't quote where unnecessary so let's follow that convention. > +PRETTY_NAME=3D"Spectrum OS @VERSION@" > +VERSION=3D@VERSION@ > +VERSION_ID=3D@VERSION@ > +IMAGE_ID=3Dspectrum_os_@VERSION@ Reading the documentation it doesn't look like a version is supposed to be included here, and that's what IMAGE_VERSION is for? > +IMAGE_VERSION=3D@VERSION@ > +RELEASE_TYPE=3Ddevelopment > +HOME_URL=3D"https://www.spectrum-os.org" No www is canonical. > diff --git a/host/rootfs/shell.nix b/host/rootfs/shell.nix > index bd234e90ee19bdfa6591d29c518cb0dc393b01c8..b5ed566062da03944567dd610= c88e1a58523e303 100644 > --- a/host/rootfs/shell.nix > +++ b/host/rootfs/shell.nix > @@ -3,7 +3,7 @@ > # SPDX-FileCopyrightText: 2022 Unikie >=20=20 > import ../../lib/call-package.nix ( > -{ callSpectrumPackage, rootfs, pkgsStatic, srcOnly, stdenv > +{ callSpectrumPackage, rootfs, srcOnly, stdenv > , btrfs-progs, cryptsetup, jq, netcat, qemu_kvm, reuse, util-linux > }: >=20=20 Good catch but doesn't belong in this change. > diff --git a/vm/app/sysupdate.d/50-verity.transfer b/vm/app/sysupdate.d/5= 0-verity.transfer > new file mode 100644 > index 0000000000000000000000000000000000000000..e437860426b8a651ca20ee7bd= dff1a9b3cf39507 > --- /dev/null > +++ b/vm/app/sysupdate.d/50-verity.transfer > @@ -0,0 +1,18 @@ > +# SPDX-License-Identifier: CC0-1.0 > +# SPDX-FileCopyrightText: 2025 Demi Marie Obenour > + > +# Uses example code from systemd man pages which is under MIT-0 > +# (no attribution required). > +[Transfer] > +Verify=3Dyes > + > +[Source] > +Type=3Durl-file > +Path=3D@UPDATE_URL@ > +MatchPattern=3DSpectrum_OS_@v.verity > + > +[Target] > +Type=3Dregular-file > +Path=3D/run/virtiofs/virtiofs0/user/update-destination What does "user" mean here? > diff --git a/vm/app/updates.nix b/vm/app/updates.nix > new file mode 100644 > index 0000000000000000000000000000000000000000..30beca30e578b5c869eaedf2f= d7e8913bf616a0c > --- /dev/null > +++ b/vm/app/updates.nix > @@ -0,0 +1,57 @@ > +# SPDX-License-Identifier: MIT > +# SPDX-FileCopyrightText: 2023 Alyssa Ross > + > +import ../../lib/call-package.nix ( > +{ callSpectrumPackage, lib, pkgsMusl, pkgsStatic, src, writeScript, syst= emd }: > + > +pkgsMusl.callPackage ( > +{ stdenvNoCC, curl }: App VMs are Glibc, so no need for this callPackage. > + > +pkgsStatic.callPackage ( > +{ execline, runCommand }: This looks vestigial. > + > +let > + raw_update_url =3D builtins.readFile ../../update-url; > + update-url =3D > + if builtins.match "^https?://([[:alnum:]:./?=3D~-]|%[[:xdigit:]]{2})= +/\n$" raw_update_url =3D=3D null then > + builtins.abort "Bad update URL" > + else > + builtins.substring 0 (builtins.stringLength raw_update_url - 1) ra= w_update_url; Let's just inline the URL here. We definitely do not need validations in Nix code. > + sysupdate-d =3D stdenvNoCC.mkDerivation { > + name =3D "spectrum-systemd-transfer-files"; > + src =3D ./.; > + installPhase =3D > + '' > + mkdir -- "$out" > + ( > + cd -- "$src" && > + for i in sysupdate.d/*.transfer; do > + s=3D''${i#sysupdate.d/} && > + sed 's,@UPDATE_URL@,${update-url},g' < "$i" > "$out/$s" || exit > + done > + printf %s\\n '${update-url}' > "$out/update-url" > + ) || exit > + ''; > + }; We have pkgs.substitute and friends for this. > + l =3D lib.escapeShellArgs; > + mountpoint =3D "/run/virtiofs/virtiofs0/user"; > + sysupdate-path =3D "${systemd}/lib/systemd/systemd-sysupdate"; > + runner =3D writeScript "update-run-script" ( > + "#!/bin/sh --\n" + > + builtins.concatStringsSep " && \\\n" [ > + (l ["mount" "-toverlay" "-olowerdir=3D${mountpoint}/etc:/etc" "--"= "overlay" "/etc"]) > + (l [sysupdate-path "--definitions=3D${sysupdate-d}" "update"]) > + (l ["${curl}/bin/curl" "-L" "--proto" "=3Dhttp,https" > + "-o" "${mountpoint}/update-destination/SHA256SUMS.gpg" > + "--" "${update-url}SHA256SUMS.gpg"]) > + (l ["${curl}/bin/curl" "-L" "--proto" "=3Dhttp,https" > + "-o" "${mountpoint}/update-destination/SHA256SUMS" > + "--" "${update-url}/SHA256SUMS"]) Why is this a shell script? > + ]); > +in > + > +callSpectrumPackage ../make-vm.nix {} { > + providers.net =3D [ "sys.netvm" ]; > + type =3D "nix"; > + run =3D "${runner}"; > +}) {}) {}) (_: {}) > > --=20 > 2.51.2 --=-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iHUEARYKAB0WIQQGoGac7QfI+H5ZtFCZddwkt31pFQUCaQI3SQAKCRCZddwkt31p FUzWAP46Zam0CGFBdQE5Rx+zHhl/VU8Wu8vPTGIRwS5hcMTJzwD+LPptCrf3yb5w GzebwRWqYE1aXm4JQ24NIQ3IZEuQIwQ= =/Esa -----END PGP SIGNATURE----- --=-=-=--