commit f60b74f415f5435adf6f34158889f12465d501a6
parent 812e35b7b9e732f5d6b507063896631bc5ad29bf
Author: Daniel Barlow <dan@telent.net>
Date: Fri, 20 Dec 2024 00:05:07 +0000
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
Diffstat:
8 files changed, 132 insertions(+), 96 deletions(-)
diff --git a/NEWS b/NEWS
@@ -142,3 +142,13 @@ hardware.dts.includePaths.
The "new" hardware.dts.includes option is now for dtsi files which
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
+\ No newline at end of file
diff --git a/devices/turris-omnia/default.nix b/devices/turris-omnia/default.nix
@@ -172,8 +172,6 @@
../../modules/arch/arm.nix
../../modules/outputs/tftpboot.nix
../../modules/outputs/mbrimage.nix
- ../../modules/outputs/extlinux.nix
- ../../modules/outputs/system-configuration.nix
];
config = {
@@ -337,7 +335,7 @@
targets = ["ath9k" "ath10k_pci"];
};
in {
- defaultOutput = "systemConfiguration";
+ defaultOutput = "updater";
loadAddress = lim.parseInt "0x00800000"; # "0x00008000";
entryPoint = lim.parseInt "0x00800000"; # "0x00008000";
rootDevice = "/dev/mmcblk0p1";
diff --git a/doc/admin.rst b/doc/admin.rst
@@ -159,48 +159,26 @@ you need to mooun the pstore filesystem.
-Updating an installed system (JFFS2)
-************************************
-
-
-Adding packages
-===============
-
-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:
+Updating an installed system
+****************************
-Rebuilding the 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`.
-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.
+To use this, build the ``outputs.updater``
+target and then run the :command:`update.sh` script it generates.
.. code-block:: console
nix-build -I liminix-config=./my-configuration.nix \
--arg device "import ./devices/mydevice" \
- -A outputs.systemConfiguration
- ./result/install.sh root@the-device
+ -A outputs.updater
+ ./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
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
depends on them), but will not affect services that haven't changed.
-
It doesn't delete old packages automatically: to do that run
:command:`min-collect-garbage`, which will delete any packages not in
the current system closure. Note that Liminix does not have the NixOS
@@ -233,6 +210,26 @@ Caveats
.. _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
********************************
diff --git a/modules/outputs.nix b/modules/outputs.nix
@@ -14,6 +14,7 @@ in
./outputs/squashfs.nix
./outputs/vmroot.nix
./outputs/extlinux.nix
+ ./outputs/updater
];
options = {
system.outputs = {
diff --git a/modules/outputs/updater/default.nix b/modules/outputs/updater/default.nix
@@ -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
+ '';
+}
diff --git a/modules/outputs/updater/update.sh b/modules/outputs/updater/update.sh
@@ -0,0 +1,51 @@
+#!/usr/bin/env bash
+
+# this shell script is run on the build system to min-copy-closure the
+# system configuration onto the device and reboot/restart services as
+# requested
+
+die() {
+ echo "$@"
+ exit 1
+}
+
+
+PATH=@min_copy_closure@/bin:$PATH
+ssh_command=${SSH_COMMAND-ssh}
+
+reboot="reboot"
+case "$1" in
+ "--no-reboot")
+ unset reboot
+ shift
+ ;;
+ "--fast")
+ reboot="soft"
+ shift
+ ;;
+esac
+
+target_host=$1
+shift
+
+test -n "$target_host" || \
+ die "Usage: $0 [--no-reboot] [--fast] target-host"
+
+toplevel=$(realpath @toplevel@)
+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
+
+$ssh_command $target_host uname -a || die "Can't ssh to $target_host"
+min-copy-closure $target_host $toplevel
+set -x
+$ssh_command $target_host $toplevel/bin/install
+case "$reboot" in
+ reboot)
+ $ssh_command $target_host "sync; source /etc/profile; reboot"
+ ;;
+ soft)
+ $ssh_command $target_host $toplevel/bin/restart-services
+ ;;
+ *)
+ ;;
+esac
diff --git a/pkgs/systemconfig/build-system-install.sh b/pkgs/systemconfig/build-system-install.sh
@@ -1,53 +0,0 @@
-#!/usr/bin/env bash
-
-# this shell script can be run on the build system to
-# min-copy-closure the system configuration onto the device
-# and reboot/restart services as requested
-
-die() {
- echo "$@"
- 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
-
-ssh_command=${SSH_COMMAND-ssh}
-
-reboot="reboot"
-
-case "$1" in
- "--no-reboot")
- unset reboot
- shift
- ;;
- "--fast")
- reboot="soft"
- shift
- ;;
-esac
-
-target_host=$1
-shift
-
-test -n "$target_host" || \
- die "Usage: $0 [--no-reboot] [--fast] target-host"
-
-toplevel=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && readlink `pwd` )
-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
-
-min-copy-closure $target_host $toplevel
-set -x
-$ssh_command $target_host $toplevel/bin/install
-case "$reboot" in
- reboot)
- $ssh_command $target_host "sync; source /etc/profile; reboot"
- ;;
- soft)
- $ssh_command $target_host $toplevel/bin/restart-services
- ;;
- *)
- ;;
-esac
diff --git a/pkgs/systemconfig/default.nix b/pkgs/systemconfig/default.nix
@@ -83,11 +83,6 @@ in attrset:
$STRIP --remove-section=.note --remove-section=.comment --strip-all activate -o $out/bin/activate
ln -s ${s6-init-bin}/bin/init $out/bin/init
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
#!/bin/sh -e
prefix=\''${1-/}