Unify the scripts to format disks

This commit is contained in:
Andreas Zweili 2024-01-12 21:28:06 +01:00
parent 8cb97ad3fc
commit a1e4d0ae67
6 changed files with 172 additions and 161 deletions

View File

@ -4,24 +4,11 @@ This repository contains my configuration for my Nixos systems.
I don't provide any garantuees that it will work on other systems.
In addition some of the scripts required for installation will destroy your data when used.
## Preparation
On a PC you don't have to do anything special.
For a Raspberry Pi you need to prepare the SD card first with a UEFI partition. On a PC navigate into this project and run the following commands:
- `nix-shell`
- `sudo create-uefi-partition.sh`
This will format the SD card at `/dev/mmcblk0`, create a partition and download and copy all the required files for running UEFI on a Pi 4.
## Installation
1. Insert an USB stick with the latest NixOS ISO into your device.
1. `curl https://git.2li.ch/Nebucatnetzer/nixos/archive/master.tar.gz | tar xz`
1. `cd nixos && nix-shell setup-shell.nix`
1. For a normal PC run: `sudo ./scripts/format-disk.py` on a Raspberry Pi 4 run: `sudo ./scripts/format-sdcard.py`
1. `sudo nixos-install --no-root-passwd --root /mnt --impure --flake .#SYSTEMNAME`
1. For Raspis it's the easiest if you prepare the SD card/disk on another system. For a PC you can just boot the installation ISO directly.
1. For both devices you can format the disk/card with the following script `sudo ./scripts/format-disk.py`. It will walk you through the formatting process and for a Raspi4 it will prepare it for UEFI setup.
1. Next install the system with `sudo nixos-install --no-root-passwd --root /mnt/nixos --impure --flake .#SYSTEMNAME`
When everything is finished you can reboot the system and remove the USB stick. You have now a fully encrypted NixOS system.

View File

