From a3e2a970f896821f75c9f57962953d77c4c5a39a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lars=20Sj=C3=B6strom?= <lars@radicore.se>
Date: Mon, 17 Mar 2025 10:18:30 +0100
Subject: [PATCH] chore: clean up

---
 flake.nix                                 |  80 +-
 pkgs/cert/default.nix                     |  17 +
 pkgs/image/default.nix                    | 149 +++-
 pkgs/image/mkimage.sh                     | 140 ---
 pkgs/kernel/default.nix                   |  20 +-
 pkgs/kernel/generic.config                |   7 +-
 pkgs/kernel/manual-config.nix             | 981 ++++++++++++----------
 pkgs/rootfs/default.nix                   |  38 -
 pkgs/rootfs/mkinitrd.nix                  |  67 +-
 pkgs/rootfs/mkinitrd.sh                   |  53 --
 pkgs/rootfs/{mkrootfs.sh => mkrootfs.nix} |  65 +-
 11 files changed, 845 insertions(+), 772 deletions(-)
 create mode 100644 pkgs/cert/default.nix
 delete mode 100644 pkgs/image/mkimage.sh
 delete mode 100644 pkgs/rootfs/default.nix
 delete mode 100644 pkgs/rootfs/mkinitrd.sh
 rename pkgs/rootfs/{mkrootfs.sh => mkrootfs.nix} (75%)

diff --git a/flake.nix b/flake.nix
index 5b1774f..2358ab1 100644
--- a/flake.nix
+++ b/flake.nix
@@ -22,22 +22,14 @@
       {
         packages = {
           default = patosPkgs.image;
-          image = pkgs.callPackage ./pkgs/image {
-            inherit patosPkgs;
-            inherit version;
-          };
-          rootfs = pkgs.callPackage ./pkgs/rootfs {
-            inherit patosPkgs;
-            inherit version;
-          };
-          initrd = pkgs.callPackage ./pkgs/rootfs/mkinitrd.nix {
-            inherit patosPkgs;
-            inherit version;
-          };
+          image = pkgs.callPackage ./pkgs/image { inherit patosPkgs version; };
+          rootfs = pkgs.callPackage ./pkgs/rootfs/mkrootfs.nix { inherit patosPkgs version; };
+          initrd = pkgs.callPackage ./pkgs/rootfs/mkinitrd.nix { inherit patosPkgs version; };
           kernel = pkgs.callPackage ./pkgs/kernel { };
           glibc = pkgs.callPackage ./pkgs/glibc { };
           busybox = pkgs.callPackage ./pkgs/busybox { };
           openssl = pkgs.callPackage ./pkgs/openssl { };
+          cert = pkgs.callPackage ./pkgs/cert { };
           kexec = pkgs.callPackage ./pkgs/kexec-tools { };
           lvm2 = pkgs.callPackage ./pkgs/lvm2 { };
           tpm2-tools = pkgs.callPackage ./pkgs/tpm2-tools { inherit patosPkgs; };
@@ -51,38 +43,38 @@
             name = "debug-tools";
             version = "0.0.1";
             packages = [
-                { drv = pkgs.curl; path = "bin/curl"; }
-                { drv = pkgs.bash; path = "bin/bash"; }
-                { drv = patosPkgs.glibc; path = "bin/ldd"; }
-                { drv = pkgs.keyutils; path = "bin/keyctl"; }
-                { drv = pkgs.gnutar; path = "bin/tar"; }
-                { drv = pkgs.binutils-unwrapped; path = "bin/strings"; }
-                { drv = pkgs.strace; path = "bin/strace"; }
-                { drv = patosPkgs.tpm2-tools; path = "bin/tpm2"; }
-                { drv = patosPkgs.openssl; path = "bin/openssl"; }
-                { drv = pkgs.cryptsetup; path = "bin/cryptsetup"; }
-                { drv = pkgs.cryptsetup; path = "bin/veritysetup"; }
-                { drv = pkgs.erofs-utils; path = "bin/mkfs.erofs"; }
-                # shared lib required for cryptsetup
-                { drv = pkgs.popt; path = "lib/libpopt.so.0.0.2"; }
-                { drv = pkgs.popt; path = "lib/libpopt.so.0"; }
-                { drv = pkgs.popt; path = "lib/libpopt.so"; }
-                # shared lib required for mkfs.erofs
-                { drv = pkgs.lz4.lib; path = "lib/liblz4.so.1.10.0"; }
-                { drv = pkgs.lz4.lib; path = "lib/liblz4.so.1"; }
-                { drv = pkgs.lz4.lib; path = "lib/liblz4.so"; }
-                # shared lib required for binutils
-                { drv = pkgs.binutils-unwrapped.lib; path = "lib/libsframe.so.1.0.0"; }
-                { drv = pkgs.binutils-unwrapped.lib; path = "lib/libsframe.so.1"; }
-                { drv = pkgs.binutils-unwrapped.lib; path = "lib/libbfd-2.43.1.so"; }
-                { drv = pkgs.binutils-unwrapped.lib; path = "lib/libbfd.so"; }
-                # shared lib required for strace
-                { drv = pkgs.elfutils.out; path = "lib/libdw-0.192.so"; }
-                { drv = pkgs.elfutils.out; path = "lib/libdw.so.1"; }
-                { drv = pkgs.elfutils.out; path = "lib/libdw.so"; }
-                { drv = pkgs.elfutils.out; path = "lib/libelf-0.192.so"; }
-                { drv = pkgs.elfutils.out; path = "lib/libelf.so.1"; }
-                { drv = pkgs.elfutils.out; path = "lib/libelf.so"; }
+              { drv = pkgs.curl; path = "bin/curl"; }
+              { drv = pkgs.bash; path = "bin/bash"; }
+              { drv = patosPkgs.glibc; path = "bin/ldd"; }
+              { drv = pkgs.keyutils; path = "bin/keyctl"; }
+              { drv = pkgs.gnutar; path = "bin/tar"; }
+              { drv = pkgs.binutils-unwrapped; path = "bin/strings"; }
+              { drv = pkgs.strace; path = "bin/strace"; }
+              { drv = patosPkgs.tpm2-tools; path = "bin/tpm2"; }
+              { drv = patosPkgs.openssl; path = "bin/openssl"; }
+              { drv = pkgs.cryptsetup; path = "bin/cryptsetup"; }
+              { drv = pkgs.cryptsetup; path = "bin/veritysetup"; }
+              { drv = pkgs.erofs-utils; path = "bin/mkfs.erofs"; }
+              # shared lib required for cryptsetup
+              { drv = pkgs.popt; path = "lib/libpopt.so.0.0.2"; }
+              { drv = pkgs.popt; path = "lib/libpopt.so.0"; }
+              { drv = pkgs.popt; path = "lib/libpopt.so"; }
+              # shared lib required for mkfs.erofs
+              { drv = pkgs.lz4.lib; path = "lib/liblz4.so.1.10.0"; }
+              { drv = pkgs.lz4.lib; path = "lib/liblz4.so.1"; }
+              { drv = pkgs.lz4.lib; path = "lib/liblz4.so"; }
+              # shared lib required for binutils
+              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libsframe.so.1.0.0"; }
+              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libsframe.so.1"; }
+              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libbfd-2.43.1.so"; }
+              { drv = pkgs.binutils-unwrapped.lib; path = "lib/libbfd.so"; }
+              # shared lib required for strace
+              { drv = pkgs.elfutils.out; path = "lib/libdw-0.192.so"; }
+              { drv = pkgs.elfutils.out; path = "lib/libdw.so.1"; }
+              { drv = pkgs.elfutils.out; path = "lib/libdw.so"; }
+              { drv = pkgs.elfutils.out; path = "lib/libelf-0.192.so"; }
+              { drv = pkgs.elfutils.out; path = "lib/libelf.so.1"; }
+              { drv = pkgs.elfutils.out; path = "lib/libelf.so"; }
             ];
           };
         };
diff --git a/pkgs/cert/default.nix b/pkgs/cert/default.nix
new file mode 100644
index 0000000..f3237e9
--- /dev/null
+++ b/pkgs/cert/default.nix
@@ -0,0 +1,17 @@
+{
+  runCommand,
+  pkgs,
+
+}:
+
+runCommand "patagia-certs"
+  {
+    buildInputs = with pkgs; [
+      openssl
+    ];
+
+  }
+  ''
+    mkdir -pv $out
+    openssl req -new -x509 -days 365 -nodes -out $out/cert.pem -keyout $out/key.pem -subj "/CN=patagia-signing"
+  ''
diff --git a/pkgs/image/default.nix b/pkgs/image/default.nix
index 5612185..7d5f565 100644
--- a/pkgs/image/default.nix
+++ b/pkgs/image/default.nix
@@ -1,16 +1,15 @@
 {
   pkgs,
-  stdenvNoCC,
   patosPkgs,
   version,
+  runCommand,
   ...
 }:
 let
   pname = "patos-image";
 in
