From 17ff37597121573c11d473068f25a232bdb5f231 Mon Sep 17 00:00:00 2001 From: Petru Paler Date: Wed, 3 Jan 2024 15:28:53 +0000 Subject: [PATCH] Import setup scripts. --- nixos-setup/c1-hardware.nix | 59 +++++++++++++ nixos-setup/c2-hardware.nix | 59 +++++++++++++ nixos-setup/c3-hardware.nix | 59 +++++++++++++ nixos-setup/configuration.nix | 155 ++++++++++++++++++++++++++++++++++ nixos-setup/fs-diff.sh | 26 ++++++ nixos-setup/keys/c1.key | Bin 0 -> 4096 bytes nixos-setup/keys/c2.key | Bin 0 -> 4096 bytes nixos-setup/keys/c3.key | Bin 0 -> 4096 bytes nixos-setup/setup.sh | 56 ++++++++++++ 9 files changed, 414 insertions(+) create mode 100644 nixos-setup/c1-hardware.nix create mode 100644 nixos-setup/c2-hardware.nix create mode 100644 nixos-setup/c3-hardware.nix create mode 100644 nixos-setup/configuration.nix create mode 100755 nixos-setup/fs-diff.sh create mode 100644 nixos-setup/keys/c1.key create mode 100644 nixos-setup/keys/c2.key create mode 100644 nixos-setup/keys/c3.key create mode 100755 nixos-setup/setup.sh diff --git a/nixos-setup/c1-hardware.nix b/nixos-setup/c1-hardware.nix new file mode 100644 index 0000000..c748107 --- /dev/null +++ b/nixos-setup/c1-hardware.nix @@ -0,0 +1,59 @@ +# 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, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/42e95613-29c2-4a47-a3cc-3627f18fdec2"; + fsType = "btrfs"; + options = [ "subvol=root" ]; + }; + + boot.initrd.luks.devices."luksroot".device = "/dev/disk/by-uuid/7fa539a0-6c91-49ec-9df2-e81708a07662"; + + fileSystems."/persist" = + { device = "/dev/disk/by-uuid/42e95613-29c2-4a47-a3cc-3627f18fdec2"; + fsType = "btrfs"; + options = [ "subvol=persist" ]; + }; + + fileSystems."/nix" = + { device = "/dev/disk/by-uuid/42e95613-29c2-4a47-a3cc-3627f18fdec2"; + fsType = "btrfs"; + options = [ "subvol=nix" ]; + }; + + fileSystems."/var/log" = + { device = "/dev/disk/by-uuid/42e95613-29c2-4a47-a3cc-3627f18fdec2"; + fsType = "btrfs"; + options = [ "subvol=log" ]; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/D8C2-9216"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + # 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.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nixos-setup/c2-hardware.nix b/nixos-setup/c2-hardware.nix new file mode 100644 index 0000000..5e3b959 --- /dev/null +++ b/nixos-setup/c2-hardware.nix @@ -0,0 +1,59 @@ +# 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, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/2d595dde-975b-498a-acb5-2e22751d3cea"; + fsType = "btrfs"; + options = [ "subvol=root" ]; + }; + + boot.initrd.luks.devices."luksroot".device = "/dev/disk/by-uuid/03ee7c3b-19d5-491d-bc2e-3b0681e6506f"; + + fileSystems."/nix" = + { device = "/dev/disk/by-uuid/2d595dde-975b-498a-acb5-2e22751d3cea"; + fsType = "btrfs"; + options = [ "subvol=nix" ]; + }; + + fileSystems."/persist" = + { device = "/dev/disk/by-uuid/2d595dde-975b-498a-acb5-2e22751d3cea"; + fsType = "btrfs"; + options = [ "subvol=persist" ]; + }; + + fileSystems."/var/log" = + { device = "/dev/disk/by-uuid/2d595dde-975b-498a-acb5-2e22751d3cea"; + fsType = "btrfs"; + options = [ "subvol=log" ]; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/B543-374F"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + # 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.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nixos-setup/c3-hardware.nix b/nixos-setup/c3-hardware.nix new file mode 100644 index 0000000..aebf78d --- /dev/null +++ b/nixos-setup/c3-hardware.nix @@ -0,0 +1,59 @@ +# 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, ... }: + +{ + imports = + [ (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = + { device = "/dev/disk/by-uuid/2b96989f-cec5-40bd-afa8-e5ca0b8f30e9"; + fsType = "btrfs"; + options = [ "subvol=root" ]; + }; + + boot.initrd.luks.devices."luksroot".device = "/dev/disk/by-uuid/c4a43a18-b480-43ed-87f2-f78a50f03976"; + + fileSystems."/nix" = + { device = "/dev/disk/by-uuid/2b96989f-cec5-40bd-afa8-e5ca0b8f30e9"; + fsType = "btrfs"; + options = [ "subvol=nix" ]; + }; + + fileSystems."/persist" = + { device = "/dev/disk/by-uuid/2b96989f-cec5-40bd-afa8-e5ca0b8f30e9"; + fsType = "btrfs"; + options = [ "subvol=persist" ]; + }; + + fileSystems."/var/log" = + { device = "/dev/disk/by-uuid/2b96989f-cec5-40bd-afa8-e5ca0b8f30e9"; + fsType = "btrfs"; + options = [ "subvol=log" ]; + }; + + fileSystems."/boot" = + { device = "/dev/disk/by-uuid/3051-C478"; + fsType = "vfat"; + }; + + swapDevices = [ ]; + + # 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.eno1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nixos-setup/configuration.nix b/nixos-setup/configuration.nix new file mode 100644 index 0000000..ee93662 --- /dev/null +++ b/nixos-setup/configuration.nix @@ -0,0 +1,155 @@ +{ config, pkgs, ... }: + +let + impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz"; +in +{ + imports = + [ + "${impermanence}/nixos.nix" + ./hardware-configuration.nix + ]; + + networking.hostName = "c1"; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.settings.trusted-users = [ "root" "@wheel" ]; + + boot.initrd.kernelModules = [ "usb_storage" ]; + boot.initrd.luks.devices."luksroot" = { + allowDiscards = true; + bypassWorkqueues = true; + keyFileSize = 4096; + keyFile = "/dev/sda"; + }; + + swapDevices = pkgs.lib.mkForce [ { + device = "/dev/disk/by-id/nvme-eui.002538b981b03d98-part2"; + randomEncryption.enable = true; + }]; + + fileSystems."/".options = ["compress=zstd" "noatime" ]; + fileSystems."/nix".options = ["compress=zstd" "noatime" ]; + fileSystems."/persist".options = ["compress=zstd" "noatime" ]; + fileSystems."/persist".neededForBoot = true; + fileSystems."/var/log".options = ["compress=zstd" "noatime" ]; + fileSystems."/var/log".neededForBoot = true; + + # reset / at each boot + # Note `lib.mkBefore` is used instead of `lib.mkAfter` here. + boot.initrd.postDeviceCommands = pkgs.lib.mkBefore '' + mkdir -p /mnt + + # We first mount the btrfs root to /mnt + # so we can manipulate btrfs subvolumes. + mount -o subvol=/ /dev/mapper/luksroot /mnt + + # While we're tempted to just delete /root and create + # a new snapshot from /root-blank, /root is already + # populated at this point with a number of subvolumes, + # which makes `btrfs subvolume delete` fail. + # So, we remove them first. + # + # /root contains subvolumes: + # - /root/var/lib/portables + # - /root/var/lib/machines + # + # I suspect these are related to systemd-nspawn, but + # since I don't use it I'm not 100% sure. + # Anyhow, deleting these subvolumes hasn't resulted + # in any issues so far, except for fairly + # benign-looking errors from systemd-tmpfiles. + btrfs subvolume list -o /mnt/root | + cut -f9 -d' ' | + while read subvolume; do + echo "deleting /$subvolume subvolume..." + btrfs subvolume delete "/mnt/$subvolume" + done && + echo "deleting /root subvolume..." && + btrfs subvolume delete /mnt/root + + echo "restoring blank /root subvolume..." + btrfs subvolume snapshot /mnt/root-blank /mnt/root + + # Once we're done rolling back to a blank snapshot, + # we can unmount /mnt and continue on the boot process. + umount /mnt + ''; + + # configure impermanence + environment.persistence."/persist" = { + directories = [ + "/etc/nixos" + ]; + files = [ + "/etc/machine-id" + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + "/etc/ssh/ssh_host_rsa_key" + "/etc/ssh/ssh_host_rsa_key.pub" + ]; + }; + + security.sudo = { + extraConfig = '' + # rollback results in sudo lectures after each reboot + Defaults lecture = never + ''; + wheelNeedsPassword = false; + }; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + networking.networkmanager.enable = true; + + time.timeZone = "Europe/Lisbon"; + + users.mutableUsers = false; + users.users.ppetru = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + + openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCdZ9dHN+DamoyRAIS8v7Ph85KyJ9zYdgwoqkp7F+smEJEdDKboHE5LA49IDQk4cgkR5xNEMtxANpJm+AXNAhQOPVl/w57vI/Z+TBtSvDoj8LuAvKjmmrPfok2iyD2IIlbctcw8ypn1revZwDb1rBFefpbbZdr5h+75tVqqmNebzxk6UQsfL++lU8HscWwYKzxrrom5aJL6wxNTfy7/Htkt4FHzoKAc5gcB2KM/q0s6NvZzX9WtdHHwAR1kib2EekssjDM9VLecX75Xhtbp+LrHOJKRnxbIanXos4UZUzaJctdNTcOYzEVLvV0BCYaktbI+uVvJcC0qo28bXbHdS3rTGRu8CsykFneJXnrrRIJw7mYWhJSTV9bf+6j/lnFNAurbiYmd4SzaTgbGjj2j38Gr/CTsyv8Rho7P3QUWbRRZnn4a7eVPtjGagqwIwS59YDxRcOy2Wdsw35ry/N2G802V7Cr3hUqeaAIev2adtn4FaG72C8enacYUeACPEhi7TYdsDzuuyt31W7AQa5Te4Uda20rTa0Y9N5Lw85uGB2ebbdYWlO2CqI/m+xNYcPkKqL7zZILz782jDw1sxWd/RUbEgJNrWjsKZ7ybiEMmhpw5vLiMGOeqQWIT6cBCNjocmW0ocU+FBLhhioyrvuZOyacoEZLoklatsL0DMkvvkbT0Ew== petru@paler.net" ]; + }; + + environment.systemPackages = with pkgs; [ + vim + ]; + + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + }; + extraConfig = '' + AllowTcpForwarding yes + X11Forwarding no + AllowAgentForwarding no + AllowStreamLocalForwarding no + AuthenticationMethods publickey + ''; + }; + + networking.firewall = { + enable = true; + allowedTCPPorts = [ 22 ]; + allowedUDPPorts = [ ]; + }; + + # Copy the NixOS configuration file and link it from the resulting system + # (/run/current-system/configuration.nix). This is useful in case you + # accidentally delete configuration.nix. + system.copySystemConfiguration = true; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It's perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "23.05"; # Did you read the comment? +} + diff --git a/nixos-setup/fs-diff.sh b/nixos-setup/fs-diff.sh new file mode 100755 index 0000000..1ee1884 --- /dev/null +++ b/nixos-setup/fs-diff.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# fs-diff.sh +set -euo pipefail + +mkdir -p /mnt/root-blank +mount -o subvol=root-blank /dev/mapper/luksroot /mnt/root-blank +OLD_TRANSID=$(btrfs subvolume find-new /mnt/root-blank 9999999) +OLD_TRANSID=${OLD_TRANSID#transid marker was } + +sudo btrfs subvolume find-new / "$OLD_TRANSID" | +sed '$d' | +cut -f17- -d' ' | +sort | +uniq | +while read path; do + path="/$path" + if [ -L "$path" ]; then + : # The path is a symbolic link, so is probably handled by NixOS already + elif [ -d "$path" ]; then + : # The path is a directory, ignore + else + echo "$path" + fi +done + +umount /mnt/root-blank diff --git a/nixos-setup/keys/c1.key b/nixos-setup/keys/c1.key new file mode 100644 index 0000000000000000000000000000000000000000..8ae583d0487a96cdd81b610c7c4b01f440c3d062 GIT binary patch literal 4096 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