1
0

add a new updater output

this is so that we don't have to obfuscate store paths in
systemConfiguration to avoid dragging in build system
deps.

breaking-ish change to workflows, docs updated
This commit is contained in:
Daniel Barlow 2024-12-20 00:05:07 +00:00
parent 812e35b7b9
commit f60b74f415
7 changed files with 86 additions and 51 deletions

10
NEWS
View File

@ -142,3 +142,13 @@ hardware.dts.includePaths.
The "new" hardware.dts.includes option is now for dtsi files which The "new" hardware.dts.includes option is now for dtsi files which
should be merged into the device tree. should be merged into the device tree.
2024-12-19
Incremental updates changed again (but not massively). From hereon in,
the preferred way to do an incremental update on an installed device
with a writable filesystem is to build the updater output
nix-build -I liminix-config=hosts/myhost.nix --argstr deviceName turris-omnia -A outputs.updater
and then run the generated `update.sh` script. See
https://www.liminix.org/doc/admin.html#updating-an-installed-system

View File

@ -172,8 +172,6 @@
../../modules/arch/arm.nix ../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix ../../modules/outputs/tftpboot.nix
../../modules/outputs/mbrimage.nix ../../modules/outputs/mbrimage.nix
../../modules/outputs/extlinux.nix
../../modules/outputs/system-configuration.nix
]; ];
config = { config = {
@ -337,7 +335,7 @@
targets = ["ath9k" "ath10k_pci"]; targets = ["ath9k" "ath10k_pci"];
}; };
in { in {
defaultOutput = "systemConfiguration"; defaultOutput = "updater";
loadAddress = lim.parseInt "0x00800000"; # "0x00008000"; loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
entryPoint = lim.parseInt "0x00800000"; # "0x00008000"; entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
rootDevice = "/dev/mmcblk0p1"; rootDevice = "/dev/mmcblk0p1";

View File

@ -159,48 +159,26 @@ you need to mooun the pstore filesystem.
Updating an installed system (JFFS2) Updating an installed system
************************************ ****************************
If your system has a writable root filesystem (JFFS2, btrfs etc -
anything but squashfs), we have mechanisms for in-places updates
analogous to :command:`nixos-rebuild`, but the operation is a bit
different because it expects to run on a build machine and then copy
to the host device using :command:`ssh`.
Adding packages To use this, build the ``outputs.updater``
=============== target and then run the :command:`update.sh` script it generates.
If your device is running a JFFS2 root filesystem, you can build
extra packages for it on your build system and copy them to the
device: any package in Nixpkgs or in the Liminix overlay is available
with the ``pkgs`` prefix:
.. code-block:: console
nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" -A pkgs.tcpdump
nix-shell -p min-copy-closure root@the-device result/
Note that this only copies the package to the device: it doesn't update
any profile to add it to ``$PATH``
.. _rebuilding the system:
Rebuilding the system
=====================
Liminix has a mechanism for in-place updates of a running system which
is analogous to :command:`nixos-rebuild`, but its operation is a
bit different because it expects to run on a build machine and then
copy to the host device. To use this, build the `outputs.systemConfiguration`
target and then run the :command:`result/install.sh` script it generates.
.. code-block:: console .. code-block:: console
nix-build -I liminix-config=./my-configuration.nix \ nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" \ --arg device "import ./devices/mydevice" \
-A outputs.systemConfiguration -A outputs.updater
./result/install.sh root@the-device ./result/bin/update.sh root@the-device
The install script uses min-copy-closure to copy new or changed The update script uses min-copy-closure to copy new or changed
packages to the device, then (perhaps) reboots it. The reboot packages to the device, then (perhaps) reboots it. The reboot
behaviour can be affected by flags: behaviour can be affected by flags:
@ -213,7 +191,6 @@ behaviour can be affected by flags:
the services that have updated store paths (and anything that the services that have updated store paths (and anything that
depends on them), but will not affect services that haven't changed. depends on them), but will not affect services that haven't changed.
It doesn't delete old packages automatically: to do that run It doesn't delete old packages automatically: to do that run
:command:`min-collect-garbage`, which will delete any packages not in :command:`min-collect-garbage`, which will delete any packages not in
the current system closure. Note that Liminix does not have the NixOS the current system closure. Note that Liminix does not have the NixOS
@ -233,6 +210,26 @@ Caveats
.. _levitate: .. _levitate:
Adding packages
===============
If you simply wish to add a package without any change to services,
you can call :command:`min-copy-closure` directly to install
any package in Nixpkgs or in the Liminix overlay
.. code-block:: console
nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" -A pkgs.tcpdump
nix-shell -p min-copy-closure root@the-device result/
Note that this only copies the package and its dependencies to the
device: it doesn't update any profile to add it to ``$PATH``
.. _rebuilding the system:
Reinstalling on a running system Reinstalling on a running system
******************************** ********************************

View File

@ -14,6 +14,7 @@ in
./outputs/squashfs.nix ./outputs/squashfs.nix
./outputs/vmroot.nix ./outputs/vmroot.nix
./outputs/extlinux.nix ./outputs/extlinux.nix
./outputs/updater
]; ];
options = { options = {
system.outputs = { system.outputs = {

View File

@ -0,0 +1,36 @@
{
config
, pkgs
, lib
, ...
}:
let
inherit (lib) mkIf;
o = config.system.outputs;
inherit (pkgs) runCommand;
inherit (lib) mkOption types;
inherit (pkgs.buildPackages) min-copy-closure;
in
{
imports = [ ../system-configuration.nix ];
options.system.outputs.updater = mkOption {
type = types.package;
description = ''
updater
******
For configurations with a writable filesystem, create a shell
script that runs on the build system and updates the device
over the network to the new configuration
'';
};
config.system.outputs.updater =
runCommand "buildUpdater" { } ''
mkdir -p $out/bin
substitute ${./update.sh} $out/bin/update.sh \
--subst-var-by toplevel ${o.systemConfiguration} \
--subst-var-by min_copy_closure ${min-copy-closure}
chmod +x $out/bin/update.sh
'';
}

View File

@ -1,22 +1,19 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# this shell script can be run on the build system to # this shell script is run on the build system to min-copy-closure the
# min-copy-closure the system configuration onto the device # system configuration onto the device and reboot/restart services as
# and reboot/restart services as requested # requested
die() { die() {
echo "$@" echo "$@"
exit 1 exit 1
} }
# add min-copy-closure to the path. removing junk characters
# inserted by default.nix (q.v.)
min_copy_closure=@min-copy-closure@; PATH=${min_copy_closure//_/}/bin:$PATH
PATH=@min_copy_closure@/bin:$PATH
ssh_command=${SSH_COMMAND-ssh} ssh_command=${SSH_COMMAND-ssh}
reboot="reboot" reboot="reboot"
case "$1" in case "$1" in
"--no-reboot") "--no-reboot")
unset reboot unset reboot
@ -34,10 +31,11 @@ shift
test -n "$target_host" || \ test -n "$target_host" || \
die "Usage: $0 [--no-reboot] [--fast] target-host" die "Usage: $0 [--no-reboot] [--fast] target-host"
toplevel=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && readlink `pwd` ) toplevel=$(realpath @toplevel@)
test -e $toplevel/etc/nix-store-paths || die "missing etc/nix-store-paths, is this really a system configuration?" test -e $toplevel/etc/nix-store-paths || die "missing etc/nix-store-paths, is this really a system configuration?"
echo installing from systemConfiguration $toplevel to host $target_host echo installing from systemConfiguration $toplevel to host $target_host
$ssh_command $target_host uname -a || die "Can't ssh to $target_host"
min-copy-closure $target_host $toplevel min-copy-closure $target_host $toplevel
set -x set -x
$ssh_command $target_host $toplevel/bin/install $ssh_command $target_host $toplevel/bin/install

View File

@ -83,11 +83,6 @@ in attrset:
$STRIP --remove-section=.note --remove-section=.comment --strip-all activate -o $out/bin/activate $STRIP --remove-section=.note --remove-section=.comment --strip-all activate -o $out/bin/activate
ln -s ${s6-init-bin}/bin/init $out/bin/init ln -s ${s6-init-bin}/bin/init $out/bin/init
cp -p ${writeFennel "restart-services" {} ./restart-services.fnl} $out/bin/restart-services cp -p ${writeFennel "restart-services" {} ./restart-services.fnl} $out/bin/restart-services
# obfuscate the store path of min-copy-closure so that the output
# closure doesn't include a bunch of build system stuff
f=${buildPackages.min-copy-closure}; f=$(echo $f | sed 's/\(.....\)/\1_/g')
substitute ${./build-system-install.sh} $out/install.sh --subst-var-by min-copy-closure $f
chmod +x $out/install.sh
cat > $out/bin/install <<EOF cat > $out/bin/install <<EOF
#!/bin/sh -e #!/bin/sh -e
prefix=\''${1-/} prefix=\''${1-/}