-stdenvNoCC.mkDerivation (finalAttrs: {
+runCommand pname {
   inherit version;
-  inherit pname;
 
   buildInputs = with pkgs; [
     erofs-utils
@@ -27,12 +26,142 @@ stdenvNoCC.mkDerivation (finalAttrs: {
     SYSTEMD_REPART_MKFS_OPTIONS_EROFS = "--all-root"; # -zlz4hc,12 -C1048576 -Efragments,dedupe,ztailpacking";
   };
 
-  systemd = patosPkgs.systemd.out;
-  kernel = patosPkgs.kernel;
-  initrd = patosPkgs.initrd.out;
-  rootfs = patosPkgs.rootfs.out;
-
   kernelCmdLine = "console=ttyS0";
+}
+''
+mkdir -p $out/init.repart.d $out/final.repart.d $out/boot
+pushd $out
 
-  builder = ./mkimage.sh;
-})
+# Don't seem to work just to create a symlink to rootfs derivation?
+# ln -sf $rootfs rootfs
+mkdir rootfs
+cp -prP ${patosPkgs.rootfs}/* rootfs/
+find rootfs/ -type d -exec chmod 755 {} \;
+
+# set default target to multi-user
+ln -sf multi-user.target rootfs/usr/lib/systemd/system/default.target
+
+# enable dbus
+ln -sf ../dbus.service rootfs/usr/lib/systemd/system/multi-user.target.wants/dbus.service
+ln -sf ../dbus.socket rootfs/usr/lib/systemd/system/sockets.target.wants/dbus.socket
+
+# enable network services
+ln -sf ../systemd-networkd.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-networkd.service
+ln -sf ../systemd-resolved.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-resolved.service
+ln -sf ../systemd-timesyncd.service rootfs/usr/lib/systemd/system/multi-user.target.wants/systemd-timesyncd.service
+# enable default network config
+mv rootfs/usr/lib/systemd/network/89-ethernet.network.example rootfs/usr/lib/systemd/network/89-ethernet.network
+
+# enable confext/sysext services
+ln -sf ../systemd-confext.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-confext.service
+ln -sf ../systemd-sysext.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-sysext.service
+
+# Initial partitioning
+cat <<EOF > init.repart.d/10-root.conf
+[Partition]
+Type=root
+Format=erofs
+Minimize=best
+CopyFiles=/rootfs:/
+Verity=data
+VerityMatchKey=root
+SplitName=root
+EOF
+
+cat <<EOF > init.repart.d/20-root-verity.conf
+[Partition]
+Type=root-verity
+Verity=hash
+VerityMatchKey=root
+Minimize=best
+SplitName=verity
+EOF
+
+#TODO: Add verity signature partition
+
+${patosPkgs.systemd}/usr/bin/systemd-repart \
+  --no-pager \
+  --empty=create \
+  --size=auto \
+  --definitions=./init.repart.d \
+  --split=true \
+  --json=pretty \
+  --root=$out \
+  patos-$version.raw > init-repart-output.json && rm -f patos-$version.raw
+
+roothash=$(jq -r '.[0].roothash' init-repart-output.json)
+rootPart=$(jq -r '.[0].split_path' init-repart-output.json)
+rootUuid=$(jq -r '.[0].uuid' init-repart-output.json)
+
+verityPart=$(jq -r '.[1].split_path' init-repart-output.json)
+verityUuid=$(jq -r '.[1].uuid' init-repart-output.json)
+
+${patosPkgs.systemd}/usr/bin/ukify build \
+  --linux ${patosPkgs.kernel}/bzImage \
+  --initrd ${patosPkgs.initrd}/initrd.xz \
+  --os-release @rootfs/etc/os-release \
+  --cmdline "$kernelCmdLine roothash=$roothash" \
+  -o patos_${version}.efi
+
+# install ESP
+SYSTEMD_RELAX_ESP_CHECKS=1 ${patosPkgs.systemd}/usr/bin/bootctl install --root ./rootfs --esp-path /boot \
+  --secure-boot-auto-enroll=true --certificate=${patosPkgs.cert}/cert.pem --private-key=${patosPkgs.cert}/key.pem
+echo "timeout 2" > rootfs/boot/loader/loader.conf
+
+# sign EFIs
+${patosPkgs.systemd}/usr/lib/systemd/systemd-sbsign sign --certificate=${patosPkgs.cert}/cert.pem --private-key=${patosPkgs.cert}/key.pem \
+  rootfs/boot/EFI/BOOT/BOOTX64.EFI  --output=rootfs/boot/EFI/BOOT/BOOTX64.EFI
+
+${patosPkgs.systemd}/usr/lib/systemd/systemd-sbsign sign --certificate=${patosPkgs.cert}/cert.pem --private-key=${patosPkgs.cert}/key.pem \
+  patos_${version}.efi --output=patos_${version}.efi
+
+# install UKI
+cp patos_${version}.efi rootfs/boot/EFI/Linux
+
+echo "secure-boot-enroll force" >> rootfs/boot/loader/loader.conf
+
+# Final partitioning
+cat <<EOF > final.repart.d/10-esp.conf
+[Partition]
+Type=esp
+Format=vfat
+SizeMinBytes=160M
+SizeMaxBytes=160M
+CopyFiles=/rootfs/boot:/
+EOF
+
+cat <<EOF > final.repart.d/20-root.conf
+[Partition]
+Type=root
+Label=root-${version}
+CopyBlocks=/$rootPart
+UUID=$rootUuid
+SizeMinBytes=256M
+SizeMaxBytes=256M
+ReadOnly=1
+EOF
+
+cat <<EOF > final.repart.d/22-root-verity.conf
+[Partition]
+Type=root-verity
+Label=verity-${version}
+CopyBlocks=/$verityPart
+UUID=$verityUuid
+SizeMinBytes=10M
+SizeMaxBytes=10M
+ReadOnly=1
+EOF
+
+# finalize image ready for boot
+${patosPkgs.systemd}/usr/bin/systemd-repart \
+  --no-pager \
+  --empty=create \
+  --size=auto \
+  --definitions=./final.repart.d \
+  --root=$out \
+  patos-$version.raw > final-repart-output.json
+
+rm -rf rootfs
+
+popd
+''
diff --git a/pkgs/image/mkimage.sh b/pkgs/image/mkimage.sh
deleted file mode 100644
index 1d14349..0000000
--- a/pkgs/image/mkimage.sh
+++ /dev/null
@@ -1,140 +0,0 @@
-set -ex -o pipefail
-
-mkdir -p $out/init.repart.d $out/final.repart.d $out/boot
-pushd $out
-
-# Don't seem to work just to create a symlink to rootfs derivation?
-# ln -sf $rootfs rootfs
-mkdir rootfs
-cp -prP $rootfs/* rootfs/
-find rootfs/ -type d -exec chmod 755 {} \;
-
-# set default target to multi-user
-ln -sf multi-user.target rootfs/usr/lib/systemd/system/default.target
-
-# enable dbus
-ln -sf ../dbus.service rootfs/usr/lib/systemd/system/multi-user.target.wants/dbus.service
-ln -sf ../dbus.socket rootfs/usr/lib/systemd/system/sockets.target.wants/dbus.socket
-
-# enable network services
-ln -sf ../systemd-networkd.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-networkd.service
-ln -sf ../systemd-resolved.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-resolved.service
-ln -sf ../systemd-timesyncd.service rootfs/usr/lib/systemd/system/multi-user.target.wants/systemd-timesyncd.service
-# enable default network config
-mv rootfs/usr/lib/systemd/network/89-ethernet.network.example rootfs/usr/lib/systemd/network/89-ethernet.network
-
-# enable confext/sysext services
-ln -sf ../systemd-confext.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-confext.service
-ln -sf ../systemd-sysext.service rootfs/usr/lib/systemd/system/sysinit.target.wants/systemd-sysext.service
-
-# Initial partitioning
-cat <<EOF > init.repart.d/10-root.conf
-[Partition]
-Type=root
-Format=erofs
-Minimize=best
-CopyFiles=/rootfs:/
-Verity=data
-VerityMatchKey=root
-SplitName=root
-EOF
-
-cat <<EOF > init.repart.d/20-root-verity.conf
-[Partition]
-Type=root-verity
-Verity=hash
-VerityMatchKey=root
-Minimize=best
-SplitName=verity
-EOF
-
-#TODO: Add verity signature partition
-
-$systemd/usr/bin/systemd-repart \
-  --no-pager \
-  --empty=create \
-  --size=auto \
-  --definitions=./init.repart.d \
-  --split=true \
-  --json=pretty \
-  --root=$out \
-  patos-$version.raw > init-repart-output.json && rm -f patos-$version.raw
-
-roothash=$(jq -r '.[0].roothash' init-repart-output.json)
-rootPart=$(jq -r '.[0].split_path' init-repart-output.json)
-rootUuid=$(jq -r '.[0].uuid' init-repart-output.json)
-
-verityPart=$(jq -r '.[1].split_path' init-repart-output.json)
-verityUuid=$(jq -r '.[1].uuid' init-repart-output.json)
-
-$systemd/usr/bin/ukify build \
-  --linux $kernel/bzImage \
-  --initrd $initrd/initrd.xz \
-  --os-release @rootfs/etc/os-release \
-  --cmdline "$kernelCmdLine roothash=$roothash" \
-  -o patos_${version}.efi
-
-# Secure boot
-openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem -subj "/CN=patagia-signing"
-
-# install ESP
-SYSTEMD_RELAX_ESP_CHECKS=1 $systemd/usr/bin/bootctl install --root ./rootfs --esp-path /boot \
-  --secure-boot-auto-enroll=true --certificate=./cert.pem --private-key=./key.pem
-echo "timeout 2" > rootfs/boot/loader/loader.conf
-
-# sign EFIs
-$systemd/usr/lib/systemd/systemd-sbsign sign --certificate=./cert.pem --private-key=./key.pem \
-  rootfs/boot/EFI/BOOT/BOOTX64.EFI  --output=rootfs/boot/EFI/BOOT/BOOTX64.EFI
-
-$systemd/usr/lib/systemd/systemd-sbsign sign --certificate=./cert.pem --private-key=./key.pem \
-  patos_${version}.efi --output=patos_${version}.efi
-
-# install UKI
-cp patos_${version}.efi rootfs/boot/EFI/Linux
-
-echo "secure-boot-enroll force" >> rootfs/boot/loader/loader.conf
-
-# Final partitioning
-cat <<EOF > final.repart.d/10-esp.conf
-[Partition]
-Type=esp
-Format=vfat
-SizeMinBytes=160M
-SizeMaxBytes=160M
-CopyFiles=/rootfs/boot:/
-EOF
-
-cat <<EOF > final.repart.d/20-root.conf
-[Partition]
-Type=root
-Label=root-${version}
-CopyBlocks=/${rootPart}
-UUID=${rootUuid}
-SizeMinBytes=256M
-SizeMaxBytes=256M
-ReadOnly=1
-EOF
-
-cat <<EOF > final.repart.d/22-root-verity.conf
-[Partition]
-Type=root-verity
-Label=verity-${version}
-CopyBlocks=/${verityPart}
-UUID=${verityUuid}
-SizeMinBytes=10M
-SizeMaxBytes=10M
-ReadOnly=1
-EOF
-
-# finalize image ready for boot
-$systemd/usr/bin/systemd-repart \
-  --no-pager \
-  --empty=create \
-  --size=auto \
-  --definitions=./final.repart.d \
-  --root=$out \
-  patos-$version.raw > final-repart-output.json
-
-rm -rf rootfs
-
-popd
diff --git a/pkgs/kernel/default.nix b/pkgs/kernel/default.nix
index edbfb65..a5f24db 100644
--- a/pkgs/kernel/default.nix
+++ b/pkgs/kernel/default.nix
@@ -3,13 +3,13 @@ let
   version = "6.13.7";
   hash = "sha256-Ojm2IDi3rC9D0mofhLQoPhl4BOHoF61jfpo9h0xHgB0=";
 in
-  (pkgs.callPackage ./manual-config.nix {}) {
-    version = "${version}-patos1";
-    modDirVersion = version;
-    src = pkgs.fetchurl {
-      url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${version}.tar.xz";
-      hash = hash;
-    };
-    configfile = ./generic.config;
-    allowImportFromDerivation = true;
-  }
+(pkgs.callPackage ./manual-config.nix { }) {
+  version = "${version}-patos1";
+  modDirVersion = version;
+  src = pkgs.fetchurl {
+    url = "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${version}.tar.xz";
+    hash = hash;
+  };
+  configfile = ./generic.config;
+  allowImportFromDerivation = true;
+}
diff --git a/pkgs/kernel/generic.config b/pkgs/kernel/generic.config
index 647bf91..048421b 100644
--- a/pkgs/kernel/generic.config
+++ b/pkgs/kernel/generic.config
@@ -522,10 +522,6 @@ CONFIG_DEBUG_BUGVERBOSE=y
 CONFIG_DEBUG_ENTRY=y
 CONFIG_DEBUG_FS_ALLOW_ALL=y
 CONFIG_DEBUG_FS=y
-#CONFIG_DEBUG_INFO_BTF_MODULES=y
-#CONFIG_DEBUG_INFO_BTF=y
-#CONFIG_DEBUG_INFO_COMPRESSED_NONE=y
-#CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
 CONFIG_DEBUG_INFO=n
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_LIST=y
@@ -1401,9 +1397,8 @@ CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_SIG=y
-CONFIG_MODULE_SIG_FORCE=n
+CONFIG_MODULE_SIG_FORCE=y
 CONFIG_MODULE_SIG_ALL=y
-CONFIG_MODULE_SIG_KEY="certs/signing_key.pem"
 CONFIG_MODULES_TREE_LOOKUP=y
 CONFIG_MODULES_USE_ELF_RELA=y
 CONFIG_MODULES=y
diff --git a/pkgs/kernel/manual-config.nix b/pkgs/kernel/manual-config.nix
index ffcf758..9f1ba99 100644
--- a/pkgs/kernel/manual-config.nix
+++ b/pkgs/kernel/manual-config.nix
@@ -1,465 +1,576 @@
-{ lib, stdenv, buildPackages, runCommand, nettools, bc, bison, flex, perl, rsync, gmp, libmpc, mpfr, openssl
-, cpio, elfutils, hexdump, zstd, python3Minimal, zlib, pahole, kmod, ubootTools
-, fetchpatch
-, rustc, rust-bindgen, rustPlatform
+{
+  lib,
+  stdenv,
+  buildPackages,
+  runCommand,
+  nettools,
+  bc,
+  bison,
+  flex,
+  perl,
+  rsync,
+  gmp,
+  libmpc,
+  mpfr,
+  openssl,
+  cpio,
+  elfutils,
+  hexdump,
+  zstd,
+  python3Minimal,
+  zlib,
+  pahole,
+  kmod,
+  ubootTools,
+  fetchpatch,
+  rustc,
+  rust-bindgen,
+  rustPlatform,
 }:
 
 let
   lib_ = lib;
   stdenv_ = stdenv;
 
-  readConfig = configfile: import (runCommand "config.nix" {} ''
-    echo "{" > "$out"
-    while IFS='=' read key val; do
-      [ "x''${key#CONFIG_}" != "x$key" ] || continue
-      no_firstquote="''${val#\"}";
-      echo '  "'"$key"'" = "'"''${no_firstquote%\"}"'";' >> "$out"
-    done < "${configfile}"
-    echo "}" >> $out
-  '').outPath;
-in lib.makeOverridable ({
-  # The kernel version
-  version,
-  # The kernel pname (should be set for variants)
-  pname ? "linux",
-  # Position of the Linux build expression
-  pos ? null,
-  # Additional kernel make flags
-  extraMakeFlags ? [],
-  # The name of the kernel module directory
-  # Needs to be X.Y.Z[-extra], so pad with zeros if needed.
-  modDirVersion ? null /* derive from version */,
-  # The kernel source (tarball, git checkout, etc.)
-  src,
-  # a list of { name=..., patch=..., extraConfig=...} patches
-  kernelPatches ? [],
-  # The kernel .config file
-  configfile,
-  # Manually specified nixexpr representing the config
-  # If unspecified, this will be autodetected from the .config
-  config ? lib.optionalAttrs allowImportFromDerivation (readConfig configfile),
-  # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
-  # automatically extended with extra per-version and per-config values.
-  randstructSeed ? "",
-  # Extra meta attributes
-  extraMeta ? {},
-
-  # for module compatibility
-  isZen      ? false,
-  isLibre    ? false,
-  isHardened ? false,
-
-  # Whether to utilize the controversial import-from-derivation feature to parse the config
-  allowImportFromDerivation ? false,
-  # ignored
-  features ? null, lib ? lib_, stdenv ? stdenv_,
-}:
-
-let
-  # Provide defaults. Note that we support `null` so that callers don't need to use optionalAttrs,
-  # which can lead to unnecessary strictness and infinite recursions.
-  modDirVersion_ = if modDirVersion == null then lib.versions.pad 3 version else modDirVersion;
+  readConfig =
+    configfile:
+    import
+      (runCommand "config.nix" { } ''
+        echo "{" > "$out"
+        while IFS='=' read key val; do
+          [ "x''${key#CONFIG_}" != "x$key" ] || continue
+          no_firstquote="''${val#\"}";
+          echo '  "'"$key"'" = "'"''${no_firstquote%\"}"'";' >> "$out"
+        done < "${configfile}"
+        echo "}" >> $out
+      '').outPath;
 in
-let
-  # Shadow the un-defaulted parameter; don't want null.
-  modDirVersion = modDirVersion_;
-  inherit (lib)
-    hasAttr getAttr optional optionals optionalString optionalAttrs maintainers platforms;
+lib.makeOverridable (
+  {
+    # The kernel version
+    version,
+    # The kernel pname (should be set for variants)
+    pname ? "linux",
+    # Position of the Linux build expression
+    pos ? null,
+    # Additional kernel make flags
+    extraMakeFlags ? [ ],
+    # The name of the kernel module directory
+    # Needs to be X.Y.Z[-extra], so pad with zeros if needed.
+    modDirVersion ? null, # derive from version
+    # The kernel source (tarball, git checkout, etc.)
+    src,
+    # a list of { name=..., patch=..., extraConfig=...} patches
+    kernelPatches ? [ ],
+    # The kernel .config file
+    configfile,
+    # Manually specified nixexpr representing the config
+    # If unspecified, this will be autodetected from the .config
+    config ? lib.optionalAttrs allowImportFromDerivation (readConfig configfile),
+    # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
+    # automatically extended with extra per-version and per-config values.
+    randstructSeed ? "",
+    # Extra meta attributes
+    extraMeta ? { },
 
-  drvAttrs = config_: kernelConf: kernelPatches: configfile:
-    let
-      # Folding in `ubootTools` in the default nativeBuildInputs is problematic, as
-      # it makes updating U-Boot cumbersome, since it will go above the current
-      # threshold of rebuilds
-      #
-      # To prevent these needless rounds of staging for U-Boot builds, we can
-      # limit the inclusion of ubootTools to target platforms where uImage *may*
-      # be produced.
-      #
-      # This command lists those (kernel-named) platforms:
-      #     .../linux $ grep -l uImage ./arch/*/Makefile | cut -d'/' -f3 | sort
-      #
-      # This is still a guesstimation, but since none of our cached platforms
-      # coincide in that list, this gives us "perfect" decoupling here.
-      linuxPlatformsUsingUImage = [
-        "arc"
-        "arm"
-        "csky"
-        "mips"
-        "powerpc"
-        "sh"
-        "sparc"
-        "xtensa"
-      ];
-      needsUbootTools =
-        lib.elem stdenv.hostPlatform.linuxArch linuxPlatformsUsingUImage
+    # for module compatibility
+    isZen ? false,
+    isLibre ? false,
+    isHardened ? false,
+
+    # Whether to utilize the controversial import-from-derivation feature to parse the config
+    allowImportFromDerivation ? false,
+    # ignored
+    features ? null,
+    lib ? lib_,
+    stdenv ? stdenv_,
+  }:
+
+  let
+    # Provide defaults. Note that we support `null` so that callers don't need to use optionalAttrs,
+    # which can lead to unnecessary strictness and infinite recursions.
+    modDirVersion_ = if modDirVersion == null then lib.versions.pad 3 version else modDirVersion;
+  in
+  let
+    # Shadow the un-defaulted parameter; don't want null.
+    modDirVersion = modDirVersion_;
+    inherit (lib)
+      hasAttr
+      getAttr
+      optional
+      optionals
+      optionalString
+      optionalAttrs
+      maintainers
+      platforms
       ;
 
-      config = let attrName = attr: "CONFIG_" + attr; in {
-        isSet = attr: hasAttr (attrName attr) config;
+    drvAttrs =
+      config_: kernelConf: kernelPatches: configfile:
+      let
+        # Folding in `ubootTools` in the default nativeBuildInputs is problematic, as
+        # it makes updating U-Boot cumbersome, since it will go above the current
+        # threshold of rebuilds
+        #
+        # To prevent these needless rounds of staging for U-Boot builds, we can
+        # limit the inclusion of ubootTools to target platforms where uImage *may*
+        # be produced.
+        #
+        # This command lists those (kernel-named) platforms:
+        #     .../linux $ grep -l uImage ./arch/*/Makefile | cut -d'/' -f3 | sort
+        #
+        # This is still a guesstimation, but since none of our cached platforms
+        # coincide in that list, this gives us "perfect" decoupling here.
+        linuxPlatformsUsingUImage = [
+          "arc"
+          "arm"
+          "csky"
+          "mips"
+          "powerpc"
+          "sh"
+          "sparc"
+          "xtensa"
+        ];
+        needsUbootTools = lib.elem stdenv.hostPlatform.linuxArch linuxPlatformsUsingUImage;
 
-        getValue = attr: if config.isSet attr then getAttr (attrName attr) config else null;
+        config =
+          let
+            attrName = attr: "CONFIG_" + attr;
+          in
+          {
+            isSet = attr: hasAttr (attrName attr) config;
 
-        isYes = attr: (config.getValue attr) == "y";
+            getValue = attr: if config.isSet attr then getAttr (attrName attr) config else null;
 
-        isNo = attr: (config.getValue attr) == "n";
+            isYes = attr: (config.getValue attr) == "y";
 
-        isModule = attr: (config.getValue attr) == "m";
+            isNo = attr: (config.getValue attr) == "n";
 
-        isEnabled = attr: (config.isModule attr) || (config.isYes attr);
+            isModule = attr: (config.getValue attr) == "m";
 
-        isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
-      } // config_;
+            isEnabled = attr: (config.isModule attr) || (config.isYes attr);
 
-      isModular = config.isYes "MODULES";
-      withRust = config.isYes "RUST";
+            isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
+          }
+          // config_;
 
-      buildDTBs = kernelConf.DTB or false;
+        isModular = config.isYes "MODULES";
+        withRust = config.isYes "RUST";
 
-      # Dependencies that are required to build kernel modules
-      moduleBuildDependencies = [
-        pahole
-        perl
-        elfutils
-        # module makefiles often run uname commands to find out the kernel version
-        (buildPackages.deterministic-uname.override { inherit modDirVersion; })
-      ]
-      ++ optional (lib.versionAtLeast version "5.13") zstd
-      ++ optionals withRust [ rustc rust-bindgen ]
-      ;
+        buildDTBs = kernelConf.DTB or false;
 
-    in (optionalAttrs isModular { outputs = [ "out" "dev" ]; }) // {
-      passthru = rec {
-        inherit version modDirVersion config kernelPatches configfile
-          moduleBuildDependencies stdenv;
-        inherit isZen isHardened isLibre withRust;
-        isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
-        baseVersion = lib.head (lib.splitString "-rc" version);
-        kernelOlder = lib.versionOlder baseVersion;
-        kernelAtLeast = lib.versionAtLeast baseVersion;
+        # Dependencies that are required to build kernel modules
+        moduleBuildDependencies =
+          [
+            pahole
+            perl
+            elfutils
+            # module makefiles often run uname commands to find out the kernel version
+            (buildPackages.deterministic-uname.override { inherit modDirVersion; })
+          ]
+          ++ optional (lib.versionAtLeast version "5.13") zstd
+          ++ optionals withRust [
+            rustc
+            rust-bindgen
+          ];
+
+      in
+      (optionalAttrs isModular {
+        outputs = [
+          "out"
+          "dev"
+        ];
+      })
+      // {
+        passthru = rec {
+          inherit
+            version
+            modDirVersion
+            config
+            kernelPatches
+            configfile
+            moduleBuildDependencies
+            stdenv
+            ;
+          inherit
+            isZen
+            isHardened
+            isLibre
+            withRust
+            ;
+          isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
+          baseVersion = lib.head (lib.splitString "-rc" version);
+          kernelOlder = lib.versionOlder baseVersion;
+          kernelAtLeast = lib.versionAtLeast baseVersion;
+        };
+
+        inherit src;
+
+        depsBuildBuild = [ buildPackages.stdenv.cc ];
+        nativeBuildInputs =
+          [
+            bison
+            flex
+            perl
+            bc
+            nettools
+            openssl
+            rsync
+            gmp
+            libmpc
+            mpfr
+            elfutils
+            zstd
+            python3Minimal
+            kmod
+            hexdump
+          ]
+          ++ optional needsUbootTools ubootTools
+          ++ optionals (lib.versionAtLeast version "5.2") [
+            cpio
+            pahole
+            zlib
+          ]
+          ++ optionals withRust [
+            rustc
+            rust-bindgen
+          ];
+
+        RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
+
+        # avoid leaking Rust source file names into the final binary, which adds
+        # a false dependency on rust-lib-src on targets with uncompressed kernels
+        KRUSTFLAGS = lib.optionalString withRust "--remap-path-prefix ${rustPlatform.rustLibSrc}=/";
+
+        # patches =
+        #   map (p: p.patch) kernelPatches
+        #   # Required for deterministic builds along with some postPatch magic.
+        #   ++ optional (lib.versionOlder version "5.19") ./randstruct-provide-seed.patch
+        #   ++ optional (lib.versionAtLeast version "5.19") ./randstruct-provide-seed-5.19.patch
+        #   # Linux 5.12 marked certain PowerPC-only symbols as GPL, which breaks
+        #   # OpenZFS; this was fixed in Linux 5.19 so we backport the fix
+        #   # https://github.com/openzfs/zfs/pull/13367
+        #   ++ optional (lib.versionAtLeast version "5.12" &&
+        #                lib.versionOlder version "5.19" &&
+        #                stdenv.hostPlatform.isPower)
+        #     (fetchpatch {
+        #       url = "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/patch/?id=d9e5c3e9e75162f845880535957b7fd0b4637d23";
+        #       hash = "sha256-bBOyJcP6jUvozFJU0SPTOf3cmnTQ6ZZ4PlHjiniHXLU=";
+        #     });
+
+        postPatch = ''
+          # Ensure that depmod gets resolved through PATH
+          sed -i Makefile -e 's|= /sbin/depmod|= depmod|'
+
+          # Some linux-hardened patches now remove certain files in the scripts directory, so the file may not exist.
+          [[ -f scripts/ld-version.sh ]] && patchShebangs scripts/ld-version.sh
+
+          # Set randstruct seed to a deterministic but diversified value. Note:
+          # we could have instead patched gen-random-seed.sh to take input from
+          # the buildFlags, but that would require also patching the kernel's
+          # toplevel Makefile to add a variable export. This would be likely to
+          # cause future patch conflicts.
+          # for file in scripts/gen-randstruct-seed.sh scripts/gcc-plugins/gen-random-seed.sh; do
+          #   if [ -f "$file" ]; then
+          #     substituteInPlace "$file" \
+          #       --replace NIXOS_RANDSTRUCT_SEED \
+          #       $(echo ${randstructSeed}${src} ${placeholder "configfile"} | sha256sum | cut -d ' ' -f 1 | tr -d '\n')
+          #     break
+          #   fi
+          # done
+
+          patchShebangs scripts
+
+          # also patch arch-specific install scripts
+          for i in $(find arch -name install.sh); do
+              patchShebangs "$i"
+          done
+
+          # unset $src because the build system tries to use it and spams a bunch of warnings
+          # see: https://github.com/torvalds/linux/commit/b1992c3772e69a6fd0e3fc81cd4d2820c8b6eca0
+          unset src
+        '';
+
+        configurePhase = ''
+          runHook preConfigure
+
+          mkdir build
+          export buildRoot="$(pwd)/build"
+
+          echo "manual-config configurePhase buildRoot=$buildRoot pwd=$PWD"
+
+          if [ -f "$buildRoot/.config" ]; then
+            echo "Could not link $buildRoot/.config : file exists"
+            exit 1
+          fi
+          ln -sv ${configfile} $buildRoot/.config
+
+          # reads the existing .config file and prompts the user for options in
+          # the current kernel source that are not found in the file.
+          make $makeFlags "''${makeFlagsArray[@]}" oldconfig
+          runHook postConfigure
+
+          make $makeFlags "''${makeFlagsArray[@]}" prepare
+          actualModDirVersion="$(cat $buildRoot/include/config/kernel.release)"
+          if [ "$actualModDirVersion" != "${modDirVersion}" ]; then
+            echo "Error: modDirVersion ${modDirVersion} specified in the Nix expression is wrong, it should be: $actualModDirVersion"
+            exit 1
+          fi
+
+          buildFlagsArray+=("KBUILD_BUILD_TIMESTAMP=$(date -u -d @$SOURCE_DATE_EPOCH)")
+
+          cd $buildRoot
+        '';
+
+        buildFlags =
+          [
+            "KBUILD_BUILD_VERSION=1-PatOS"
+            kernelConf.target
+            "vmlinux" # for "perf" and things like that
+          ]
+          ++ optional isModular "modules"
+          ++ optionals buildDTBs [
+            "dtbs"
+            "DTC_FLAGS=-@"
+          ]
+          ++ extraMakeFlags;
+
+        installFlags =
+          [
+            "INSTALL_PATH=$(out)"
+          ]
+          ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
+          ++ optionals buildDTBs [
+            "dtbs_install"
+            "INSTALL_DTBS_PATH=$(out)/dtbs"
+          ];
+
+        dontStrip = true;
+
+        preInstall =
+          let
+            # All we really need to do here is copy the final image and System.map to $out,
+            # and use the kernel's modules_install, firmware_install, dtbs_install, etc. targets
+            # for the rest. Easy, right?
+            #
+            # Unfortunately for us, the obvious way of getting the built image path,
+            # make -s image_name, does not work correctly, because some architectures
+            # (*cough* aarch64 *cough*) change KBUILD_IMAGE on the fly in their install targets,
+            # so we end up attempting to install the thing we didn't actually build.
+            #
+            # Thankfully, there's a way out that doesn't involve just hardcoding everything.
+            #
+            # The kernel has an install target, which runs a pretty simple shell script
+            # (located at scripts/install.sh or arch/$arch/boot/install.sh, depending on
+            # which kernel version you're looking at) that tries to do something sensible.
+            #
+            # (it would be great to hijack this script immediately, as it has all the
+            #   information we need passed to it and we don't need it to try and be smart,
+            #   but unfortunately, the exact location of the scripts differs between kernel
+            #   versions, and they're seemingly not considered to be public API at all)
+            #
+            # One of the ways it tries to discover what "something sensible" actually is
+            # is by delegating to what's supposed to be a user-provided install script
+            # located at ~/bin/installkernel.
+            #
+            # (the other options are:
+            #   - a distribution-specific script at /sbin/installkernel,
+            #        which we can't really create in the sandbox easily
+            #   - an architecture-specific script at arch/$arch/boot/install.sh,
+            #        which attempts to guess _something_ and usually guesses very wrong)
+            #
+            # More specifically, the install script exec's into ~/bin/installkernel, if one
+            # exists, with the following arguments:
+            #
+            # $1: $KERNELRELEASE - full kernel version string
+            # $2: $KBUILD_IMAGE - the final image path
+            # $3: System.map - path to System.map file, seemingly hardcoded everywhere
+            # $4: $INSTALL_PATH - path to the destination directory as specified in installFlags
+            #
+            # $2 is exactly what we want, so hijack the script and use the knowledge given to it
+            # by the makefile overlords for our own nefarious ends.
+            #
+            # Note that the makefiles specifically look in ~/bin/installkernel, and
+            # writeShellScriptBin writes the script to <store path>/bin/installkernel,
+            # so HOME needs to be set to just the store path.
+            #
+            # FIXME: figure out a less roundabout way of doing this.
+            installkernel = buildPackages.writeShellScriptBin "installkernel" ''
+              cp -av $2 $4
+              cp -av $3 $4
+            '';
+          in
+          ''
+            installFlagsArray+=("-j$NIX_BUILD_CORES")
+            export HOME=${installkernel}
+          '';
+
+        # Some image types need special install targets (e.g. uImage is installed with make uinstall on arm)
+        installTargets = [
+          (kernelConf.installTarget or (
+            if kernelConf.target == "uImage" && stdenv.hostPlatform.linuxArch == "arm" then
+              "uinstall"
+            else if
+              kernelConf.target == "zImage"
+              || kernelConf.target == "Image.gz"
+              || kernelConf.target == "vmlinuz.efi"
+            then
+              "zinstall"
+            else
+              "install"
+          )
+          )
+        ];
+
+        # We remove a bunch of stuff that is symlinked from other places to save space,
+        # which trips the broken symlink check. So, just skip it. We'll know if it explodes.
+        dontCheckForBrokenSymlinks = true;
+
+        postInstall = optionalString isModular ''
+          mkdir -p $dev
+          cp vmlinux $dev/
+          # if [ -z "''${dontStrip-}" ]; then
+          #   installFlagsArray+=("INSTALL_MOD_STRIP=1")
+          # fi
+          make modules_install $makeFlags "''${makeFlagsArray[@]}" \
+            $installFlags "''${installFlagsArray[@]}"
+          unlink $out/lib/modules/${modDirVersion}/build
+          rm -f $out/lib/modules/${modDirVersion}/source
+
+          mkdir -p $dev/lib/modules/${modDirVersion}/{build,source}
+
+          # To save space, exclude a bunch of unneeded stuff when copying.
+          (cd .. && rsync --archive --prune-empty-dirs \
+              --exclude='/build/' \
+              * $dev/lib/modules/${modDirVersion}/source/)
+
+          cd $dev/lib/modules/${modDirVersion}/source
+
+          cp $buildRoot/{.config,Module.symvers} $dev/lib/modules/${modDirVersion}/build
+          make modules_prepare $makeFlags "''${makeFlagsArray[@]}" O=$dev/lib/modules/${modDirVersion}/build
+
+          # For reproducibility, removes accidental leftovers from a `cc1` call
+          # from a `try-run` call from the Makefile
+          rm -f $dev/lib/modules/${modDirVersion}/build/.[0-9]*.d
+
+          # Keep some extra files on some arches (powerpc, aarch64)
+          for f in arch/powerpc/lib/crtsavres.o arch/arm64/kernel/ftrace-mod.o; do
+            if [ -f "$buildRoot/$f" ]; then
+              cp $buildRoot/$f $dev/lib/modules/${modDirVersion}/build/$f
+            fi
+          done
+
+          # !!! No documentation on how much of the source tree must be kept
+          # If/when kernel builds fail due to missing files, you can add
+          # them here. Note that we may see packages requiring headers
+          # from drivers/ in the future; it adds 50M to keep all of its
+          # headers on 3.10 though.
+
+          chmod u+w -R ..
+          arch=$(cd $dev/lib/modules/${modDirVersion}/build/arch; ls)
+
+          # Remove unused arches
+          for d in $(cd arch/; ls); do
+            if [ "$d" = "$arch" ]; then continue; fi
+            if [ "$arch" = arm64 ] && [ "$d" = arm ]; then continue; fi
+            rm -rf arch/$d
+          done
+
+          # Remove all driver-specific code (50M of which is headers)
+          rm -fR drivers
+
+          # Keep all headers
+          find .  -type f -name '*.h' -print0 | xargs -0 -r chmod u-w
+
+          # Keep linker scripts (they are required for out-of-tree modules on aarch64)
+          find .  -type f -name '*.lds' -print0 | xargs -0 -r chmod u-w
+
+          # Keep root and arch-specific Makefiles
+          chmod u-w Makefile arch/"$arch"/Makefile*
+
+          # Keep whole scripts dir
+          chmod u-w -R scripts
+
+          # Delete everything not kept
+          find . -type f -perm -u=w -print0 | xargs -0 -r rm
+
+          # Delete empty directories
+          find -empty -type d -delete
+        '';
+
+        requiredSystemFeatures = [ "big-parallel" ];
+
+        meta = {
+          # https://github.com/NixOS/nixpkgs/pull/345534#issuecomment-2391238381
+          broken = withRust && lib.versionOlder version "6.12";
+
+          description =
+            "The Linux kernel"
+            + (
+              if kernelPatches == [ ] then
+                ""
+              else
+                " (with patches: " + lib.concatStringsSep ", " (map (x: x.name) kernelPatches) + ")"
+            );
+          license = lib.licenses.gpl2Only;
+          homepage = "https://www.kernel.org/";
+          maintainers = lib.teams.linux-kernel.members ++ [
+            maintainers.thoughtpolice
+          ];
+          platforms = platforms.linux;
+          badPlatforms =
+            lib.optionals (lib.versionOlder version "4.15") [
+              "riscv32-linux"
+              "riscv64-linux"
+            ]
+            ++ lib.optional (lib.versionOlder version "5.19") "loongarch64-linux";
+          timeout = 14400; # 4 hours
+        } // extraMeta;
       };
 
-      inherit src;
-
-      depsBuildBuild = [ buildPackages.stdenv.cc ];
-      nativeBuildInputs = [
-        bison
-        flex
-        perl
-        bc
-        nettools
-        openssl
-        rsync
-        gmp
-        libmpc
-        mpfr
-        elfutils
-        zstd
-        python3Minimal
-        kmod
-        hexdump
-      ] ++ optional  needsUbootTools ubootTools
-        ++ optionals (lib.versionAtLeast version "5.2")  [ cpio pahole zlib ]
-        ++ optionals withRust [ rustc rust-bindgen ];
-
-      RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
-
-      # avoid leaking Rust source file names into the final binary, which adds
-      # a false dependency on rust-lib-src on targets with uncompressed kernels
-      KRUSTFLAGS = lib.optionalString withRust "--remap-path-prefix ${rustPlatform.rustLibSrc}=/";
-
-      # patches =
-      #   map (p: p.patch) kernelPatches
-      #   # Required for deterministic builds along with some postPatch magic.
-      #   ++ optional (lib.versionOlder version "5.19") ./randstruct-provide-seed.patch
-      #   ++ optional (lib.versionAtLeast version "5.19") ./randstruct-provide-seed-5.19.patch
-      #   # Linux 5.12 marked certain PowerPC-only symbols as GPL, which breaks
-      #   # OpenZFS; this was fixed in Linux 5.19 so we backport the fix
-      #   # https://github.com/openzfs/zfs/pull/13367
-      #   ++ optional (lib.versionAtLeast version "5.12" &&
-      #                lib.versionOlder version "5.19" &&
-      #                stdenv.hostPlatform.isPower)
-      #     (fetchpatch {
-      #       url = "https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/patch/?id=d9e5c3e9e75162f845880535957b7fd0b4637d23";
-      #       hash = "sha256-bBOyJcP6jUvozFJU0SPTOf3cmnTQ6ZZ4PlHjiniHXLU=";
-      #     });
-
-      postPatch = ''
-        # Ensure that depmod gets resolved through PATH
-        sed -i Makefile -e 's|= /sbin/depmod|= depmod|'
-
-        # Some linux-hardened patches now remove certain files in the scripts directory, so the file may not exist.
-        [[ -f scripts/ld-version.sh ]] && patchShebangs scripts/ld-version.sh
-
-        # Set randstruct seed to a deterministic but diversified value. Note:
-        # we could have instead patched gen-random-seed.sh to take input from
-        # the buildFlags, but that would require also patching the kernel's
-        # toplevel Makefile to add a variable export. This would be likely to
-        # cause future patch conflicts.
-        for file in scripts/gen-randstruct-seed.sh scripts/gcc-plugins/gen-random-seed.sh; do
-          if [ -f "$file" ]; then
-            substituteInPlace "$file" \
-              --replace NIXOS_RANDSTRUCT_SEED \
-              $(echo ${randstructSeed}${src} ${placeholder "configfile"} | sha256sum | cut -d ' ' -f 1 | tr -d '\n')
-            break
-          fi
-        done
-
-        patchShebangs scripts
-
-        # also patch arch-specific install scripts
-        for i in $(find arch -name install.sh); do
-            patchShebangs "$i"
-        done
-
-        # unset $src because the build system tries to use it and spams a bunch of warnings
-        # see: https://github.com/torvalds/linux/commit/b1992c3772e69a6fd0e3fc81cd4d2820c8b6eca0
-        unset src
-      '';
-
-      configurePhase = ''
-        runHook preConfigure
-
-        mkdir build
-        export buildRoot="$(pwd)/build"
-
-        echo "manual-config configurePhase buildRoot=$buildRoot pwd=$PWD"
-
-        if [ -f "$buildRoot/.config" ]; then
-          echo "Could not link $buildRoot/.config : file exists"
-          exit 1
-        fi
-        ln -sv ${configfile} $buildRoot/.config
-
-        # reads the existing .config file and prompts the user for options in
-        # the current kernel source that are not found in the file.
-        make $makeFlags "''${makeFlagsArray[@]}" oldconfig
-        runHook postConfigure
-
-        make $makeFlags "''${makeFlagsArray[@]}" prepare
-        actualModDirVersion="$(cat $buildRoot/include/config/kernel.release)"
-        if [ "$actualModDirVersion" != "${modDirVersion}" ]; then
-          echo "Error: modDirVersion ${modDirVersion} specified in the Nix expression is wrong, it should be: $actualModDirVersion"
-          exit 1
-        fi
-
-        buildFlagsArray+=("KBUILD_BUILD_TIMESTAMP=$(date -u -d @$SOURCE_DATE_EPOCH)")
-
-        cd $buildRoot
-      '';
-
-      buildFlags = [
-        "KBUILD_BUILD_VERSION=1-PatOS"
-        kernelConf.target
-        "vmlinux"  # for "perf" and things like that
-      ] ++ optional isModular "modules"
-        ++ optionals buildDTBs ["dtbs" "DTC_FLAGS=-@"]
+    # Absolute paths for compilers avoid any PATH-clobbering issues.
+    commonMakeFlags =
+      [
+        "ARCH=${stdenv.hostPlatform.linuxArch}"
+        "CROSS_COMPILE=${stdenv.cc.targetPrefix}"
+      ]
+      ++ lib.optionals (stdenv.isx86_64 && stdenv.cc.bintools.isLLVM) [
+        # The wrapper for ld.lld breaks linking the kernel. We use the
+        # unwrapped linker as workaround. See:
+        #
+        # https://github.com/NixOS/nixpkgs/issues/321667
+        "LD=${stdenv.cc.bintools.bintools}/bin/${stdenv.cc.targetPrefix}ld"
+      ]
+      ++ (stdenv.hostPlatform.linux-kernel.makeFlags or [ ])
       ++ extraMakeFlags;
+  in
 
-      installFlags = [
-        "INSTALL_PATH=$(out)"
-      ] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
-      ++ optionals buildDTBs ["dtbs_install" "INSTALL_DTBS_PATH=$(out)/dtbs"];
+  stdenv.mkDerivation (
+    builtins.foldl' lib.recursiveUpdate { } [
+      (drvAttrs config stdenv.hostPlatform.linux-kernel kernelPatches configfile)
+      {
+        inherit pname version;
 
-      dontStrip = true;
+        enableParallelBuilding = true;
 
-      preInstall = let
-        # All we really need to do here is copy the final image and System.map to $out,
-        # and use the kernel's modules_install, firmware_install, dtbs_install, etc. targets
-        # for the rest. Easy, right?
-        #
-        # Unfortunately for us, the obvious way of getting the built image path,
-        # make -s image_name, does not work correctly, because some architectures
-        # (*cough* aarch64 *cough*) change KBUILD_IMAGE on the fly in their install targets,
-        # so we end up attempting to install the thing we didn't actually build.
-        #
-        # Thankfully, there's a way out that doesn't involve just hardcoding everything.
-        #
-        # The kernel has an install target, which runs a pretty simple shell script
-        # (located at scripts/install.sh or arch/$arch/boot/install.sh, depending on
-        # which kernel version you're looking at) that tries to do something sensible.
-        #
-        # (it would be great to hijack this script immediately, as it has all the
-        #   information we need passed to it and we don't need it to try and be smart,
-        #   but unfortunately, the exact location of the scripts differs between kernel
-        #   versions, and they're seemingly not considered to be public API at all)
-        #
-        # One of the ways it tries to discover what "something sensible" actually is
-        # is by delegating to what's supposed to be a user-provided install script
-        # located at ~/bin/installkernel.
-        #
-        # (the other options are:
-        #   - a distribution-specific script at /sbin/installkernel,
-        #        which we can't really create in the sandbox easily
-        #   - an architecture-specific script at arch/$arch/boot/install.sh,
-        #        which attempts to guess _something_ and usually guesses very wrong)
-        #
-        # More specifically, the install script exec's into ~/bin/installkernel, if one
-        # exists, with the following arguments:
-        #
-        # $1: $KERNELRELEASE - full kernel version string
-        # $2: $KBUILD_IMAGE - the final image path
-        # $3: System.map - path to System.map file, seemingly hardcoded everywhere
-        # $4: $INSTALL_PATH - path to the destination directory as specified in installFlags
-        #
-        # $2 is exactly what we want, so hijack the script and use the knowledge given to it
-        # by the makefile overlords for our own nefarious ends.
-        #
-        # Note that the makefiles specifically look in ~/bin/installkernel, and
-        # writeShellScriptBin writes the script to <store path>/bin/installkernel,
-        # so HOME needs to be set to just the store path.
-        #
-        # FIXME: figure out a less roundabout way of doing this.
-        installkernel = buildPackages.writeShellScriptBin "installkernel" ''
-          cp -av $2 $4
-          cp -av $3 $4
-        '';
-      in ''
-        installFlagsArray+=("-j$NIX_BUILD_CORES")
-        export HOME=${installkernel}
-      '';
-
-      # Some image types need special install targets (e.g. uImage is installed with make uinstall on arm)
-      installTargets = [
-        (kernelConf.installTarget or (
-          /**/ if kernelConf.target == "uImage" && stdenv.hostPlatform.linuxArch == "arm" then "uinstall"
-          else if kernelConf.target == "zImage" || kernelConf.target == "Image.gz" || kernelConf.target == "vmlinuz.efi" then "zinstall"
-          else "install"))
-      ];
-
-      # We remove a bunch of stuff that is symlinked from other places to save space,
-      # which trips the broken symlink check. So, just skip it. We'll know if it explodes.
-      dontCheckForBrokenSymlinks = true;
-
-      postInstall = optionalString isModular ''
-        mkdir -p $dev
-        cp vmlinux $dev/
-        if [ -z "''${dontStrip-}" ]; then
-          installFlagsArray+=("INSTALL_MOD_STRIP=1")
-        fi
-        make modules_install $makeFlags "''${makeFlagsArray[@]}" \
-          $installFlags "''${installFlagsArray[@]}"
-        unlink $out/lib/modules/${modDirVersion}/build
-        rm -f $out/lib/modules/${modDirVersion}/source
-
-        mkdir -p $dev/lib/modules/${modDirVersion}/{build,source}
-
-        # To save space, exclude a bunch of unneeded stuff when copying.
-        (cd .. && rsync --archive --prune-empty-dirs \
-            --exclude='/build/' \
-            * $dev/lib/modules/${modDirVersion}/source/)
-
-        cd $dev/lib/modules/${modDirVersion}/source
-
-        cp $buildRoot/{.config,Module.symvers} $dev/lib/modules/${modDirVersion}/build
-        make modules_prepare $makeFlags "''${makeFlagsArray[@]}" O=$dev/lib/modules/${modDirVersion}/build
-
-        # For reproducibility, removes accidental leftovers from a `cc1` call
-        # from a `try-run` call from the Makefile
-        rm -f $dev/lib/modules/${modDirVersion}/build/.[0-9]*.d
-
-        # Keep some extra files on some arches (powerpc, aarch64)
-        for f in arch/powerpc/lib/crtsavres.o arch/arm64/kernel/ftrace-mod.o; do
-          if [ -f "$buildRoot/$f" ]; then
-            cp $buildRoot/$f $dev/lib/modules/${modDirVersion}/build/$f
-          fi
-        done
-
-        # !!! No documentation on how much of the source tree must be kept
-        # If/when kernel builds fail due to missing files, you can add
-        # them here. Note that we may see packages requiring headers
-        # from drivers/ in the future; it adds 50M to keep all of its
-        # headers on 3.10 though.
-
-        chmod u+w -R ..
-        arch=$(cd $dev/lib/modules/${modDirVersion}/build/arch; ls)
-
-        # Remove unused arches
-        for d in $(cd arch/; ls); do
-          if [ "$d" = "$arch" ]; then continue; fi
-          if [ "$arch" = arm64 ] && [ "$d" = arm ]; then continue; fi
-          rm -rf arch/$d
-        done
-
-        # Remove all driver-specific code (50M of which is headers)
-        rm -fR drivers
-
-        # Keep all headers
-        find .  -type f -name '*.h' -print0 | xargs -0 -r chmod u-w
-
-        # Keep linker scripts (they are required for out-of-tree modules on aarch64)
-        find .  -type f -name '*.lds' -print0 | xargs -0 -r chmod u-w
-
-        # Keep root and arch-specific Makefiles
-        chmod u-w Makefile arch/"$arch"/Makefile*
-
-        # Keep whole scripts dir
-        chmod u-w -R scripts
-
-        # Delete everything not kept
-        find . -type f -perm -u=w -print0 | xargs -0 -r rm
-
-        # Delete empty directories
-        find -empty -type d -delete
-      '';
-
-      requiredSystemFeatures = [ "big-parallel" ];
-
-      meta = {
-        # https://github.com/NixOS/nixpkgs/pull/345534#issuecomment-2391238381
-        broken = withRust && lib.versionOlder version "6.12";
-
-        description =
-          "The Linux kernel" +
-          (if kernelPatches == [] then "" else
-            " (with patches: "
-            + lib.concatStringsSep ", " (map (x: x.name) kernelPatches)
-            + ")");
-        license = lib.licenses.gpl2Only;
-        homepage = "https://www.kernel.org/";
-        maintainers = lib.teams.linux-kernel.members ++ [
-          maintainers.thoughtpolice
+        hardeningDisable = [
+          "bindnow"
+          "format"
+          "fortify"
+          "stackprotector"
+          "pic"
+          "pie"
         ];
-        platforms = platforms.linux;
-        badPlatforms =
-          lib.optionals (lib.versionOlder version "4.15") [ "riscv32-linux" "riscv64-linux" ] ++
-          lib.optional (lib.versionOlder version "5.19") "loongarch64-linux";
-        timeout = 14400; # 4 hours
-      } // extraMeta;
-    };
 
-  # Absolute paths for compilers avoid any PATH-clobbering issues.
-  commonMakeFlags = [
-    "ARCH=${stdenv.hostPlatform.linuxArch}"
-    "CROSS_COMPILE=${stdenv.cc.targetPrefix}"
-  ] ++ lib.optionals (stdenv.isx86_64 && stdenv.cc.bintools.isLLVM) [
-    # The wrapper for ld.lld breaks linking the kernel. We use the
-    # unwrapped linker as workaround. See:
-    #
-    # https://github.com/NixOS/nixpkgs/issues/321667
-    "LD=${stdenv.cc.bintools.bintools}/bin/${stdenv.cc.targetPrefix}ld"
-  ] ++ (stdenv.hostPlatform.linux-kernel.makeFlags or [])
-    ++ extraMakeFlags;
-in
+        makeFlags = [
+          "O=$(buildRoot)"
+        ] ++ commonMakeFlags;
 
-stdenv.mkDerivation (
-  builtins.foldl' lib.recursiveUpdate {} [
-    (drvAttrs config stdenv.hostPlatform.linux-kernel kernelPatches configfile)
-    {
-      inherit pname version;
+        passthru = { inherit commonMakeFlags; };
 
-      enableParallelBuilding = true;
-
-      hardeningDisable = [ "bindnow" "format" "fortify" "stackprotector" "pic" "pie" ];
-
-      makeFlags = [
-        "O=$(buildRoot)"
-      ] ++ commonMakeFlags;
-
-      passthru = { inherit commonMakeFlags; };
-
-      karch = stdenv.hostPlatform.linuxArch;
-    }
-    (optionalAttrs (pos != null) { inherit pos; })
-  ]
-))
+        karch = stdenv.hostPlatform.linuxArch;
+      }
+      (optionalAttrs (pos != null) { inherit pos; })
+    ]
+  )
+)
diff --git a/pkgs/rootfs/default.nix b/pkgs/rootfs/default.nix
deleted file mode 100644
index d3c39c3..0000000
--- a/pkgs/rootfs/default.nix
+++ /dev/null
@@ -1,38 +0,0 @@
-{
-  pkgs,
-  stdenvNoCC,
-  patosPkgs,
-  version,
-  ...
-}:
-let
-  pname = "patos-rootfs";
-  defaultPassword = "patos";
-in
-stdenvNoCC.mkDerivation (finalAttrs: {
-  inherit version;
-  inherit pname;
-  inherit defaultPassword;
-
-  buildInputs = with pkgs; [
-    glibc
-    binutils
-  ];
-
-  glibcPatos = patosPkgs.glibc.out;
-  systemd = patosPkgs.systemd.out;
-  dbusBroker = patosPkgs.dbus-broker.out;
-  kernel = patosPkgs.kernel;
-  busybox = patosPkgs.busybox.out;
-  kmodLibs = pkgs.kmod.lib;
-  kmodBin = pkgs.kmod.out;
-  cacert = pkgs.cacert.out;
-  libbpf = pkgs.libbpf.out;
-  btrfs = pkgs.btrfs-progs.out;
-  tpm2Libs = patosPkgs.tpm2-tss.out;
-  kexec = patosPkgs.kexec.out;
-  lvm2 = patosPkgs.lvm2.out;
-  openssl = patosPkgs.openssl.out;
-
-  builder = ./mkrootfs.sh;
-})
diff --git a/pkgs/rootfs/mkinitrd.nix b/pkgs/rootfs/mkinitrd.nix
index 3708483..8eb721e 100644
--- a/pkgs/rootfs/mkinitrd.nix
+++ b/pkgs/rootfs/mkinitrd.nix
@@ -1,23 +1,66 @@
 {
   pkgs,
-  stdenvNoCC,
   patosPkgs,
-  version,
+  runCommand,
   ...
 }:
