Finalise UEFI support for Raspberry Pi 4
This commit is contained in:
parent
5e83a5049b
commit
e9fd402dba
31
README.md
31
README.md
|
@ -4,25 +4,26 @@ 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.
|
||||
|
||||
## Raspberry Pi installation
|
||||
## Preparation
|
||||
|
||||
1. Add the new system to `flake.nix`.
|
||||
2. Build the image with `scripts/build-raspi-image.sh SYSTEMNAME`
|
||||
3. Flash the image to an SD card
|
||||
`dd if=~/Downloads/SYSTEMNAME.img of=/dev/mmcblk0 bs=4M`.
|
||||
4. After you've booted the Pi get the new SSH key with
|
||||
`ssh-keyscan hostname.custom.domain` and add it to `scrts/secrets.nix`.
|
||||
5. Then login into the new Pi and mount the `FIRMWARE` partition with
|
||||
`sudo mkdir -p /mnt && sudo mount /dev/disk/by-label/FIRMWARE /mnt` and make
|
||||
sure that your `config.txt` looks like [./systems/raspi4/config.txt](./systems/raspi4/config.txt)
|
||||
6. Change the password
|
||||
On a PC you don't have to do anything special.
|
||||
|
||||
## x86 installation
|
||||
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`
|
||||
2. `cd nixos && nix-shell`
|
||||
3. `sudo ./scripts/format-disk.py`
|
||||
4. `sudo nixos-install --no-root-passwd --root /mnt --impure --flake .#SYSTEMNAME`
|
||||
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`
|
||||
|
||||
When everything is finished you can reboot the system and remove the USB stick. You have now a fully encrypted NixOS system.
|
||||
|
||||
## Update remote systems
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
("Literate Haskell" brittany)
|
||||
("Lua" lua-fmt)
|
||||
("Markdown" prettier)
|
||||
("Nix" nixpkgs-fmt)
|
||||
("Nix" nixfmt)
|
||||
("Objective-C" clang-format)
|
||||
("OCaml" ocp-indent)
|
||||
("Perl" perltidy)
|
||||
|
|
|
@ -11,7 +11,10 @@ in {
|
|||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile /dev/null
|
||||
User nixos
|
||||
LogLevel QUIET
|
||||
|
||||
Host mobile.2li.local
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile /dev/null
|
||||
|
||||
Host *.2li.local
|
||||
User andreas
|
||||
|
|
|
@ -64,16 +64,20 @@ in {
|
|||
supportedFilesystems =
|
||||
lib.mkForce [ "f2fs" "ntfs" "cifs" "ext4" "vfat" "nfs" "nfs4" ];
|
||||
};
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
options = [ "noatime" ];
|
||||
};
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-label/NixosSd";
|
||||
fsType = "ext4";
|
||||
options = [ "noatime" ];
|
||||
};
|
||||
fileSystems."/boot" = {
|
||||
device = "/dev/disk/by-label/SdBoot";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
boot = {
|
||||
initrd.availableKernelModules = [
|
||||
"cryptd"
|
||||
"genet" # required for the ethernet to work at initrd
|
||||
"usbhid"
|
||||
"usb_storage"
|
||||
"vc4"
|
||||
|
@ -81,13 +85,24 @@ in {
|
|||
"reset-raspberrypi" # required for vl805 firmware to load
|
||||
];
|
||||
|
||||
loader = {
|
||||
grub.enable = false;
|
||||
generic-extlinux-compatible.enable = true;
|
||||
initrd.luks.devices."cryptlvmsd".device = "/dev/mmcblk1p2";
|
||||
initrd.network = {
|
||||
enable = true;
|
||||
ssh = {
|
||||
enable = true;
|
||||
port = 22;
|
||||
shell = "/bin/cryptsetup-askpass";
|
||||
authorizedKeys =
|
||||
config.users.users.${config.az-username}.openssh.authorizedKeys.keys;
|
||||
hostKeys = [
|
||||
"/etc/secrets/initrd/ssh_host_rsa_key"
|
||||
"/etc/secrets/initrd/ssh_host_ed25519_key"
|
||||
];
|
||||
};
|
||||
};
|
||||
loader = { systemd-boot.enable = true; };
|
||||
};
|
||||
boot.extraModulePackages = [ ];
|
||||
boot.kernelParams = [ ];
|
||||
|
||||
hardware.enableRedistributableFirmware = true;
|
||||
hardware.pulseaudio.enable = true;
|
||||
|
|
|
@ -16,6 +16,8 @@ in {
|
|||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
boot.kernelParams =
|
||||
[ "ip=${cfg.ip}::10.7.89.1:255.255.255.0:${cfg.hostname}:eth0" ];
|
||||
hardware.az-raspi4-base.enable = true;
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
|
|
|
@ -18,6 +18,8 @@ in {
|
|||
config = lib.mkIf cfg.enable {
|
||||
hardware.az-raspi4-base.enable = true;
|
||||
|
||||
boot.kernelParams =
|
||||
[ "ip=10.7.89.159::10.7.89.1:255.255.255.0:mobile:enabcm6e4ei0" ];
|
||||
boot = {
|
||||
kernelModules = [ "libcomposite" ];
|
||||
loader.raspberryPi.firmwareConfig = "dtoverlay=dwc2";
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#! /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
|
|
@ -9,22 +9,17 @@ import sys
|
|||
|
||||
def _run_command(command, user_input=""):
|
||||
if user_input:
|
||||
result = subprocess.run(command,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True,
|
||||
input=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)
|
||||
result = subprocess.run(command, capture_output=True, text=True, check=True)
|
||||
return result
|
||||
|
||||
|
||||
def _get_system_memory():
|
||||
mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
|
||||
mem_gib = mem_bytes / (1024.**3)
|
||||
mem_bytes = os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES")
|
||||
mem_gib = mem_bytes / (1024.0**3)
|
||||
return round(mem_gib)
|
||||
|
||||
|
||||
|
@ -72,16 +67,16 @@ def _partition_suffix(disk):
|
|||
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", "1MiB", "512MiB"]
|
||||
)
|
||||
_run_command(["parted", "--script", disk, "set", "1", "esp", "on"])
|
||||
_run_command(["mkfs.fat", "-F", "32", "-n", "BOOT", boot_partition])
|
||||
|
||||
|
||||
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", "512MiB", "100%"])
|
||||
return "{}{}2".format(disk, _partition_suffix(disk))
|
||||
|
||||
|
||||
|
@ -93,21 +88,20 @@ def _create_main_filesystem():
|
|||
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(["lvcreate", "-L", "{}G".format(memory), "MainGroup", "-n", "swap"])
|
||||
_run_command(["mkswap", "-L", "swap", "/dev/MainGroup/swap"])
|
||||
|
||||
|
||||
def _encrypt_disk(partition_path):
|
||||
password = getpass.getpass()
|
||||
print("Encrypting disk.")
|
||||
_run_command(["cryptsetup", "luksFormat", "-q",
|
||||
"--type", "luks1", partition_path], user_input=password)
|
||||
_run_command(["cryptsetup", "open", partition_path, "cryptlvm"], user_input=password)
|
||||
_run_command(
|
||||
["cryptsetup", "luksFormat", "-q", "--type", "luks1", partition_path],
|
||||
user_input=password,
|
||||
)
|
||||
_run_command(
|
||||
["cryptsetup", "open", partition_path, "cryptlvm"], user_input=password
|
||||
)
|
||||
|
||||
|
||||
def _setup_lvm(lvm_target):
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#! nix-shell -i python3 -p python3 parted
|
||||
|
||||
import getpass
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
|
||||
|
@ -15,24 +16,29 @@ def _run_command(command, user_input=""):
|
|||
return result
|
||||
|
||||
|
||||
def create_partition_table(disk):
|
||||
print("Create partition table.")
|
||||
_run_command(["parted", "--script", disk, "mklabel", "gpt"])
|
||||
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_boot_partition(disk):
|
||||
boot_partition = f"{disk}p1"
|
||||
print(f"Create boot partition {boot_partition}.")
|
||||
_run_command(
|
||||
["parted", "--script", disk, "mkpart", "ESP", "fat32", "1MiB", "1024MiB"]
|
||||
)
|
||||
_run_command(["parted", "--script", disk, "set", "1", "esp", "on"])
|
||||
_run_command(["mkfs.fat", "-F", "32", "-n", "SdBoot", boot_partition])
|
||||
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", "1024MiB", "100%"])
|
||||
_run_command(["parted", "--script", disk, "mkpart", "primary", "1GiB", "100%"])
|
||||
return f"{disk}p2"
|
||||
|
||||
|
||||
|
@ -67,12 +73,20 @@ def create_file_systems(partition):
|
|||
_create_main_filesystem()
|
||||
|
||||
|
||||
def mount_partitions():
|
||||
print("Mounting partitions.")
|
||||
_run_command(["mount", "/dev/MainGroupSd/sdroot", "/mnt"])
|
||||
os.mkdir("/mnt/boot")
|
||||
_run_command(["mount", "/dev/disk/by-label/SdBoot", "/mnt/boot"])
|
||||
|
||||
|
||||
def main():
|
||||
disk_to_format = "/dev/mmcblk0"
|
||||
create_partition_table(disk_to_format)
|
||||
create_boot_partition(disk_to_format)
|
||||
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__":
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
{ pkgs ? import <nixpkgs> { } }:
|
||||
pkgs.mkShell {
|
||||
name = "nixosbuildshell";
|
||||
nativeBuildInputs = with pkgs; [ nixFlakes ];
|
||||
|
||||
shellHook = ''
|
||||
PATH=${
|
||||
pkgs.writeShellScriptBin "nix" ''
|
||||
${pkgs.nixFlakes}/bin/nix --experimental-features "nix-command flakes" "$@"
|
||||
''
|
||||
}/bin:$PATH
|
||||
'';
|
||||
}
|
||||
|
Loading…
Reference in New Issue