{ config, pkgs, lib, ... }: let installer = pkgs.writeShellApplication { name = "cascade-installer"; runtimeInputs = with pkgs; [ btrfs-progs coreutils cryptsetup dig dosfstools e2fsprogs git lvm2 nix parted util-linux ]; text = let shq = lib.escapeShellArg; partedMin = cmd: '' parted -f -a minimal "$DEVICE" --script ${cmd} ''; partedOpt = cmd: '' parted -f -a optimal "$DEVICE" --script ${cmd} ''; in '' if [ "$#" -ne 2 ];then 1>&2 echo "usage: $0 hostname full-disk-device" exit 1 fi HOSTNAME="$1" DEVICE="$2" LABEL="$HOSTNAME"-luks0 LV="$HOSTNAME"-luks echo ABOUT TO DESTROY THIS MACHINE sleep 10 || exit 1 wipefs -a "$DEVICE" ${partedMin "mklabel gpt"} ${partedMin "mkpart ESP fat32 0% 1GB"} ${partedMin "set 1 esp on"} ${partedOpt "mkpart \"$HOSTNAME\"-luks0 ext4 1GB 100%"} sleep 1 cryptsetup -q luksFormat --type luks2 /dev/disk/by-partlabel/"$LABEL" -d /dev/zero -l 32 cryptsetup -q luksOpen /dev/disk/by-partlabel/"$LABEL" "$LABEL" -d /dev/zero -l 32 pvcreate /dev/mapper/"$LABEL" vgcreate "$LV" /dev/mapper/"$LABEL" lvcreate -L 20G -n "$HOSTNAME"-root "$LV" mkfs.fat -F 32 -n BOOT /dev/disk/by-partlabel/ESP mkfs.ext4 -L "$HOSTNAME"-root /dev/"$LV"/"$HOSTNAME"-root sleep 1 # note to future self who "fixes" this: # the -p is to prevent error if the path exists, not to create / which obviously exists. # this is a scenario that happens when rerunning these commands during debugging. just # leave the -p, future me. please just leave it. mkdir -p /mnt mount /dev/disk/by-label/"$HOSTNAME"-root /mnt mkdir -p /mnt/boot mount /dev/disk/by-label/BOOT /mnt/boot mkdir -p /mnt/root TOKEN="$(dig +short lan-git-token.cascade TXT | tr -d '"')" umask 0077 mkdir -p /root printf 'machine git.strudelline.net\nlogin james\npassword %s\n' "$TOKEN" > /root/.netrc printf 'machine git.strudelline.net\nlogin james\npassword %s\n' "$TOKEN" > /mnt/root/.netrc nixos-install --flake git+https://git.strudelline.net/cascade/nixos#"$HOSTNAME" --impure --no-root-password ''; }; in { environment.systemPackages = [ installer ]; }