diff --git a/README.md b/README.md index 575bf72..11c5d11 100644 --- a/README.md +++ b/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 diff --git a/home-manager/modules/programs/emacs/emacs.d/lib/az_format_all.el b/home-manager/modules/programs/emacs/emacs.d/lib/az_format_all.el index 52f6412..b24cfa8 100644 --- a/home-manager/modules/programs/emacs/emacs.d/lib/az_format_all.el +++ b/home-manager/modules/programs/emacs/emacs.d/lib/az_format_all.el @@ -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) diff --git a/home-manager/modules/programs/ssh/default.nix b/home-manager/modules/programs/ssh/default.nix index 1582875..b7ea57e 100644 --- a/home-manager/modules/programs/ssh/default.nix +++ b/home-manager/modules/programs/ssh/default.nix @@ -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 diff --git a/modules/hardware/raspi4/raspi-base.nix b/modules/hardware/raspi4/raspi-base.nix index d8d4d36..933105e 100644 --- a/modules/hardware/raspi4/raspi-base.nix +++ b/modules/hardware/raspi4/raspi-base.nix @@ -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; diff --git a/modules/hardware/raspi4/raspi-ethernet.nix b/modules/hardware/raspi4/raspi-ethernet.nix index 8cc3d80..676eb90 100644 --- a/modules/hardware/raspi4/raspi-ethernet.nix +++ b/modules/hardware/raspi4/raspi-ethernet.nix @@ -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; diff --git a/modules/hardware/raspi4/raspi-usb.nix b/modules/hardware/raspi4/raspi-usb.nix index 34c1557..7356bb4 100644 --- a/modules/hardware/raspi4/raspi-usb.nix +++ b/modules/hardware/raspi4/raspi-usb.nix @@ -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"; diff --git a/scripts/create-uefi.sh b/scripts/create-uefi.sh new file mode 100755 index 0000000..4d871e1 --- /dev/null +++ b/scripts/create-uefi.sh @@ -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 diff --git a/scripts/format-disk.py b/scripts/format-disk.py index cd6b5fd..7a45c2f 100755 --- a/scripts/format-disk.py +++ b/scripts/format-disk.py @@ -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): diff --git a/scripts/format-sdcard.py b/scripts/format-sdcard.py index fec1c07..79fefdc 100755 --- a/scripts/format-sdcard.py +++ b/scripts/format-sdcard.py @@ -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__": diff --git a/setup-shell.nix b/setup-shell.nix new file mode 100644 index 0000000..b38938e --- /dev/null +++ b/setup-shell.nix @@ -0,0 +1,14 @@ +{ pkgs ? import { } }: +pkgs.mkShell { + name = "nixosbuildshell"; + nativeBuildInputs = with pkgs; [ nixFlakes ]; + + shellHook = '' + PATH=${ + pkgs.writeShellScriptBin "nix" '' + ${pkgs.nixFlakes}/bin/nix --experimental-features "nix-command flakes" "$@" + '' + }/bin:$PATH + ''; +} +