From 6953cdb81fda3fe17fb6325a64bab8db447dce99 Mon Sep 17 00:00:00 2001 From: Tom Alexander Date: Tue, 17 Dec 2024 15:26:10 -0500 Subject: [PATCH] Set up a minimal initial config. --- nix/configuration/boot.nix | 14 ++ nix/configuration/configuration.nix | 177 ++++++++++++++++++ nix/configuration/flake.nix | 66 +++++++ nix/configuration/hosts/odo/default.nix | 14 ++ nix/configuration/hosts/odo/disk-config.nix | 110 +++++++++++ .../hosts/odo/hardware-configuration.nix | 26 +++ nix/configuration/network.nix | 32 ++++ nix/configuration/zfs.nix | 16 ++ 8 files changed, 455 insertions(+) create mode 100644 nix/configuration/boot.nix create mode 100644 nix/configuration/configuration.nix create mode 100644 nix/configuration/flake.nix create mode 100644 nix/configuration/hosts/odo/default.nix create mode 100644 nix/configuration/hosts/odo/disk-config.nix create mode 100644 nix/configuration/hosts/odo/hardware-configuration.nix create mode 100644 nix/configuration/network.nix create mode 100644 nix/configuration/zfs.nix diff --git a/nix/configuration/boot.nix b/nix/configuration/boot.nix new file mode 100644 index 0000000..fd2cbeb --- /dev/null +++ b/nix/configuration/boot.nix @@ -0,0 +1,14 @@ +{ config, lib, pkgs, ... }: + +{ + imports = []; + + # Use the systemd-boot EFI boot loader. + boot.loader.systemd-boot.enable = true; + # TODO: make false on real hardware + # TODO: make not write bootx64.efi + boot.loader.efi.canTouchEfiVariables = true; + + # Automatically delete old generations + boot.loader.systemd-boot.configurationLimit = 3; +} diff --git a/nix/configuration/configuration.nix b/nix/configuration/configuration.nix new file mode 100644 index 0000000..6d37573 --- /dev/null +++ b/nix/configuration/configuration.nix @@ -0,0 +1,177 @@ +{ config, lib, pkgs, pkgs-unstable, ... }: + +{ + imports = + [ + ./hosts/odo + "${builtins.fetchTarball {url="https://github.com/nix-community/disko/archive/refs/tags/v1.9.0.tar.gz";sha256="0j76ar4qz320fakdii4659w5lww8wiz6yb7g47npywqvf2lbp388";}}/module.nix" + ./boot.nix + ./zfs.nix + ./network.nix + ]; + + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + + users.mutableUsers = false; + users.users.talexander = { + isNormalUser = true; + createHome = true; # https://github.com/NixOS/nixpkgs/issues/6481 + extraGroups = [ "wheel" ]; + packages = with pkgs; [ + tree + ]; + # Generate with `mkpasswd -m scrypt` + hashedPassword = "$7$CU..../....VXvNQ8za3wSGpdzGXNT50/$HcFtn/yvwPMCw4888BelpiAPLAxe/zU87fD.d/N6U48"; + openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGu+k5lrirokdW5zVdRVBOqEOAvAPlIkG/MdJNc9g5ky" + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIEI6mu6I5Jp+Ib0vJxapGHbEShZjyvzV8jz5DnzDrI39AAAABHNzaDo=" + "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAFNcSXwvy+brYTOGo56G93Ptuq2MmZsjvRWAfMqbmMLAAAABHNzaDo=" + ]; + }; + + # Automatic garbage collection + nix.gc = { + # Runs nix-collect-garbage --delete-older-than 5d + automatic = true; + randomizedDelaySec = "14m"; + options = "--delete-older-than 5d"; + }; + + # Use doas instead of sudo + security.doas.enable = true; + security.doas.wheelNeedsPassword = false; + security.sudo.enable = false; + security.doas.extraRules = [{ + # Retain environment (for example NIX_PATH) + keepEnv = true; + persist = true; # Only ask for a password the first time. + }]; + + # Do not use default packages (nixos includes some defaults like nano) + environment.defaultPackages = lib.mkForce []; + + environment.systemPackages = with pkgs; [ + git + wget + mg + rsync + libinput + htop + tmux + file + usbutils # for lsusb + pciutils # for lspci + ]; + + services.openssh = { + enable = true; + settings = { + PasswordAuthentication = false; + KbdInteractiveAuthentication = false; + }; + hostKeys = [ + { + path = "/persist/ssh/ssh_host_ed25519_key"; + type = "ed25519"; + } + { + path = "/persist/ssh/ssh_host_rsa_key"; + type = "rsa"; + bits = 4096; + } + ]; + }; + + # Open ports in the firewall. + networking.firewall.allowedTCPPorts = [ 22 ]; + networking.firewall.allowedUDPPorts = [ ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # Check what will be lost with `zfs diff zroot/linux/root@blank` + boot.initrd.systemd.enable = lib.mkDefault true; + boot.initrd.systemd.services.zfs-rollback = { + description = "Rollback ZFS root dataset to blank snapshot"; + wantedBy = [ + "initrd.target" + ]; + after = [ + "zfs-import-zroot.service" + ]; + before = [ + "sysroot.mount" + ]; + path = with pkgs; [ + zfs + ]; + unitConfig.DefaultDependencies = "no"; + serviceConfig.Type = "oneshot"; + script = '' + zfs rollback -r zroot/linux/root@blank + zfs rollback -r zroot/linux/home@blank + echo "rollback complete" + ''; + }; + + environment.persistence."/persist" = { + hideMounts = true; + directories = [ + "/etc/nixos" # Contains system configuration, optional + "/etc/NetworkManager/system-connections" # Wifi settings + "/var/lib/iwd" # Wifi settings + "/var/lib/nixos" # Contains user information (uids/gids) + ]; + files = [ + "/etc/ssh/ssh_host_rsa_key" + "/etc/ssh/ssh_host_rsa_key.pub" + "/etc/ssh/ssh_host_ed25519_key" + "/etc/ssh/ssh_host_ed25519_key.pub" + ]; + # users.talexander = { + # directories = []; + # files = []; + # }; + }; + + # Write a list of the currently installed packages to /etc/current-system-packages + environment.etc."current-system-packages".text = + let + packages = builtins.map (p: "${p.name}") config.environment.systemPackages; + sortedUnique = builtins.sort builtins.lessThan (lib.unique packages); + formatted = builtins.concatStringsSep "\n" sortedUnique; + in + formatted; + + # nixpkgs.overlays = [ + # (final: prev: { + # nix = pkgs-unstable.nix; + # }) + # ]; + + + + # 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 option defines the first version of NixOS you have installed on this particular machine, + # and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions. + # + # Most users should NEVER change this value after the initial install, for any reason, + # even if you've upgraded your system to a new NixOS release. + # + # This value does NOT affect the Nixpkgs version your packages and OS are pulled from, + # so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how + # to actually do that. + # + # This value being lower than the current NixOS release does NOT mean your system is + # out of date, out of support, or vulnerable. + # + # Do NOT change this value unless you have manually inspected all the changes it would make to your configuration, + # and migrated your data accordingly. + # + # For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.stateVersion . + system.stateVersion = "24.11"; # Did you read the comment? + +} diff --git a/nix/configuration/flake.nix b/nix/configuration/flake.nix new file mode 100644 index 0000000..4f30f4d --- /dev/null +++ b/nix/configuration/flake.nix @@ -0,0 +1,66 @@ +{ + description = "My system configuration"; + + inputs = { + impermanence.url = "github:nix-community/impermanence"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11"; + nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; + nixpkgs-b93b4e9b5.url = "github:NixOS/nixpkgs/b93b4e9b527904aadf52dba6ca35efde2067cbd4"; + home-manager.url = "github:nix-community/home-manager/release-24.11"; + home-manager.inputs.nixpkgs.follows = "nixpkgs"; + }; + + outputs = { self, nixpkgs, nixpkgs-unstable, nixpkgs-b93b4e9b5, impermanence, home-manager, ... }@inputs: let + base-system = {}; + in + { + nixosConfigurations.odo = nixpkgs.lib.nixosSystem rec { + system = "x86_64-linux"; + specialArgs = { + pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 { + inherit system; + # config.allowUnfree = true; + }; + pkgs-unstable = import nixpkgs-unstable { + inherit system; + # config.allowUnfree = true; + }; + }; + modules = [ + impermanence.nixosModules.impermanence + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + } + ./configuration.nix + ]; + }; + nixosConfigurations.odovm = nixpkgs.lib.nixosSystem rec { + system = "x86_64-linux"; + specialArgs = { + pkgs-b93b4e9b5 = import nixpkgs-b93b4e9b5 { + inherit system; + # config.allowUnfree = true; + }; + pkgs-unstable = import nixpkgs-unstable { + inherit system; + # config.allowUnfree = true; + }; + }; + modules = [ + impermanence.nixosModules.impermanence + home-manager.nixosModules.home-manager + { + home-manager.useGlobalPkgs = true; + home-manager.useUserPackages = true; + } + ./configuration.nix + ({lib, ...}: { + networking.dhcpcd.enable = lib.mkForce true; + networking.useDHCP = lib.mkForce true; + }) + ]; + }; + }; +} diff --git a/nix/configuration/hosts/odo/default.nix b/nix/configuration/hosts/odo/default.nix new file mode 100644 index 0000000..f7a70de --- /dev/null +++ b/nix/configuration/hosts/odo/default.nix @@ -0,0 +1,14 @@ +{ config, pkgs, ... }: +{ + imports = [ + ./hardware-configuration.nix + ./disk-config.nix + ]; + + # Generate with `head -c4 /dev/urandom | od -A none -t x4` + networking.hostId = "908cbf04"; + + networking.hostName = "odo"; # Define your hostname. + + time.timeZone = "America/New_York"; +} diff --git a/nix/configuration/hosts/odo/disk-config.nix b/nix/configuration/hosts/odo/disk-config.nix new file mode 100644 index 0000000..8b56d7e --- /dev/null +++ b/nix/configuration/hosts/odo/disk-config.nix @@ -0,0 +1,110 @@ +{ + disko.devices = { + disk = { + main = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "1G"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "umask=0077" "noatime" "discard" ]; + }; + }; + zfs = { + size = "100%"; + content = { + type = "zfs"; + pool = "zroot"; + }; + }; + }; + }; + }; + }; + zpool = { + zroot = { + type = "zpool"; + # mode = "mirror"; + # Workaround: cannot import 'zroot': I/O error in disko tests + options.cachefile = "none"; + options = { + ashift = "12"; + compatibility = "openzfs-2.2-freebsd"; + autotrim = "on"; + }; + rootFsOptions = { + acltype = "posixacl"; + atime = "off"; + relatime = "off"; + xattr = "sa"; + mountpoint = "none"; + compression = "lz4"; + canmount = "off"; + utf8only = "on"; + dnodesize = "auto"; + normalization = "formD"; + }; + + datasets = { + "linux/nix" = { + type = "zfs_fs"; + options.mountpoint = "none"; + options = { + encryption = "aes-256-gcm"; + keyformat = "passphrase"; + # keylocation = "file:///tmp/secret.key"; + }; + }; + "linux/nix/root" = { + type = "zfs_fs"; + options.mountpoint = "legacy"; + mountpoint = "/"; + postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/root@blank$' || zfs snapshot zroot/linux/nix/root@blank"; + }; + "linux/nix/nix" = { + type = "zfs_fs"; + options.mountpoint = "legacy"; + mountpoint = "/nix"; + postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/nix@blank$' || zfs snapshot zroot/linux/nix/nix@blank"; + options = { + recordsize = "16MiB"; + compression = "zstd-19"; + }; + }; + "linux/nix/home" = { + type = "zfs_fs"; + options.mountpoint = "legacy"; + mountpoint = "/home"; + postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/home@blank$' || zfs snapshot zroot/linux/nix/home@blank"; + }; + "linux/nix/persist" = { + type = "zfs_fs"; + options.mountpoint = "legacy"; + mountpoint = "/persist"; + postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/persist@blank$' || zfs snapshot zroot/linux/nix/persist@blank"; + }; + "linux/nix/state" = { + type = "zfs_fs"; + options.mountpoint = "legacy"; + mountpoint = "/state"; + postCreateHook = "zfs list -t snapshot -H -o name | grep -E '^zroot/linux/nix/state@blank$' || zfs snapshot zroot/linux/nix/state@blank"; + }; + }; + }; + }; + }; + + # Make sure all persistent volumes are marked as neededForBoot + # + # Also mounts /home so it is mounted before the user home directories are created. + fileSystems."/persist".neededForBoot = true; + fileSystems."/state".neededForBoot = true; + fileSystems."/home".neededForBoot = true; +} diff --git a/nix/configuration/hosts/odo/hardware-configuration.nix b/nix/configuration/hosts/odo/hardware-configuration.nix new file mode 100644 index 0000000..cc0eefc --- /dev/null +++ b/nix/configuration/hosts/odo/hardware-configuration.nix @@ -0,0 +1,26 @@ +# 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" "usbhid" "usb_storage" "sd_mod" "rtsx_pci_sdmmc" ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.extraModulePackages = [ ]; + + # 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; + # networking.interfaces.wlp58s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nix/configuration/network.nix b/nix/configuration/network.nix new file mode 100644 index 0000000..b9bbf5f --- /dev/null +++ b/nix/configuration/network.nix @@ -0,0 +1,32 @@ +{ config, lib, pkgs, ... }: + +{ + imports = []; + + networking.dhcpcd.enable = false; + networking.useDHCP = false; + # networking.nameservers = ["8.8.8.8" "8.8.4.4"]; + networking.nameservers = [ "194.242.2.2#doh.mullvad.net" "[2a07:e340::2]#doh.mullvad.net" ]; + # networking.nameservers = [ "1.1.1.1#one.one.one.one" "1.0.0.1#one.one.one.one" ]; + services.resolved = { + enable = true; + dnssec = "true"; + domains = [ "~." ]; + fallbackDns = [ ]; + dnsovertls = "true"; + }; + networking.wireless.iwd = { + enable = true; + + settings = { + General = { + EnableNetworkConfiguration = true; + AddressRandomization = "network"; + }; + }; + }; + environment.systemPackages = with pkgs; [ + iw + iwd + ]; +} diff --git a/nix/configuration/zfs.nix b/nix/configuration/zfs.nix new file mode 100644 index 0000000..a16d06a --- /dev/null +++ b/nix/configuration/zfs.nix @@ -0,0 +1,16 @@ +{ config, lib, pkgs, ... }: + +{ + imports = []; + + boot.zfs.devNodes = "/dev/disk/by-partuuid"; + + services.zfs = { + autoScrub = { + enable = true; + interval = "monthly"; + }; + trim.enable = true; + }; + +}