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. 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. 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 ## Installation
1. Insert an USB stick with the latest NixOS ISO into your device. 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. `curl https://git.2li.ch/Nebucatnetzer/nixos/archive/master.tar.gz | tar xz` 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. `cd nixos && nix-shell setup-shell.nix` 1. Next install the system with `sudo nixos-install --no-root-passwd --root /mnt/nixos --impure --flake .#SYSTEMNAME`
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`
When everything is finished you can reboot the system and remove the USB stick. You have now a fully encrypted NixOS system. 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" ]; boot.kernelParams = [ "rootflags=atgc" "rw" ];
fileSystems."/" = { fileSystems."/" = {
device = "/dev/disk/by-label/NixosSd"; device = "/dev/disk/by-label/NIXOSSD";
fsType = "f2fs"; fsType = "f2fs";
options = [ options = [
"atgc,gc_merge" "atgc,gc_merge"
@ -77,7 +77,7 @@ in {
]; ];
}; };
fileSystems."/boot" = { fileSystems."/boot" = {
device = "/dev/disk/by-label/SdBoot"; device = "/dev/disk/by-label/BOOT";
fsType = "vfat"; 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 #! /usr/bin/env nix-shell
#! nix-shell -i python3 -p python3 #! nix-shell -i python3 -p python3 parted
import getpass import getpass
import os import os
import subprocess
import sys import sys
import subprocess
import zipfile
from time import sleep
from urllib.request import urlretrieve
def _run_command(command, user_input=""): def _run_command(command, user_input=""):
@ -56,91 +61,135 @@ def get_disk_to_format():
def create_partition_table(disk): def create_partition_table(disk):
print("Create partition table.") print("Create partition table.")
_run_command(["parted", "--script", disk, "mklabel", "gpt"]) _run_command(["parted", "--script", disk, "mklabel", "gpt"])
sleep(5)
def _partition_suffix(disk): def _partition_suffix(disk):
if "nvmne" in disk: prefixes = ["nvmne", "mmc"]
if any(prefix in disk for prefix in prefixes):
return "p" return "p"
return "" 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): def create_boot_partition(disk):
boot_partition = "{}{}1".format(disk, _partition_suffix(disk)) boot_partition = "{}{}1".format(disk, _partition_suffix(disk))
print("Create boot partition {}.".format(boot_partition)) print("Create boot partition {}.".format(boot_partition))
_run_command( _run_command(["parted", "--script", disk, "mkpart", "ESP", "fat32", "0%", "1GiB"])
["parted", "--script", disk, "mkpart", "ESP", "fat32", "1MiB", "512MiB"]
)
_run_command(["parted", "--script", disk, "set", "1", "esp", "on"]) _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): def create_main_partition(disk):
print("Create main partition.") 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)) return "{}{}2".format(disk, _partition_suffix(disk))
def _create_main_filesystem(): def _create_ext4():
_run_command(["lvcreate", "-l", "100%FREE", "MainGroup", "-n", "root"]) _run_command(["lvcreate", "-l", "100%FREE", "grouptoformat", "-n", "ROOTTOFRMT"])
_run_command(["mkfs.ext4", "-L", "nixos", "/dev/MainGroup/root"]) _run_command(["mkfs.ext4", "-L", "ROOTTOFRMT", "/dev/grouptoformat/ROOTTOFRMT"])
def _create_f2fs():
_run_command(["mkfs.f2fs", "-l", "ROOTTOFRMT", "/dev/mapper/crypttoformat"])
def _create_swap(): def _create_swap():
memory = _get_system_memory() memory = _get_system_memory()
print("Create swap partition of {} GiB in size".format(memory)) print("Create swap partition of {} GiB in size".format(memory))
_run_command(["lvcreate", "-L", "{}G".format(memory), "MainGroup", "-n", "swap"]) _run_command(
_run_command(["mkswap", "-L", "swap", "/dev/MainGroup/swap"]) ["lvcreate", "-L", "{}G".format(memory), "grouptoformat", "-n", "SWAPTOFRMT"]
)
_run_command(["mkswap", "-L", "SWAPTOFRMT", "/dev/grouptoformat/SWAPTOFRMT"])
def _encrypt_disk(partition_path): def _encrypt_disk(partition_path):
password = getpass.getpass() password = getpass.getpass()
print("Encrypting disk.") print("Encrypting disk.")
_run_command( _run_command(
["cryptsetup", "luksFormat", "-q", "--type", "luks1", partition_path], ["cryptsetup", "luksFormat", "-q", partition_path],
user_input=password, user_input=password,
) )
_run_command( _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): def _setup_lvm(lvm_target):
print("Set up LVM on {}.".format(lvm_target)) print("Set up LVM on {}.".format(lvm_target))
_run_command(["pvcreate", 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.") print("Mounting partitions.")
_run_command(["mount", "/dev/MainGroup/root", "/mnt"]) sleep(5)
os.mkdir("/mnt/boot") os.makedirs(root_target, exist_ok=True)
_run_command(["mount", "/dev/disk/by-label/BOOT", "/mnt/boot"]) _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.") print("Creating filesystems.")
if encryption: if encryption:
lvm_target = "/dev/mapper/cryptlvm" lvm_target = "/dev/mapper/crypttoformat"
_encrypt_disk(partition) _encrypt_disk(partition)
else: else:
lvm_target = partition lvm_target = partition
_setup_lvm(lvm_target) _setup_lvm(lvm_target)
if swap: if swap:
_create_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(): def main():
disks = read_disks() disks = read_disks()
create_menu(disks) create_menu(disks)
disk_to_format = disks[get_disk_to_format()] disk_to_format = disks[get_disk_to_format()]
swap = _y_n("Do you need swap?") raspi = _y_n("Do you want to setup a Raspi?")
encryption = _y_n("Do you want to encrypt your data?")
create_partition_table(disk_to_format) create_partition_table(disk_to_format)
create_boot_partition(disk_to_format) create_boot_partition(disk_to_format)
main_partition = create_main_partition(disk_to_format) main_partition = create_main_partition(disk_to_format)
create_file_systems(main_partition, swap, encryption) if raspi:
mount_partitions() 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__": 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()