@ -65,7 +65,7 @@ in {
boot.kernelParams = [ "rootflags=atgc" "rw" ];
fileSystems."/" = {
device = "/dev/disk/by-label/NixosSd";
device = "/dev/disk/by-label/NIXOSSD";
fsType = "f2fs";
options = [
"atgc,gc_merge"
@ -77,7 +77,7 @@ in {
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/SdBoot";
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
};

View File

@ -1,19 +0,0 @@
#! /usr/bin/env nix-shell
#! nix-shell -i bash -p parted unzip curl
# Create the boot partition
parted --script /dev/mmcblk0 mklabel gpt
parted --script /dev/mmcblk0 mkpart ESP fat32 0% 1GiB
parted --script /dev/mmcblk0 set 1 esp on
mkfs.fat -F32 -n SdBoot /dev/mmcblk0p1
# Download and install the UEFI firmware
mkdir -p /tmp/sdcard/boot
mount /dev/mmcblk0p1 /tmp/sdcard/boot
curl -o /tmp/pi4-uefi.zip -L https://github.com/pftf/RPi4/releases/download/v1.35/RPi4_UEFI_Firmware_v1.35.zip
unzip /tmp/pi4-uefi.zip -d /tmp/sdcard/boot
sync
# Cleanup
umount /tmp/sdcard/boot
rm /tmp/pi4-uefi.zip

View File

@ -1,10 +1,15 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3
#! nix-shell -i python3 -p python3 parted
import getpass
import os
import subprocess
import sys
import subprocess
import zipfile
from time import sleep
from urllib.request import urlretrieve
def _run_command(command, user_input=""):
@ -56,91 +61,135 @@ def get_disk_to_format():
def create_partition_table(disk):
print("Create partition table.")
_run_command(["parted", "--script", disk, "mklabel", "gpt"])
sleep(5)
def _partition_suffix(disk):
if "nvmne" in disk:
prefixes = ["nvmne", "mmc"]
if any(prefix in disk for prefix in prefixes):
return "p"
return ""
def _get_uefi():
filename = "RPi4_UEFI_Firmware_v1.35.zip"
url = f"https://github.com/pftf/RPi4/releases/download/v1.35/{filename}"
retrieved_file, _ = urlretrieve(url, f"/tmp/{filename}")
return retrieved_file
def _extract_uefi(path_to_zip, partition):
with zipfile.ZipFile(path_to_zip, "r") as zip_ref:
zip_ref.extractall(partition)
def _create_uefi():
print("Create UEFI partition.")
filename = _get_uefi()
_extract_uefi(filename, "/mnt/nixos/boot")
def create_boot_partition(disk):
boot_partition = "{}{}1".format(disk, _partition_suffix(disk))
print("Create boot partition {}.".format(boot_partition))
_run_command(
["parted", "--script", disk, "mkpart", "ESP", "fat32", "1MiB", "512MiB"]
)
_run_command(["parted", "--script", disk, "mkpart", "ESP", "fat32", "0%", "1GiB"])
_run_command(["parted", "--script", disk, "set", "1", "esp", "on"])
_run_command(["mkfs.fat", "-F", "32", "-n", "BOOT", boot_partition])
_run_command(["mkfs.fat", "-F", "32", "-n", "BOOTTOFRMT", boot_partition])
sleep(5)
def create_main_partition(disk):
print("Create main partition.")
_run_command(["parted", "--script", disk, "mkpart", "primary", "512MiB", "100%"])
_run_command(["parted", "--script", disk, "mkpart", "primary", "1GiB", "100%"])
return "{}{}2".format(disk, _partition_suffix(disk))
def _create_main_filesystem():
_run_command(["lvcreate", "-l", "100%FREE", "MainGroup", "-n", "root"])
_run_command(["mkfs.ext4", "-L", "nixos", "/dev/MainGroup/root"])
def _create_ext4():
_run_command(["lvcreate", "-l", "100%FREE", "grouptoformat", "-n", "ROOTTOFRMT"])
_run_command(["mkfs.ext4", "-L", "ROOTTOFRMT", "/dev/grouptoformat/ROOTTOFRMT"])
def _create_f2fs():
_run_command(["mkfs.f2fs", "-l", "ROOTTOFRMT", "/dev/mapper/crypttoformat"])
def _create_swap():
memory = _get_system_memory()
print("Create swap partition of {} GiB in size".format(memory))
_run_command(["lvcreate", "-L", "{}G".format(memory), "MainGroup", "-n", "swap"])
_run_command(["mkswap", "-L", "swap", "/dev/MainGroup/swap"])
_run_command(
["lvcreate", "-L", "{}G".format(memory), "grouptoformat", "-n", "SWAPTOFRMT"]
)
_run_command(["mkswap", "-L", "SWAPTOFRMT", "/dev/grouptoformat/SWAPTOFRMT"])
def _encrypt_disk(partition_path):
password = getpass.getpass()
print("Encrypting disk.")
_run_command(
["cryptsetup", "luksFormat", "-q", "--type", "luks1", partition_path],
["cryptsetup", "luksFormat", "-q", partition_path],
user_input=password,
)
_run_command(
["cryptsetup", "open", partition_path, "cryptlvm"], user_input=password
["cryptsetup", "open", partition_path, "crypttoformat"], user_input=password
)
return "/dev/mapper/crypttoformat"
def _setup_lvm(lvm_target):
print("Set up LVM on {}.".format(lvm_target))
_run_command(["pvcreate", lvm_target])
_run_command(["vgcreate", "MainGroup", lvm_target])
_run_command(["vgcreate", "grouptoformat", lvm_target])
def mount_partitions():
def mount_partitions(
root_src="/dev/disk/by-label/ROOTTOFRMT",
boot_src="/dev/disk/by-label/BOOTTOFRMT",
root_target="/mnt/nixos",
boot_target="/mnt/nixos/boot",
):
print("Mounting partitions.")
_run_command(["mount", "/dev/MainGroup/root", "/mnt"])
os.mkdir("/mnt/boot")
_run_command(["mount", "/dev/disk/by-label/BOOT", "/mnt/boot"])
sleep(5)
os.makedirs(root_target, exist_ok=True)
_run_command(["mount", root_src, root_target])
os.makedirs(boot_target, exist_ok=True)
_run_command(["mount", boot_src, boot_target])
def create_file_systems(partition, swap, encryption):
def create_pc(partition, swap, encryption):
print("Creating filesystems.")
if encryption:
lvm_target = "/dev/mapper/cryptlvm"
lvm_target = "/dev/mapper/crypttoformat"
_encrypt_disk(partition)
else:
lvm_target = partition
_setup_lvm(lvm_target)
if swap:
_create_swap()
_create_main_filesystem()
_create_ext4()
def create_raspi(main_partition):
print("Create filesystems.")
_encrypt_disk(main_partition)
_create_f2fs()
mount_partitions()
_create_uefi()
def main():
disks = read_disks()
create_menu(disks)
disk_to_format = disks[get_disk_to_format()]
swap = _y_n("Do you need swap?")
encryption = _y_n("Do you want to encrypt your data?")
raspi = _y_n("Do you want to setup a Raspi?")
create_partition_table(disk_to_format)
create_boot_partition(disk_to_format)
main_partition = create_main_partition(disk_to_format)
create_file_systems(main_partition, swap, encryption)
mount_partitions()
if raspi:
create_raspi(main_partition)
else:
swap = _y_n("Do you need swap?")
encryption = _y_n("Do you need encryption?")
create_pc(main_partition, swap, encryption)
if __name__ == "__main__":

View File

@ -1,97 +0,0 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 parted
import getpass
import os
import subprocess
def _run_command(command, user_input=""):
if user_input:
result = subprocess.run(
command, capture_output=True, text=True, check=True, input=user_input
)
else:
result = subprocess.run(command, capture_output=True, text=True, check=True)
return result
def _partition_suffix(disk):
if ("nvmne" or "mmc") in disk:
return "p"
return ""
def read_disks():
output = _run_command(["lsblk", "-dpno", "name"])
disks = []
for disk in output.stdout.splitlines():
if "loop" in disk:
continue
disks.append(disk)
return disks
def create_menu(disks):
for position, disk in enumerate(disks):
print("{}: {}".format(position, disk))
def get_disk_to_format():
disk_to_format = input("Which disk dou you want to format?: ")
return int(disk_to_format)
def create_main_partition(disk):
print("Create main partition.")
_run_command(["parted", "--script", disk, "mkpart", "primary", "1GiB", "100%"])
return f"{disk}{_partition_suffix(disk)}2"
def _create_main_filesystem():
_run_command(
[
"mkfs.f2fs",
"-l",
"NixosSd",
"-O",
"extra_attr,inode_checksum,sb_checksum,compression",
"/dev/mapper/cryptsd",
]
)
def _encrypt_disk(partition_path):
password = getpass.getpass()
print("Encrypting disk.")
_run_command(
["cryptsetup", "luksFormat", "-q", partition_path],
user_input=password,
)
_run_command(["cryptsetup", "open", partition_path, "cryptsd"], user_input=password)
def create_file_systems(partition):
print("Creating filesystems.")
_encrypt_disk(partition)
_create_main_filesystem()
def mount_partitions():
print("Mounting partitions.")
_run_command(["mount", "/dev/disk/by-label/NixosSd", "/mnt"])
os.mkdir("/mnt/boot")
_run_command(["mount", "/dev/disk/by-label/SdBoot", "/mnt/boot"])
def main():
disks = read_disks()
create_menu(disks)
disk_to_format = disks[get_disk_to_format()]
main_partition = create_main_partition(disk_to_format)
create_file_systems(main_partition)
mount_partitions()
if __name__ == "__main__":
main()

91
scripts/rename-partitions.py Executable file
View File

@ -0,0 +1,91 @@
#! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 parted
import subprocess
import sys
from time import sleep
def _run_command(command, user_input=""):
if user_input:
result = subprocess.run(
command, capture_output=True, text=True, check=True, input=user_input
)
else:
result = subprocess.run(command, capture_output=True, text=True, check=True)
return result
def _y_n(question):
answer = input("{} (Y/N): ".format(question))
if answer.lower() == "y":
return True
if answer.lower() == "n":
return False
print("Please only answer with Y or N!")
sys.exit(1)
def rename_boot_partition():
print("Rename boot partition.")
_run_command(["fatlabel", "/dev/disk/by-label/BOOTTOFRMT", "BOOT"])
def _rename_ext4():
print("Rename ext4 partition.")
_run_command(["e2label", "/dev/MainGroup/roottoformat", "root"])
def _rename_f2fs():
print("Rename f2fs partition.")
_run_command(["f2fslabel", "/dev/disk/by-label/ROOTTOFRMT", "root"])
def _rename_swap():
print("Rename swap partition.")
_run_command(["swaplabel", "-L", "swap", "/dev/GroupToFormat/swaptoformat"])
def _rename_lvm():
print("Rename LVM")
_run_command(["lvrename", "GroupToFormat", "roottoformat", "root"])
_run_command(["vgrename", "GroupToFormat", "MainGroup"])
def unmount_partitions():
print("Unmounting partitions.")
_run_command(["umount", "/mnt/nixos/boot"])
_run_command(["umount", "/mnt/nixos"])
sleep(3)
def close_luks():
_run_command(["cryptsetup", "close", "crypttoformat"])
def rename_pc(swap):
if swap:
_rename_swap()
_rename_ext4()
_rename_lvm()
def rename_raspi():
_rename_f2fs()
def main():
raspi = _y_n("Do we rename a Raspberry Pi?")
unmount_partitions()
sleep(5)
rename_boot_partition()
if raspi:
rename_raspi()
else:
swap = _y_n("Do you have swap?")
rename_pc(swap)
close_luks()
if __name__ == "__main__":
main()