diff --git a/base.nix b/base.nix
index 7eaee32..9aa338e 100644
--- a/base.nix
+++ b/base.nix
@@ -27,6 +27,11 @@ with lib;
       description = "enable rngd";
       default = false;
     };
+    not-os.sd = mkOption {
+      type = types.bool;
+      default = false;
+      description = "enable sd image support";
+    };
     not-os.simpleStaticIp = mkOption {
       type = types.bool;
       default = false;
@@ -84,17 +89,25 @@ with lib;
     };
     environment.etc = {
       "nix/nix.conf".source = pkgs.runCommand "nix.conf" {} ''
-        extraPaths=$(for i in $(cat ${pkgs.writeReferencesToFile pkgs.runtimeShell}); do if test -d $i; then echo $i; fi; done)
+        extraPaths=$(for i in $(cat ${pkgs.writeClosure [ pkgs.bash ]}); do if test -d $i; then echo $i; fi; done)
         cat > $out << EOF
-        build-use-sandbox = true
+        auto-optimise-store = true
         build-users-group = nixbld
-        build-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths)
-        build-max-jobs = 1
-        build-cores = 4
+        cores = 0
+        extra-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths)
+        max-jobs = auto
+        sandbox = true
+        trusted-users = root
         EOF
       '';
+      "ssl/certs/ca-certificates.crt".source = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
+      "ssl/certs/ca-bundle.crt".source = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
       bashrc.text = "export PATH=/run/current-system/sw/bin";
-      profile.text = "export PATH=/run/current-system/sw/bin";
+      profile.text = ''
+        export PATH=/run/current-system/sw/bin
+        export EDITOR=nano
+        export NIX_PATH="nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels"
+      '';
       "resolv.conf".text = "nameserver 10.0.2.3";
       passwd.text = ''
         root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash
diff --git a/runit.nix b/runit.nix
index d7b0bf3..70353a1 100644
--- a/runit.nix
+++ b/runit.nix
@@ -65,7 +65,6 @@ in
       '';
       "service/nix/run".source = pkgs.writeScript "nix" ''
         #!${pkgs.runtimeShell}
-        nix-store --load-db < /nix/store/nix-path-registration
         nix-daemon
       '';
     }
diff --git a/stage-1.nix b/stage-1.nix
index 331fecd..aa5148e 100644
--- a/stage-1.nix
+++ b/stage-1.nix
@@ -117,11 +117,6 @@ let
     plymouth --show-splash
     ''}
 
-
-    for x in ${lib.concatStringsSep " " config.boot.initrd.kernelModules}; do
-      modprobe $x
-    done
-
     root=/dev/vda
     realroot=tmpfs
     for o in $(cat /proc/cmdline); do
@@ -164,7 +159,9 @@ let
     mkdir -p /mnt/nix/store/
 
 
-    ${if config.not-os.nix then ''
+    ${if config.not-os.sd && config.not-os.nix then ''
+    mount $root /mnt
+    '' else if config.not-os.nix then ''
     # make the store writeable
     mkdir -p /mnt/nix/.ro-store /mnt/nix/.overlay-store /mnt/nix/store
     mount $root /mnt/nix/.ro-store -t squashfs
@@ -190,6 +187,11 @@ let
   initialRamdisk = pkgs.makeInitrd {
     contents = [ { object = bootStage1; symlink = "/init"; } ];
   };
+  # Use for zynq_image
+  uRamdisk =  pkgs.makeInitrd {
+    makeUInitrd = true;
+    contents = [ { object = bootStage1; symlink = "/init"; } ];
+  };
 in
 {
   options = {
@@ -205,6 +207,7 @@ in
   config = {
     system.build.bootStage1 = bootStage1;
     system.build.initialRamdisk = initialRamdisk;
+    system.build.uRamdisk = uRamdisk;
     system.build.extraUtils = extraUtils;
     boot.initrd.availableKernelModules = [ ];
     boot.initrd.kernelModules = [ "tun" "loop" "squashfs" ] ++ (lib.optional config.not-os.nix "overlay");
diff --git a/stage-2-init.sh b/stage-2-init.sh
index 6cc08e2..0c854c4 100644
--- a/stage-2-init.sh
+++ b/stage-2-init.sh
@@ -19,4 +19,7 @@ mount -t tmpfs tmpfs /dev/shm
 
 $systemConfig/activate
 
+# Run any user-specified commands.
+@runtimeShell@ @postBootCommands@
+
 exec runit
diff --git a/stage-2.nix b/stage-2.nix
index c61f9d6..fbdf0fd 100644
--- a/stage-2.nix
+++ b/stage-2.nix
@@ -20,6 +20,19 @@ with lib;
         example = "256m";
         type = types.str;
        };
+      postBootCommands = mkOption {
+        default = "";
+        example = "rm -f /var/log/messages";
+        type = types.lines;
+        description = lib.mdDoc ''
+          Shell commands to be executed just before runit is started.
+        '';
+      };
+    };
+    networking.hostName = mkOption {
+      default = "";
+      type = types.strMatching
+        "^$|^[[:alnum:]]([[:alnum:]_-]{0,61}[[:alnum:]])?$";
     };
   };
   config = {
@@ -28,6 +41,9 @@ with lib;
       isExecutable = true;
       path = config.system.path;
       inherit (pkgs) runtimeShell;
+      postBootCommands = pkgs.writeText "local-cmds" ''
+        ${config.boot.postBootCommands}
+      '';
     };
   };
 }
diff --git a/zynq_image.nix b/zynq_image.nix
index 3fa23ab..069fe89 100644
--- a/zynq_image.nix
+++ b/zynq_image.nix
@@ -1,66 +1,89 @@
-{ config, pkgs, ... }:
+{ lib, config, pkgs, ... }:
 
