diff --git a/flake.nix b/flake.nix
index 221d203..90fe634 100644
--- a/flake.nix
+++ b/flake.nix
@@ -37,6 +37,7 @@
           glibc = pkgs.callPackage ./glibc { };
           systemd = pkgs.callPackage ./systemd { };
           dbus-broker = pkgs.callPackage ./dbus-broker { };
+          rootfs = pkgs.callPackage ./rootfs { inherit patosPkgs; };
 
           mkinitrd = pkgs.callPackage ./utils/mkinitrd.nix { inherit patosPkgs; };
           qemu-uefi-tpm = pkgs.callPackage ./utils/qemu-uefi-tpm.nix { };
diff --git a/rootfs/default.nix b/rootfs/default.nix
new file mode 100644
index 0000000..5880254
--- /dev/null
+++ b/rootfs/default.nix
@@ -0,0 +1,30 @@
+{
+  pkgs,
+  stdenvNoCC,
+  patosPkgs,
+  ...
+}:
+let
+  version = "0.0.1";
+  pname = "patos-rootfs";
+in
+stdenvNoCC.mkDerivation (finalAttrs: {
+  inherit version;
+  inherit pname;
+
+  buildInputs = with pkgs; [
+    glibc
+    binutils
+  ];
+
+  glibcPatos = "${patosPkgs.glibc.out}";
+  systemd = "${patosPkgs.systemd.out}";
+  dbusBroker = "${patosPkgs.dbus-broker.out}";
+  kernel = "${patosPkgs.kernel.kernel}";
+  busybox = "${pkgs.busybox.out}";
+  kmodLibs = "${pkgs.kmod.lib}";
+  kmodBin = "${pkgs.kmod.out}";
+  libbpf = "${pkgs.libbpf.out}";
+
+  builder = ./install.sh;
+})
diff --git a/rootfs/install.sh b/rootfs/install.sh
new file mode 100644
index 0000000..b850129
--- /dev/null
+++ b/rootfs/install.sh
@@ -0,0 +1,54 @@
+set -ex -o pipefail
+
+mkdir -p $out
+mkdir -p $out/etc $out/dev $out/proc $out/sys $out/tmp $out/root
+ln -sf ../usr/bin $out/bin
+ln -sf ../usr/bin $out/sbin
+ln -sf ../usr/lib $out/lib
+ln -sf ../usr/lib $out/lib64
+ln -sf ../proc/self/mounts $out/etc/mtab
+
+### install systemd
+echo "Installing systemd"
+cp -Pr $systemd/* $out/
+find $out -type d -exec chmod 755 {} \;
+rm -rf $out/usr/include
+rm -rf $out/usr/sbin
+rm -f $out/usr/lib/systemd/system/sysinit.target.wants/systemd-firstboot.service
+# remove vconsole setup
+rm -f $out/usr/lib/udev/rules.d/90-vconsole.rules
+
+### install PatOS glibc
+cp -P $glibcPatos/lib/*.so* $out/usr/lib/
+
+### install kernel modules
+cp -r $kernel/lib/modules $out/usr/lib/
+find $out/usr/lib/modules -type d -exec chmod 755 {} \;
+
+### install busybox
+cp $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/
+
+### install lib kmod
+cp -P $kmodLibs/lib/* $out/usr/lib
+cp -P $kmodBin/bin/* $out/usr/bin
+
+### install libbpf
+cp -P $libbpf/lib/libbpf* $out/usr/lib
+
+### Find and install all shared libs
+find $out -type f -executable -exec ldd {} \; | awk '{print $3}' | grep -v systemd | grep -v glibc | sort -u | xargs cp -t $out/usr/lib
+find $out -type f -executable -exec chmod 755 {} \;
+
+# FIXME: ELF patching. Is there a better way?
+find $out -type f -executable -exec patchelf --set-rpath /lib:/usr/lib:/usr/lib/systemd {} \;
+find $out -type f -executable -exec patchelf --set-interpreter /lib/ld-linux-x86-64.so.2 {} \;
+patchelf --remove-rpath $out/usr/lib/ld-linux-x86-64.so.2
+
+# strip binaries
+find $out -type f -executable -exec strip {} \;
+find $out -type d -exec chmod 755 {} \;
+
diff --git a/utils/mkinitrd.nix b/utils/mkinitrd.nix
index 0bd234c..47f7f30 100644
--- a/utils/mkinitrd.nix
+++ b/utils/mkinitrd.nix
@@ -7,7 +7,6 @@ pkgs.writeShellApplication {
   name = "mkinitrd";
 
   runtimeInputs = with pkgs; [
-    patchelf
     cpio
     gzip
   ];
@@ -17,56 +16,21 @@ pkgs.writeShellApplication {
     mkdir -p root
     pushd root
 
+    ### copy rootfs
+    cp -prP ${patosPkgs.rootfs}/* .
+    find . -type d -exec chmod 755 {} \;
+
     ### create directories
-    mkdir -p etc dev proc sys tmp root
-    ln -sf usr/bin bin
-    ln -sf usr/bin sbin
-    ln -sf usr/lib lib
-    ln -sf usr/lib lib64
-    ln -sf ../proc/self/mounts etc/mtab
     ln -sf ../usr/lib/systemd/systemd init
 
-    ### install systemd
-    cp -Pr ${patosPkgs.systemd.out}/* ./
-    find . -type d -exec chmod 755 {} \;
-    rm -rf ./usr/include
-    rm -rf ./usr/sbin
     # set default target to basic
     mkdir usr/lib/systemd/system/basic.target.wants
     ln -sf basic.target usr/lib/systemd/system/default.target
-    # remove first boot
-    rm -f usr/lib/systemd/system/sysinit.target.wants/systemd-firstboot.service
-    # remove vconsole setup
-    rm -f usr/lib/udev/rules.d/90-vconsole.rules
 
-    ### install PatOS glibc
-    cp -Pr ${patosPkgs.glibc.out}/lib/*.so* ./usr/lib/
-
-    ### install kernel modules
-    cp -Pr ${patosPkgs.kernel.kernel}/lib/modules ./usr/lib/
-    find usr/lib/modules -type d -exec chmod 755 {} \;
-
-    ### install busybox
-    cp ${pkgs.busybox.out}/bin/busybox ./usr/bin/
-    usr/bin/busybox --list | xargs -I {} ln -sf busybox usr/bin/{}
-
-    ### install dbus broker
-    cp -r ${patosPkgs.dbus-broker.out}/* ./
+    # enable dbus broker
     ln -sf ../dbus-broker.service usr/lib/systemd/system/basic.target.wants/dbus.service
     ln -sf ../dbus.socket usr/lib/systemd/system/sockets.target.wants/dbus.socket
 
-    ### install lib kmod
-    cp -P ${pkgs.kmod.lib}/lib/* ./usr/lib
-    cp -P ${pkgs.kmod.out}/bin/* ./usr/bin
-
-    ### install libbpf
-    cp -P ${pkgs.libbpf.out}/lib/libbpf* ./usr/lib
-
-    ### Find and install all shared libs
-    find . -type f -executable -exec ldd {} \; 2> /dev/null | awk '{print $3}' | grep -v systemd | grep -v glibc | sort -u | xargs cp -t usr/lib
-    find . -type f -executable -exec chmod 755 {} \;
-
-
     ### Create needed files
     echo patos > ./etc/hostname
     cat <<EOF > ./etc/os-release
@@ -152,15 +116,6 @@ pkgs.writeShellApplication {
     EOF
     ln -sf ../demo.service usr/lib/systemd/system/basic.target.wants/demo.service
 
-    # FIXME: ELF patching. Is there a better way?
-    find . -type f -executable -exec patchelf --set-rpath /lib:/usr/lib:/usr/lib/systemd {} \; 2> /dev/null
-    find . -type f -executable -exec patchelf --set-interpreter /lib/ld-linux-x86-64.so.2 {} \; 2> /dev/null
-    patchelf --remove-rpath ./usr/lib/ld-linux-x86-64.so.2
-
-    # strip binaries
-    find . -type f -executable -exec strip {} \; 2> /dev/null
-    find . -type d -exec chmod 755 {} \;
-
     # gen initrd
     find . -print0 | cpio --null --owner=root:root -o --format=newc | gzip -9 > ../initrd.gz