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.
|
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.
|
||||||
|
|
||||||
## Raspberry Pi installation
|
## Preparation
|
||||||
|
|
||||||
1. Add the new system to `flake.nix`.
|
On a PC you don't have to do anything special.
|
||||||
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
|
|
||||||
|
|
||||||
## 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`
|
1. `curl https://git.2li.ch/Nebucatnetzer/nixos/archive/master.tar.gz | tar xz`
|
||||||
2. `cd nixos && nix-shell`
|
1. `cd nixos && nix-shell setup-shell.nix`
|
||||||
3. `sudo ./scripts/format-disk.py`
|
1. For a normal PC run: `sudo ./scripts/format-disk.py` on a Raspberry Pi 4 run: `sudo ./scripts/format-sdcard.py`
|
||||||
4. `sudo nixos-install --no-root-passwd --root /mnt --impure --flake .#SYSTEMNAME`
|
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
|
## Update remote systems
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
("Literate Haskell" brittany)
|
("Literate Haskell" brittany)
|
||||||
("Lua" lua-fmt)
|
("Lua" lua-fmt)
|
||||||
("Markdown" prettier)
|
("Markdown" prettier)
|
||||||
("Nix" nixpkgs-fmt)
|
("Nix" nixfmt)
|
||||||
("Objective-C" clang-format)
|
("Objective-C" clang-format)
|
||||||
("OCaml" ocp-indent)
|
("OCaml" ocp-indent)
|
||||||
("Perl" perltidy)
|
("Perl" perltidy)
|
||||||
|
|
|
@ -11,7 +11,10 @@ in {
|
||||||
StrictHostKeyChecking no
|
StrictHostKeyChecking no
|
||||||
UserKnownHostsFile /dev/null
|
UserKnownHostsFile /dev/null
|
||||||
User nixos
|
User nixos
|
||||||
LogLevel QUIET
|
|
||||||
|
Host mobile.2li.local
|
||||||
|
StrictHostKeyChecking no
|
||||||
|
UserKnownHostsFile /dev/null
|
||||||
|
|
||||||
Host *.2li.local
|
Host *.2li.local
|
||||||
User andreas
|
User andreas
|
||||||
|
|
|
@ -64,16 +64,20 @@ in {
|
||||||
supportedFilesystems =
|
supportedFilesystems =
|
||||||
lib.mkForce [ "f2fs" "ntfs" "cifs" "ext4" "vfat" "nfs" "nfs4" ];
|
lib.mkForce [ "f2fs" "ntfs" "cifs" "ext4" "vfat" "nfs" "nfs4" ];
|
||||||
};
|
};
|
||||||
fileSystems = {
|
fileSystems."/" = {
|
||||||
"/" = {
|
device = "/dev/disk/by-label/NixosSd";
|
||||||
device = "/dev/disk/by-label/NIXOS_SD";
|
fsType = "ext4";
|
||||||
fsType = "ext4";
|
options = [ "noatime" ];
|
||||||
options = [ "noatime" ];
|
};
|
||||||
};
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/disk/by-label/SdBoot";
|
||||||
|
fsType = "vfat";
|
||||||
};
|
};
|
||||||
|
|
||||||
boot = {
|
boot = {
|
||||||
initrd.availableKernelModules = [
|
initrd.availableKernelModules = [
|
||||||
|
"cryptd"
|
||||||
|
"genet" # required for the ethernet to work at initrd
|
||||||
"usbhid"
|
"usbhid"
|
||||||
"usb_storage"
|
"usb_storage"
|
||||||
"vc4"
|
"vc4"
|
||||||
|
@ -81,13 +85,24 @@ in {
|
||||||
"reset-raspberrypi" # required for vl805 firmware to load
|
"reset-raspberrypi" # required for vl805 firmware to load
|
||||||
];
|
];
|
||||||
|
|
||||||
loader = {
|
initrd.luks.devices."cryptlvmsd".device = "/dev/mmcblk1p2";
|
||||||
grub.enable = false;
|
initrd.network = {
|
||||||
generic-extlinux-compatible.enable = true;
|
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.extraModulePackages = [ ];
|
||||||
boot.kernelParams = [ ];
|
|
||||||
|
|
||||||
hardware.enableRedistributableFirmware = true;
|
hardware.enableRedistributableFirmware = true;
|
||||||
hardware.pulseaudio.enable = true;
|
hardware.pulseaudio.enable = true;
|
||||||
|
|
|
@ -16,6 +16,8 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
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;
|
hardware.az-raspi4-base.enable = true;
|
||||||
networking = {
|
networking = {
|
||||||
useDHCP = false;
|
useDHCP = false;
|
||||||
|
|
|
@ -18,6 +18,8 @@ in {
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
hardware.az-raspi4-base.enable = true;
|
hardware.az-raspi4-base.enable = true;
|
||||||
|
|
||||||
|
boot.kernelParams =
|
||||||
|
[ "ip=10.7.89.159::10.7.89.1:255.255.255.0:mobile:enabcm6e4ei0" ];
|
||||||
boot = {
|
boot = {
|
||||||
kernelModules = [ "libcomposite" ];
|
kernelModules = [ "libcomposite" ];
|
||||||
loader.raspberryPi.firmwareConfig = "dtoverlay=dwc2";
|
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=""):
|
def _run_command(command, user_input=""):
|
||||||
if user_input:
|
if user_input:
|
||||||
result = subprocess.run(command,
|
result = subprocess.run(
|
||||||
capture_output=True,
|
command, capture_output=True, text=True, check=True, input=user_input
|
||||||
text=True,
|
)
|
||||||
check=True,
|
|
||||||
input=user_input)
|
|
||||||
else:
|
else:
|
||||||
result = subprocess.run(command,
|
result = subprocess.run(command, capture_output=True, text=True, check=True)
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
check=True)
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _get_system_memory():
|
def _get_system_memory():
|
||||||
mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')
|
mem_bytes = os.sysconf("SC_PAGE_SIZE") * os.sysconf("SC_PHYS_PAGES")
|
||||||
mem_gib = mem_bytes / (1024.**3)
|
mem_gib = mem_bytes / (1024.0**3)
|
||||||
return round(mem_gib)
|
return round(mem_gib)
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,16 +67,16 @@ def _partition_suffix(disk):
|
||||||
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(["parted", "--script", disk, "mkpart",
|
_run_command(
|
||||||
"ESP", "fat32", "1MiB", "512MiB"])
|
["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", "BOOT", boot_partition])
|
||||||
|
|
||||||
|
|
||||||
def create_main_partition(disk):
|
def create_main_partition(disk):
|
||||||
print("Create main partition.")
|
print("Create main partition.")
|
||||||
_run_command(["parted", "--script", disk, "mkpart",
|
_run_command(["parted", "--script", disk, "mkpart", "primary", "512MiB", "100%"])
|
||||||
"primary", "512MiB", "100%"])
|
|
||||||
return "{}{}2".format(disk, _partition_suffix(disk))
|
return "{}{}2".format(disk, _partition_suffix(disk))
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,21 +88,20 @@ def _create_main_filesystem():
|
||||||
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",
|
_run_command(["lvcreate", "-L", "{}G".format(memory), "MainGroup", "-n", "swap"])
|
||||||
"-L",
|
|
||||||
"{}G".format(memory),
|
|
||||||
"MainGroup",
|
|
||||||
"-n",
|
|
||||||
"swap"])
|
|
||||||
_run_command(["mkswap", "-L", "swap", "/dev/MainGroup/swap"])
|
_run_command(["mkswap", "-L", "swap", "/dev/MainGroup/swap"])
|
||||||
|
|
||||||
|
|
||||||
def _encrypt_disk(partition_path):
|
def _encrypt_disk(partition_path):
|
||||||
password = getpass.getpass()
|
password = getpass.getpass()
|
||||||
print("Encrypting disk.")
|
print("Encrypting disk.")
|
||||||
_run_command(["cryptsetup", "luksFormat", "-q",
|
_run_command(
|
||||||
"--type", "luks1", partition_path], user_input=password)
|
["cryptsetup", "luksFormat", "-q", "--type", "luks1", partition_path],
|
||||||
_run_command(["cryptsetup", "open", partition_path, "cryptlvm"], user_input=password)
|
user_input=password,
|
||||||
|
)
|
||||||
|
_run_command(
|
||||||
|
["cryptsetup", "open", partition_path, "cryptlvm"], user_input=password
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _setup_lvm(lvm_target):
|
def _setup_lvm(lvm_target):
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#! nix-shell -i python3 -p python3 parted
|
#! nix-shell -i python3 -p python3 parted
|
||||||
|
|
||||||
import getpass
|
import getpass
|
||||||
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,24 +16,29 @@ def _run_command(command, user_input=""):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def create_partition_table(disk):
|
def read_disks():
|
||||||
print("Create partition table.")
|
output = _run_command(["lsblk", "-dpno", "name"])
|
||||||
_run_command(["parted", "--script", disk, "mklabel", "gpt"])
|
disks = []
|
||||||
|
for disk in output.stdout.splitlines():
|
||||||
|
if "loop" in disk:
|
||||||
|
continue
|
||||||
|
disks.append(disk)
|
||||||
|
return disks
|
||||||
|
|
||||||
|
|
||||||
def create_boot_partition(disk):
|
def create_menu(disks):
|
||||||
boot_partition = f"{disk}p1"
|
for position, disk in enumerate(disks):
|
||||||
print(f"Create boot partition {boot_partition}.")
|
print("{}: {}".format(position, disk))
|
||||||
_run_command(
|
|
||||||
["parted", "--script", disk, "mkpart", "ESP", "fat32", "1MiB", "1024MiB"]
|
|
||||||
)
|
def get_disk_to_format():
|
||||||
_run_command(["parted", "--script", disk, "set", "1", "esp", "on"])
|
disk_to_format = input("Which disk dou you want to format?: ")
|
||||||
_run_command(["mkfs.fat", "-F", "32", "-n", "SdBoot", boot_partition])
|
return int(disk_to_format)
|
||||||
|
|
||||||
|
|
||||||
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", "1024MiB", "100%"])
|
_run_command(["parted", "--script", disk, "mkpart", "primary", "1GiB", "100%"])
|
||||||
return f"{disk}p2"
|
return f"{disk}p2"
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,12 +73,20 @@ def create_file_systems(partition):
|
||||||
_create_main_filesystem()
|
_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():
|
def main():
|
||||||
disk_to_format = "/dev/mmcblk0"
|
disks = read_disks()
|
||||||
create_partition_table(disk_to_format)
|
create_menu(disks)
|
||||||
create_boot_partition(disk_to_format)
|
disk_to_format = disks[get_disk_to_format()]
|
||||||
main_partition = create_main_partition(disk_to_format)
|
main_partition = create_main_partition(disk_to_format)
|
||||||
create_file_systems(main_partition)
|
create_file_systems(main_partition)
|
||||||
|
mount_partitions()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
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