+with lib;
 let
-  # dont use overlays for the qemu, it causes a lot of wasted time on recompiles
-  x86pkgs = import pkgs.path { system = "x86_64-linux"; };
-  customKernel = pkgs.linux.override {
+  customKernel = (pkgs.linux_6_6.override {
     extraConfig = ''
       OVERLAY_FS y
+      MEDIA_SUPPORT n
+      FB n
+      DRM n
+      SOUND n
+      SQUASHFS n
+      BACKLIGHT_CLASS_DEVICE n
+      FPGA y
+      FPGA_BRIDGE y
+      FPGA_REGION y
+      OF_FPGA_REGION y
+      FPGA_MGR_ZYNQ_FPGA y
+      OF_OVERLAY y
     '';
-  };
+  }).overrideAttrs (oa: {
+    postInstall = ''
+      if [ -e arch/arm/boot/uImage ]; then
+        cp arch/arm/boot/uImage $out
+      fi
+      ${oa.postInstall}
+    '';
+  });
   customKernelPackages = pkgs.linuxPackagesFor customKernel;
 in {
   imports = [ ./arm32-cross-fixes.nix ];
   boot.kernelPackages = customKernelPackages;
   nixpkgs.system = "armv7l-linux";
-  system.build.zynq_image = let
-    cmdline = "root=/dev/mmcblk0 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext config.system.build.toplevel}";
-    qemuScript = ''
-      #!/bin/bash -v
-      export PATH=${x86pkgs.qemu}/bin:$PATH
-      set -x
-      base=$(dirname $0)
-
-      cp $base/root.squashfs /tmp/
-      chmod +w /tmp/root.squashfs
-      truncate -s 64m /tmp/root.squashfs
-
-      qemu-system-arm \
-        -M xilinx-zynq-a9 \
-        -serial /dev/null \
-        -serial stdio \
-        -display none \
-        -dtb $base/zynq-zc702.dtb \
-        -kernel $base/zImage \
-        -initrd $base/initrd \
-        -drive file=/tmp/root.squashfs,if=sd,format=raw \
-        -append "${cmdline}"
-    '';
-  in pkgs.runCommand "zynq_image" {
-    inherit qemuScript;
-    passAsFile = [ "qemuScript" ];
+  networking.hostName = "zynq";
+  not-os.sd = true;
+  not-os.simpleStaticIp = true;
+  system.build.zynq_image = pkgs.runCommand "zynq_image" {
     preferLocalBuild = true;
   } ''
     mkdir $out
     cd $out
-    cp -s ${config.system.build.squashfs} root.squashfs
-    cp -s ${config.system.build.kernel}/*zImage .
-    cp -s ${config.system.build.initialRamdisk}/initrd initrd
-    cp -s ${config.system.build.kernel}/dtbs/zynq-zc702.dtb .
+    cp -s ${config.system.build.kernel}/uImage .
+    cp -s ${config.system.build.uRamdisk}/initrd uRamdisk.image.gz
+    cp -s ${config.system.build.kernel}/dtbs/zynq-zc706.dtb devicetree.dtb
     ln -sv ${config.system.build.toplevel} toplevel
-    cp $qemuScriptPath qemu-script
-    chmod +x qemu-script
-    patchShebangs qemu-script
-    ls -ltrh
-  '';
-  system.build.rpi_image_tar = pkgs.runCommand "dist.tar" {} ''
-    mkdir -p $out/nix-support
-    tar -cvf $out/dist.tar ${config.system.build.rpi_image}
-    echo "file binary-dist $out/dist.tar" >> $out/nix-support/hydra-build-products
   '';
-  environment.systemPackages = [ pkgs.strace ];
-  environment.etc."service/getty/run".source = pkgs.writeShellScript "getty" ''
-    agetty ttyPS0 115200
+  environment = {
+    systemPackages = with pkgs; [ inetutils wget gnugrep nano vim ];
+    etc = {
+      "service/getty/run".source = pkgs.writeShellScript "getty" ''
+        hostname ${config.networking.hostName}
+        exec setsid agetty ttyPS0 115200
+      '';
+      "pam.d/other".text = ''
+        auth     sufficient pam_permit.so
+        account  required pam_permit.so
+        password required pam_permit.so
+        session  optional pam_env.so
+      '';
+      "security/pam_env.conf".text = "";
+    };
+  };
+  boot.postBootCommands = lib.mkIf config.not-os.sd ''
+    # On the first boot do some maintenance tasks
+    if [ -f /nix-path-registration ]; then
+      set -euo pipefail
+      set -x
+      # Figure out device names for the boot device and root filesystem.
+      rootPart=$(${pkgs.utillinux}/bin/findmnt -n -o SOURCE /)
+      bootDevice=$(lsblk -npo PKNAME $rootPart)
+      partNum=$(lsblk -npo MAJ:MIN $rootPart | ${pkgs.gawk}/bin/awk -F: '{print $2}')
+
+      # Resize the root partition and the filesystem to fit the disk
+      echo ",+," | sfdisk -N$partNum --no-reread $bootDevice
+      ${pkgs.parted}/bin/partprobe
+      ${pkgs.e2fsprogs}/bin/resize2fs $rootPart
+
+      # Register the contents of the initial Nix store
+      nix-store --load-db < /nix-path-registration
+
+      # nixos-rebuild also requires a "system" profile and an /etc/NIXOS tag.
+      touch /etc/NIXOS
+      nix-env -p /nix/var/nix/profiles/system --set /run/current-system
+
+      # Prevents this from running on later boots.
+      rm -f /nix-path-registration
+    fi
   '';
-  environment.etc."pam.d/other".text = "";
 }