-let
-  pname = "patos-ramdisk";
-in
-stdenvNoCC.mkDerivation (finalAttrs: {
-  inherit version;
-  inherit pname;
-
+runCommand "patos-initrd" {
   buildInputs = with pkgs; [
     cpio
     xz
   ];
+}
+''
+echo "Building initram disk"
+mkdir -p $out/root
+pushd $out/root
 
-  rootfs = patosPkgs.rootfs.out;
+### copy rootfs
+cp -prP ${patosPkgs.rootfs}/* .
+find . -type d -exec chmod 755 {} \;
+mkdir sysroot
 
-  builder = ./mkinitrd.sh;
-})
+### create directories
+ln -sf ../usr/lib/systemd/systemd init
+
+### Create needed files
+echo patos > ./etc/hostname
+
+ln -sf /etc/os-release ./etc/initrd-release
+
+# set default target to initrd inside initrd
+ln -sf initrd.target ./usr/lib/systemd/system/default.target
+
+# bind mount /run to /sysroot/run
+cat <<EOF > ./usr/lib/systemd/system/sysroot-run.mount
+[Unit]
+Before=initrd-fs.target
+DefaultDependencies=false
+
+[Mount]
+Options=bind
+What=/run
+Where=/sysroot/run
+EOF
+mkdir ./usr/lib/systemd/system/initrd-fs.target.requires/
+ln -sf ../sysroot-run.mount ./usr/lib/systemd/system/initrd-fs.target.requires/sysroot-run.mount
+
+# repart: generate crypttab and fstab under /run
+mkdir ./usr/lib/systemd/system/systemd-repart.service.d
+cat <<EOF > ./usr/lib/systemd/system/systemd-repart.service.d/override.conf
+[Unit]
+After=sysroot-run.mount
+Requires=sysroot-run.mount
+
+[Service]
+Environment=SYSTEMD_REPART_MKFS_OPTIONS_BTRFS=--nodiscard
+ExecStart=
+ExecStart=systemd-repart --dry-run=no --generate-crypttab=/run/crypttab --generate-fstab=/run/fstab
+EOF
+
+# gen initrd
+find . -print0 | cpio --null --owner=root:root -o --format=newc | xz -9 --check=crc32 > ../initrd.xz
+
+popd
+rm -rf $out/root
+''
diff --git a/pkgs/rootfs/mkinitrd.sh b/pkgs/rootfs/mkinitrd.sh
deleted file mode 100644
index 43708d0..0000000
--- a/pkgs/rootfs/mkinitrd.sh
+++ /dev/null
@@ -1,53 +0,0 @@
-set -ex -p pipefail
-echo "Building initram disk"
-mkdir -p $out/root
-pushd $out/root
-
-### copy rootfs
-cp -prP $rootfs/* .
-find . -type d -exec chmod 755 {} \;
-mkdir sysroot
-
-### create directories
-ln -sf ../usr/lib/systemd/systemd init
-
-### Create needed files
-echo patos > ./etc/hostname
-
-ln -sf /etc/os-release ./etc/initrd-release
-
-# set default target to initrd inside initrd
-ln -sf initrd.target ./usr/lib/systemd/system/default.target
-
-# bind mount /run to /sysroot/run
-cat <<EOF > ./usr/lib/systemd/system/sysroot-run.mount
-[Unit]
-Before=initrd-fs.target
-DefaultDependencies=false
-
-[Mount]
-Options=bind
-What=/run
-Where=/sysroot/run
-EOF
-mkdir ./usr/lib/systemd/system/initrd-fs.target.requires/
-ln -sf ../sysroot-run.mount ./usr/lib/systemd/system/initrd-fs.target.requires/sysroot-run.mount
-
-# repart: generate crypttab and fstab under /run
-mkdir ./usr/lib/systemd/system/systemd-repart.service.d
-cat <<EOF > ./usr/lib/systemd/system/systemd-repart.service.d/override.conf
-[Unit]
-After=sysroot-run.mount
-Requires=sysroot-run.mount
-
-[Service]
-Environment=SYSTEMD_REPART_MKFS_OPTIONS_BTRFS=--nodiscard
-ExecStart=
-ExecStart=systemd-repart --dry-run=no --generate-crypttab=/run/crypttab --generate-fstab=/run/fstab
-EOF
-
-# gen initrd
-find . -print0 | cpio --null --owner=root:root -o --format=newc | xz -9 --check=crc32 > ../initrd.xz
-
-popd
-rm -rf $out/root
diff --git a/pkgs/rootfs/mkrootfs.sh b/pkgs/rootfs/mkrootfs.nix
similarity index 75%
rename from pkgs/rootfs/mkrootfs.sh
rename to pkgs/rootfs/mkrootfs.nix
index 3ccc93c..fb25c4d 100644
--- a/pkgs/rootfs/mkrootfs.sh
+++ b/pkgs/rootfs/mkrootfs.nix
@@ -1,5 +1,22 @@
-set -ex -o pipefail
+{
+  pkgs,
+  patosPkgs,
+  version,
+  runCommand,
+  ...
+}:
+let
+  defaultPassword = "patos";
+in
 
+runCommand "patos-rootfs"
+{
+  buildInputs = [
+    pkgs.glibc
+    pkgs.binutils
+  ];
+}
+''
 ### create directory structure
 mkdir -p $out/etc/repart.d $out/dev $out/proc $out/sys \
   $out/tmp $out/root $out/run $out/boot $out/mnt $out/home $out/srv $out/var/tmp
@@ -11,7 +28,7 @@ ln -sf ../proc/self/mounts $out/etc/mtab
 
 ### install systemd
 echo "Installing systemd"
-cp -Pr $systemd/* $out/
+cp -Pr ${patosPkgs.systemd}/* $out/
 find $out -type d -exec chmod 755 {} \;
 rm -rf $out/usr/include
 rm -rf $out/usr/sbin
@@ -117,57 +134,57 @@ ManagerEnvironment=PATH=/bin:/sbin:/usr/bin SYSTEMD_CRYPTTAB=/run/crypttab SYSTE
 EOF
 
 ### install PatOS glibc
-cp -P $glibcPatos/lib/*.so* $out/usr/lib/
+cp -P ${patosPkgs.glibc}/lib/*.so* $out/usr/lib/
 
 ### install openssl
-cp -P $openssl/lib/*.so* $out/usr/lib/
-cp -Pr $openssl/etc/ssl $out/etc/
+cp -P ${patosPkgs.openssl}/lib/*.so* $out/usr/lib/
+cp -Pr ${patosPkgs.openssl}/etc/ssl $out/etc/
 
 ### install busybox
-cp $busybox/bin/busybox $out/usr/bin/
+cp ${patosPkgs.busybox}/bin/busybox $out/usr/bin/
 $out/usr/bin/busybox --list | xargs -I {} ln -sf busybox $out/usr/bin/{}
 
 ### install dbus broker
-cp -r $dbusBroker/* $out/
+cp -r ${patosPkgs.dbus-broker}/* $out/
 
 ### install kexec
-cp -Pr ${kexec}/sbin/kexec $out/usr/bin/
+cp -Pr ${patosPkgs.kexec}/sbin/kexec $out/usr/bin/
 
 ### install dmsetup udev rules
-cp -P ${lvm2}/usr/bin/dmsetup $out/usr/bin/
-cp -P ${lvm2}/lib/libdevmapper.so* $out/usr/lib/
-cp -P ${lvm2}/lib/udev/rules.d/* $out/usr/lib/udev/rules.d/
+cp -P ${patosPkgs.lvm2}/usr/bin/dmsetup $out/usr/bin/
+cp -P ${patosPkgs.lvm2}/lib/libdevmapper.so* $out/usr/lib/
+cp -P ${patosPkgs.lvm2}/lib/udev/rules.d/* $out/usr/lib/udev/rules.d/
 
 ### install btrfs progs
-cp -Pr ${btrfs}/bin/* $out/usr/bin/
-cp -Pr ${btrfs}/lib/* $out/usr/lib/
+cp -Pr ${pkgs.btrfs-progs}/bin/* $out/usr/bin/
+cp -Pr ${pkgs.btrfs-progs}/lib/* $out/usr/lib/
 
 ### install tpm2 libs
-cp -P ${tpm2Libs}/lib/*.so* $out/usr/lib/
+cp -P ${patosPkgs.tpm2-tss}/lib/*.so* $out/usr/lib/
 
 ### install lib kmod
-cp -P $kmodLibs/lib/*.so* $out/usr/lib/
-cp -P $kmodBin/bin/* $out/usr/bin
+cp -P ${pkgs.kmod.lib}/lib/*.so* $out/usr/lib/
+cp -P ${pkgs.kmod}/bin/* $out/usr/bin
 
 ### install libbpf
-cp -P $libbpf/lib/libbpf*.so* $out/usr/lib
+cp -P ${pkgs.libbpf}/lib/libbpf*.so* $out/usr/lib
 
 ### install ca cert bundle
 chmod 755 $out/etc/ssl $out/etc/ssl/certs
-cp -P $cacert/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/cert.pem
+cp -P ${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt $out/etc/ssl/cert.pem
 ln -sf ../cert.pem $out/etc/ssl/certs/ca-certificates.crt
 ln -sf ../cert.pem $out/etc/ssl/certs/ca-bundle.crt
 
 # setup default files
-$systemd/usr/bin/systemd-hwdb --root=$out --usr update
-$systemd/usr/bin/systemd-tmpfiles --root=$out $out/usr/lib/tmpfiles.d/etc.conf --create
+${patosPkgs.systemd}/usr/bin/systemd-hwdb --root=$out --usr update
+${patosPkgs.systemd}/usr/bin/systemd-tmpfiles --root=$out $out/usr/lib/tmpfiles.d/etc.conf --create
 cp $out/usr/share/factory/etc/nsswitch.conf $out/etc/
 cp $out/usr/share/factory/etc/locale.conf $out/etc/
 cp $out/usr/share/factory/etc/vconsole.conf $out/etc/
 # install sys users
 mkdir creds
-echo -n $defaultPassword > creds/passwd.plaintext-password.root
-CREDENTIALS_DIRECTORY=$PWD/creds SYSTEMD_CRYPT_PREFIX='$6$' $systemd/usr/bin/systemd-sysusers --root=$out rootfs/usr/lib/sysusers.d/*.conf
+echo -n ${defaultPassword} > creds/passwd.plaintext-password.root
+CREDENTIALS_DIRECTORY=$PWD/creds SYSTEMD_CRYPT_PREFIX='$6$' ${patosPkgs.systemd}/usr/bin/systemd-sysusers --root=$out rootfs/usr/lib/sysusers.d/*.conf
 chmod 600 $out/etc/shadow
 rm -rf creds
 
@@ -195,6 +212,6 @@ find $out -type f -executable -exec strip {} \;
 find $out -type d -exec chmod 755 {} \;
 
 ### install kernel modules
-cp -r $kernel/lib/modules $out/usr/lib/
+cp -r ${patosPkgs.kernel}/lib/modules $out/usr/lib/
 find $out/usr/lib/modules -type d -exec chmod 755 {} \;
-
+''