From ba6d0a06a065d1c7fe7cb4d18c1734246e5bd1b2 Mon Sep 17 00:00:00 2001 From: Zoty Date: Sat, 23 May 2026 15:31:28 -0300 Subject: [PATCH] add disko --- Justfile | 7 ++ flake.lock | 21 ++++ flake.nix | 32 +++++-- installer/default.nix | 122 ++++++++++++++++++++++++ modules/_hardware/notebook-disko.nix | 60 ++++++++++++ modules/_hardware/notebook-hardware.nix | 59 +++--------- modules/notebook.nix | 49 ++++++---- 7 files changed, 277 insertions(+), 73 deletions(-) create mode 100644 installer/default.nix create mode 100644 modules/_hardware/notebook-disko.nix diff --git a/Justfile b/Justfile index 79a7504..5dbbda8 100644 --- a/Justfile +++ b/Justfile @@ -39,6 +39,13 @@ gc: generations: sudo nix-env --list-generations --profile /nix/var/nix/profiles/system +# Build the installer ISO (bootable USB image) +iso: + nix build .#nixosConfigurations.installer.config.system.build.isoImage + @echo "" + @echo "ISO built at: $(readlink -f result)/iso/*.iso" + @echo "Flash with: sudo dd if=result/iso/*.iso of=/dev/sdX bs=4M status=progress && sync" + # Edit the SOPS-encrypted secrets file secrets: sops secrets/secrets.yaml diff --git a/flake.lock b/flake.lock index 49e555e..c4468fa 100644 --- a/flake.lock +++ b/flake.lock @@ -34,6 +34,26 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1779226674, + "narHash": "sha256-wuOkjI6pRiN4sEn/EPBRnNW5cmcpvd7xtIM8y5LooAs=", + "owner": "nix-community", + "repo": "disko", + "rev": "65fb947964bd44fc0008faf77d1fcb7a9f40bb32", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "flake-aspects": { "locked": { "lastModified": 1773552804, @@ -337,6 +357,7 @@ "inputs": { "claude-code": "claude-code", "den": "den", + "disko": "disko", "flake-aspects": "flake-aspects", "home-manager": "home-manager", "import-tree": "import-tree", diff --git a/flake.nix b/flake.nix index b899f21..2571ab2 100644 --- a/flake.nix +++ b/flake.nix @@ -1,22 +1,32 @@ { inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.11"; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; - import-tree.url = "github:vic/import-tree"; - flake-aspects.url = "github:vic/flake-aspects"; - den.url = "github:vic/den"; + import-tree.url = "github:vic/import-tree"; + flake-aspects.url = "github:vic/flake-aspects"; + den.url = "github:vic/den"; + home-manager = { - url = "github:nix-community/home-manager/release-25.11"; + url = "github:nix-community/home-manager/release-25.11"; inputs.nixpkgs.follows = "nixpkgs"; }; + + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + niri-flake.url = "github:sodiboo/niri-flake"; + sops-nix = { - url = "github:Mic92/sops-nix"; + url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; + claude-code.url = "github:sadjow/claude-code-nix"; + qml-niri = { - url = "github:imiric/qml-niri/main"; + url = "github:imiric/qml-niri/main"; inputs.nixpkgs.follows = "nixpkgs"; }; }; @@ -30,6 +40,14 @@ specialArgs.inputs = inputs; }).config.flake; in flake // { + nixosConfigurations = flake.nixosConfigurations // { + installer = inputs.nixpkgs.lib.nixosSystem { + inherit system; + modules = [ ./installer/default.nix ]; + specialArgs = { inherit inputs; }; + }; + }; + devShells.${system}.default = pkgs.mkShell { packages = [ pkgs.just ]; }; diff --git a/installer/default.nix b/installer/default.nix new file mode 100644 index 0000000..6caa3e3 --- /dev/null +++ b/installer/default.nix @@ -0,0 +1,122 @@ +{ pkgs, lib, modulesPath, inputs, ... }: +let + installScript = pkgs.writeShellScriptBin "nixos-install-host" '' + set -euo pipefail + + BOLD='\033[1m' + RED='\033[0;31m' + GREEN='\033[0;32m' + YELLOW='\033[1;33m' + NC='\033[0m' + + header() { echo -e "\n''${BOLD}==> $1''${NC}"; } + ok() { echo -e "''${GREEN}[ok]''${NC} $1"; } + warn() { echo -e "''${YELLOW}[warn]''${NC} $1"; } + die() { echo -e "''${RED}[error]''${NC} $1"; exit 1; } + + FLAKE="path:/etc/nixos-config" + + header "NixOS Installer" + echo "Available hosts:" + nix eval "$FLAKE#nixosConfigurations" --apply builtins.attrNames --json 2>/dev/null \ + | ${pkgs.jq}/bin/jq -r '.[]' | grep -v installer | sed 's/^/ /' + echo "" + + read -p "Host to install: " HOST + [ -z "$HOST" ] && die "No host specified." + + header "Available disks" + lsblk -d -o NAME,SIZE,MODEL --noheadings | grep -v loop + echo "" + + CONFIGURED_DISK=$(nix eval "$FLAKE#nixosConfigurations.$HOST.config.local.notebook.disk" --raw 2>/dev/null \ + || echo "/dev/nvme0n1") + echo -e "Disk configured for this host: ''${BOLD}$CONFIGURED_DISK''${NC}" + read -p "Target disk [$CONFIGURED_DISK]: " DISK_INPUT + DISK="''${DISK_INPUT:-$CONFIGURED_DISK}" + + [ ! -b "$DISK" ] && die "$DISK is not a valid block device." + + if [ "$DISK" != "$CONFIGURED_DISK" ]; then + warn "Disk $DISK differs from configured $CONFIGURED_DISK." + warn "Edit modules/_hardware/-disko.nix and rebuild the ISO if it doesn't match." + fi + + header "Age key (secrets decryption)" + KEYS_PATH="" + + for candidate in /run/media/nixos/*/keys.txt /run/media/*/keys.txt /tmp/keys.txt; do + if [ -f "$candidate" ]; then + KEYS_PATH="$candidate" + ok "Found at $KEYS_PATH" + break + fi + done + + if [ -z "$KEYS_PATH" ]; then + warn "Age key not found automatically." + echo "Options:" + echo " 1. Copy keys.txt to a USB, mount it, and it will be found at /run/media/*" + echo " 2. Enter the path manually below" + read -p "Path to keys.txt: " KEYS_PATH + fi + + [ ! -f "$KEYS_PATH" ] && die "Age key not found at $KEYS_PATH" + + header "Confirmation" + echo -e " Host : ''${BOLD}$HOST''${NC}" + echo -e " Disk : ''${BOLD}$DISK''${NC} (ALL DATA WILL BE ERASED)" + echo -e " Keys : ''${BOLD}$KEYS_PATH''${NC}" + echo "" + read -p "Type 'yes' to continue: " CONFIRM + [ "$CONFIRM" != "yes" ] && { echo "Aborted."; exit 1; } + + header "Partitioning and formatting" + echo "(You will be prompted to set the LUKS passphrase.)" + disko --mode destroy,format,mount --flake "$FLAKE#$HOST" + + header "Copying age key" + mkdir -p /mnt/etc/sops/age + install -m 600 "$KEYS_PATH" /mnt/etc/sops/age/keys.txt + ok "Age key installed." + + header "Installing NixOS" + nixos-install --root /mnt --flake "$FLAKE#$HOST" --no-root-passwd + + echo "" + ok "Installation complete! Remove the USB drive and reboot." + ''; +in { + imports = [ + "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" + ]; + + services.getty.autologinUser = lib.mkForce "root"; + + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + tarball-ttl = 0; + }; + + # NetworkManager instead of wpa_supplicant for nmtui support + networking.networkmanager.enable = true; + networking.wireless.enable = lib.mkForce false; + + environment.systemPackages = [ + installScript + inputs.disko.packages.${pkgs.system}.default + pkgs.git + pkgs.age + pkgs.sops + pkgs.jq + pkgs.neovim + ]; + + # Embed the flake source so the install script can reference it at path:/etc/nixos-config + environment.etc."nixos-config".source = ../.; + + documentation.enable = lib.mkForce false; + documentation.nixos.enable = lib.mkForce false; + + system.stateVersion = "25.11"; +} diff --git a/modules/_hardware/notebook-disko.nix b/modules/_hardware/notebook-disko.nix new file mode 100644 index 0000000..235a91c --- /dev/null +++ b/modules/_hardware/notebook-disko.nix @@ -0,0 +1,60 @@ +{ lib, config, ... }: { + options.local.notebook.disk = lib.mkOption { + type = lib.types.str; + default = "/dev/nvme0n1"; + description = "Target block device for the notebook. Change this if the machine does not have an NVMe drive (e.g. /dev/sda)."; + }; + + config.disko.devices = { + disk.main = { + device = config.local.notebook.disk; + type = "disk"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "fmask=0077" "dmask=0077" ]; + }; + }; + + luks = { + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + settings.allowDiscards = true; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "@root" = { + mountpoint = "/"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; + "@nix" = { + mountpoint = "/nix"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; + "@home" = { + mountpoint = "/home"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; + "@log" = { + mountpoint = "/var/log"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/modules/_hardware/notebook-hardware.nix b/modules/_hardware/notebook-hardware.nix index 54711c0..2775cc9 100644 --- a/modules/_hardware/notebook-hardware.nix +++ b/modules/_hardware/notebook-hardware.nix @@ -1,54 +1,17 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, modulesPath, ... }: - +# Hardware-specific configuration for the notebook. +# fileSystems and swap are declared by disko (notebook-disko.nix). +# Regenerate this file with: nixos-generate-config --no-filesystems --show-hardware-config +{ config, lib, modulesPath, ... }: { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") - ]; + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "ums_realtek" "sd_mod" "sr_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = []; - fileSystems."/" = - { device = "/dev/disk/by-uuid/79211c8d-bd5e-4d19-b47c-2e57a4c6253e"; - fsType = "btrfs"; - options = [ "subvol=root" ]; - }; - - fileSystems."/nix" = - { device = "/dev/disk/by-uuid/79211c8d-bd5e-4d19-b47c-2e57a4c6253e"; - fsType = "btrfs"; - options = [ "subvol=nix" ]; - }; - - fileSystems."/home" = - { device = "/dev/disk/by-uuid/79211c8d-bd5e-4d19-b47c-2e57a4c6253e"; - fsType = "btrfs"; - options = [ "subvol=home" ]; - }; - - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/8981-AD7D"; - fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; - }; - - swapDevices = - [ { device = "/dev/disk/by-uuid/43d24b75-0fe1-422c-8a8f-b89f32063d3c"; } - ]; - - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.enp2s0.useDHCP = lib.mkDefault true; - # networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + networking.useDHCP = lib.mkDefault true; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/modules/notebook.nix b/modules/notebook.nix index f91c1a7..c4f9064 100644 --- a/modules/notebook.nix +++ b/modules/notebook.nix @@ -1,35 +1,48 @@ -{ den, ... }: { +{ den, inputs, lib, ... }: { den.aspects.notebook-specific.nixos = { pkgs, ... }: { - imports = [ ./_hardware/notebook-hardware.nix ]; + imports = [ + ./_hardware/notebook-hardware.nix + ./_hardware/notebook-disko.nix + inputs.disko.nixosModules.disko + ]; - hardware = { - graphics = { - enable = true; - enable32Bit = true; - }; + hardware.graphics = { + enable = true; + enable32Bit = true; + }; + + security.sudo.wheelNeedsPassword = lib.mkForce true; + + networking.firewall = { + enable = true; + allowedTCPPorts = []; + allowedUDPPorts = []; }; services.thermald.enable = true; - powerManagement.enable = true; + powerManagement.enable = true; + services.tlp = { - enable = true; - settings = { - CPU_SCALING_GOVERNOR_ON_AC = "performance"; + enable = true; + settings = { + CPU_SCALING_GOVERNOR_ON_AC = "performance"; CPU_SCALING_GOVERNOR_ON_BAT = "powersave"; }; }; boot = { - initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sd_mod"]; - initrd.kernelModules = []; - kernelModules = ["kvm-intel"]; - initrd.compressor = "zstd"; + initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sd_mod" ]; + initrd.kernelModules = [ "dm-crypt" ]; + kernelModules = [ "kvm-intel" ]; + initrd.compressor = "zstd"; + loader = { grub = { - enable = true; - device = "nodev"; - efiSupport = true; + enable = true; + device = "nodev"; + efiSupport = true; configurationLimit = 2; + enableCryptodisk = true; }; efi.canTouchEfiVariables = true; };