diff options
-rw-r--r-- | configuration.nix | 28 | ||||
-rw-r--r-- | install.nix | 90 | ||||
-rw-r--r-- | kexec.nix | 72 | ||||
-rw-r--r-- | release.nix | 37 | ||||
-rw-r--r-- | target-config.nix | 26 |
5 files changed, 253 insertions, 0 deletions
diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..da4d3b1 --- /dev/null +++ b/configuration.nix @@ -0,0 +1,28 @@ +# new cmd: nix-build '<nixpkgs/nixos>' -A config.system.build.kexec_tarball -I nixos-config=./configuration.nix -Q -j 4 + +{ lib, pkgs, config, ... }: + +with lib; + +{ + imports = [ + <nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix> + ./kexec.nix + ./install.nix + ]; + + # nixos-install doesn't work with nixUnstable + nix.package = mkForce pkgs.nixStable; + + boot.loader.grub.enable = false; + boot.kernelParams = [ + "console=ttyS0,115200" # allows certain forms of remote access, if the hardware is setup right + "panic=30" "boot.panic_on_fail" # reboot the machine upon fatal boot issues + ]; + + networking.hostName = "kexec"; + hardware = { + enableRedistributableFirmware = mkForce false; + opengl.driSupport = mkForce false; + }; +} diff --git a/install.nix b/install.nix new file mode 100644 index 0000000..f4186c7 --- /dev/null +++ b/install.nix @@ -0,0 +1,90 @@ +{ config, pkgs, lib, ... }: + +with lib; +let + cfg = config.kexec.justdoit; +in { + options = { + kexec.justdoit = { + rootDevice = mkOption { + type = types.str; + default = "/dev/sda"; + description = "the root block device that justdoit will nuke from orbit and force nixos onto"; + }; + bootSize = mkOption { + type = types.int; + default = 256; + description = "size of /boot in mb"; + }; + swapSize = mkOption { + type = types.int; + default = 1024; + description = "size of swap in mb"; + }; + }; + }; + + config = lib.mkIf true { + system.build.justdoit = pkgs.writeScriptBin "justdoit" '' + #!${pkgs.stdenv.shell} + + set -e + + vgchange -a n + + dd if=/dev/zero of=${cfg.rootDevice} bs=512 count=10000 + + sfdisk ${cfg.rootDevice} <<EOF + label: dos + device: ${cfg.rootDevice} + unit: sectors + ${cfg.rootDevice}1 : size=${toString (2048 * cfg.bootSize)}, type=83 + ${cfg.rootDevice}2 : size=${toString (2048 * cfg.swapSize)}, type=82 + ${cfg.rootDevice}3 : type=83 + EOF + export ROOT_DEVICE=${cfg.rootDevice}3 + export SWAP_DEVICE=${cfg.rootDevice}2 + + mkdir -p /mnt + + mkfs.ext4 ${cfg.rootDevice}1 -L NIXOS_BOOT + mkswap $SWAP_DEVICE -L NIXOS_SWAP + mkfs.ext4 $ROOT_DEVICE -L NIXOS_ROOT + + swapon $SWAP_DEVICE + mount $ROOT_DEVICE /mnt/ + mkdir -p /mnt/boot/ + mount -t ext4 ${cfg.rootDevice}1 /mnt/boot/ + + nixos-generate-config --root /mnt/ + + hostId=$(echo $(head -c4 /dev/urandom | od -A none -t x4)) + cp ${./target-config.nix} /mnt/etc/nixos/configuration.nix + + cat > /mnt/etc/nixos/generated.nix <<EOF + { ... }: { + boot.loader.grub.device = "${cfg.rootDevice}"; + networking.hostId = "$hostId"; # required for zfs use + } + EOF + + nixos-install --no-root-passwd -j 4 + reboot + ''; + environment.systemPackages = [ config.system.build.justdoit ]; + + systemd.services.performInstall = { + requiredBy = [ "multi-user.target" ]; + + path = with pkgs; [ + nixStable lvm2 utillinux e2fsprogs + ] ++ (with config.system.build; [ + nixos-install nixos-generate-config + ]); + + environment.NIX_PATH = lib.concatStringsSep ":" config.nix.nixPath; + + script = "${config.system.build.justdoit}/bin/justdoit"; + }; + }; +} diff --git a/kexec.nix b/kexec.nix new file mode 100644 index 0000000..3556f28 --- /dev/null +++ b/kexec.nix @@ -0,0 +1,72 @@ +{ pkgs, config, ... }: + +{ + system.build = rec { + image = pkgs.runCommand "image" { buildInputs = [ pkgs.nukeReferences ]; } '' + mkdir $out + cp ${config.system.build.kernel}/bzImage $out/kernel + cp ${config.system.build.netbootRamdisk}/initrd $out/initrd + echo "init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" > $out/cmdline + nuke-refs $out/kernel + ''; + + kexec_script = pkgs.writeTextFile { + executable = true; + name = "kexec-nixos"; + text = '' + #!${pkgs.stdenv.shell} + export PATH=${pkgs.kexectools}/bin:${pkgs.cpio}/bin:$PATH + set -x + cd $(mktemp -d) + pwd + mkdir initrd + pushd initrd + cat /ssh_pubkey >> authorized_keys + find -type f | cpio -o -H newc | gzip -9 > ../extra.gz + popd + cat ${image}/initrd extra.gz > final.gz + + kexec -l ${image}/kernel --initrd=final.gz --append="init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" + sync + echo "executing kernel, filesystems will be improperly umounted" + kexec -e + ''; + }; + + kexec_tarball = pkgs.callPackage <nixpkgs/nixos/lib/make-system-tarball.nix> { + storeContents = [ + { object = config.system.build.kexec_script; symlink = "/kexec_nixos"; } + ]; + contents = []; + }; + + kexec_tarball_self_extract_script = pkgs.writeTextFile { + executable = true; + name = "kexec-nixos"; + text = '' + #!/bin/sh + ARCHIVE=`awk '/^__ARCHIVE_BELOW__/ { print NR + 1; exit 0; }' $0` + + tail -n+$ARCHIVE $0 | tar xJ -C / + /kexec_nixos + + exit 0 + + __ARCHIVE_BELOW__ + ''; + }; + + kexec_bundle = pkgs.runCommand "kexec_bundle" {} '' + cat \ + ${kexec_tarball_self_extract_script} \ + ${kexec_tarball}/tarball/nixos-system-${kexec_tarball.system}.tar.xz \ + > $out + chmod +x $out + ''; + }; + + boot.initrd.postMountCommands = '' + mkdir -p /mnt-root/root/.ssh/ + cp /authorized_keys /mnt-root/root/.ssh/ + ''; +} diff --git a/release.nix b/release.nix new file mode 100644 index 0000000..7dd11aa --- /dev/null +++ b/release.nix @@ -0,0 +1,37 @@ +let + pkgs = import <nixpkgs> { config = {}; }; + callPackage = pkgs.newScope self; + self = { + kexec_tarball = (import <nixpkgs/nixos> { + configuration = ./configuration.nix; + }).config.system.build.kexec_tarball; + + kexec_bundle = (import <nixpkgs/nixos> { + configuration = ./configuration.nix; + }).config.system.build.kexec_bundle; + + qemu_test1 = let + config = (import <nixpkgs/nixos> { configuration = ./configuration.nix; }).config; + image = config.system.build.image; + in pkgs.writeScriptBin "qemu_test1" '' + #!${pkgs.stdenv.shell} + export PATH=${pkgs.qemu_kvm}/bin/:$PATH + + if ! test -e dummy_root.qcow2; then + qemu-img create -f qcow2 dummy_root.qcow2 20G + fi + + qemu-kvm -kernel ${image}/kernel -initrd ${image}/initrd -m 2048 -append "init=${builtins.unsafeDiscardStringContext config.system.build.toplevel}/init ${toString config.boot.kernelParams}" -monitor stdio -drive index=0,id=drive1,file=dummy_root.qcow2,cache=writeback,werror=report,if=virtio + ''; + qemu_test2 = pkgs.writeScriptBin "qemu_test2" '' + #!${pkgs.stdenv.shell} + export PATH=${pkgs.qemu_kvm}/bin/:$PATH + + qemu-kvm -monitor stdio -drive index=0,id=drive1,file=dummy_root.qcow2,cache=writeback,werror=report,if=virtio + ''; + qemu_test = pkgs.buildEnv { + name = "qemu_test"; + paths = with self; [ qemu_test1 qemu_test2 ]; + }; + }; +in self diff --git a/target-config.nix b/target-config.nix new file mode 100644 index 0000000..8243786 --- /dev/null +++ b/target-config.nix @@ -0,0 +1,26 @@ +{ ... }: + +{ + imports = [ + ./hardware-configuration.nix + ./generated.nix + ]; + + boot.loader.grub = { + enable = true; + version = 2; + }; + + services.openssh = { + enable = true; + permitRootLogin = "yes"; + }; + + users.users.root.openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAQDuNResYJNUNlReRIxPMMnI3hAaW5dNs3E2qoeqHsU/nwnL+czVKOkHnG8gQaKSN7q0wVP3o3ozSsGHdYBJ0YrAYMccOPGkPJ6Aua/7LBkxTc1bVbGrPAEVDYfvNKTU0KjbOfUt6bAbtx1KzbzttBHRR14AxHSUH3ELja6a1foATQWyArLmykmo8aFp75n9+b8XVkmtVtSB0VFibMGwLekNgTD1zOZfzqjxD2EQop279Y8s9kfadpxznONLBNgNUZEzkk++MTh2a6OXW4WA2+dH8WaG2hwjghYbqSDlYe9yjyxhRS0ZtUuVlxlMlTsn0MIt/fYlYNSJts4I11ehBQFkzWUv/i/BgKFKX2M1A5fZTI9emlKJ/Iz3EyXNg1VNc/8iCVaWMpKUbT8Hao8qvwihoZegyVZRmCbUDyxVpjy2Qyl3/dl8mjsYbzYK6CyLo198rCeSrYlF7c81KikPmNuibzSL0UHvA94HK7hVWfu+iZKPZOYVdIle25+hZcL+s7GROy5iGWA9qwgaqXShbqhyyg/lXCY8MdyDBdomWrdk9SvQ0hbNLwSrNlcHAoO3H8/HRcoW4/faiFsm8SFF4RnsIYfVNKCUYlf4kspbHUxUWuEMtOxpo/uu3Zs7hI+TQL9FKwrLRgnu72sx0Y1o4PIGHUldSgzoYAxL+EaF3qgYhoOyiVFa5IRioaG9FRFJ1hboq+0XxQXYzJ8z9CrRa/Gxrp/Etqdevm8IjuOWelDAR4UPgeQsvjHvZVxLOGay8wBtA0/My9meouPDn7jzPjfFUcmdB99PM/PfrqJBC+WdldEfURrAeax6b2LidFl3bN4BLGwK0BlPybjgj7jm1THMnnM4F7BmhzA8MN1tmcEIiZSbW3lRjMxTikGkhvq1NbMp/k6ZmMkwJcwORSJRVdji3wYOuQxl2/u+Ey2NtBXyA5TomPvkWR/h9us+2/8WOxVlpjs6PtYEguehLbuqPWANM1FG9ngAMc1yGMp9YXPKQn+xVvOssOK6VoAu57q9zHJ5GQe8Pm6+2Qpq7hWRDkxIfnDGAeLDIlHa4JunX+okSCH14fx2PpwRfQ1UUhp5wnDtcAfkWGmq82HQknAigNWih5LqPthfjMuhUUcgYsciWYFKZbum4/yecfXUUx9SlcAwVrEZ+kwvNw1UsjrRtITsCBaBlSDpioyXYmJ6ldxUOKZiqAvAKeB0zRF3xpALWZuADh22BzWaNeLL8Gw5uR9TV7PGQ9wpd07SRsdabqLtYqg2P0/t+zPlKHNkL80vZjmuYJeHZ6Zmv3K4PsKEsHG3nXcA8PUI09IfvBbUnzlUb46V5K2O6E3iiSeQBRv7jWEkwGZy9/lBMUM7Qxw3a9Hv till@hoeppner.ws" + ]; + + boot.kernelParams = [ + "panic=30" "boot.panic_on_fail" # reboot the machine upon fatal boot issues + ]; +} |