diff --git a/SwarselSystems.org b/SwarselSystems.org index c365d93..2f72043 100644 --- a/SwarselSystems.org +++ b/SwarselSystems.org @@ -640,8 +640,12 @@ This section used to be much longer, since I performed all of my imports right h live = lib.nixosSystem { specialArgs = { inherit inputs outputs; }; system = "x86_64-linux"; - modules = nixModules ++ [ - (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix") + modules = [ + { + _module.args = { inherit self; }; + } + "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + "${nixpkgs}/nixos/modules/installer/cd-dvd/channel.nix" ./profiles/live ]; }; @@ -746,81 +750,73 @@ This section mainly exists house different `configuration.nix` files for system #+begin_src nix :tangle profiles/live/default.nix - { inputs, outputs, config, pkgs, lib, ... }: + { self, inputs, config, pkgs, lib, ... }: + let + pubKeys = lib.filesystem.listFilesRecursive "${self}/secrets/keys/ssh"; + in { imports = [ - # ../optional/nixos/steam.nix - # ../optional/nixos/virtualbox.nix - # ../optional/nixos/vmware.nix - ../optional/nixos/autologin.nix - ../optional/nixos/nswitch-rcm.nix - # ../optional/nixos/work.nix + inputs.lanzaboote.nixosModules.lanzaboote + inputs.disko.nixosModules.disko + inputs.impermanence.nixosModules.impermanence + inputs.sops-nix.nixosModules.sops - inputs.home-manager.nixosModules.home-manager - { - home-manager.users.swarsel.imports = outputs.mixedModules ++ [ - ../optional/home/gaming.nix - # ../optional/home/work.nix - ] ++ (builtins.attrValues outputs.homeManagerModules); - } - ] ++ (builtins.attrValues outputs.nixosModules); + ../optional/nixos/minimal.nix + ]; + + + isoImage = { + makeEfiBootable = true; + makeUsbBootable = true; + squashfsCompression = "zstd -Xcompression-level 3"; + }; nixpkgs = { - inherit (outputs) overlays; - config = { - allowUnfree = true; - allowBroken = true; + hostPlatform = lib.mkDefault "x86_64-linux"; + config.allowUnfree = true; + }; + + services.getty.autologinUser = lib.mkForce "swarsel"; + + users = { + groups.swarsel = {}; + users = { + swarsel = { + name = "swarsel"; + group = "swarsel"; + isNormalUser = true; + shell = pkgs.zsh; + password = "setup"; # this is overwritten after install + openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key); + }; + root = { + shell = pkgs.zsh; + password = lib.mkForce config.users.users.swarsel.password; # this is overwritten after install + openssh.authorizedKeys.keys = config.users.users.swarsel.openssh.authorizedKeys.keys; + }; }; }; - isoImage.makeEfiBootable = true; - isoImage.makeUsbBootable = true; - - networking.networkmanager.wifi.scanRandMacAddress = false; - - boot = { - loader.efi.canTouchEfiVariables = true; - kernelPackages = pkgs.linuxPackages_latest; + systemd = { + services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; + targets = { + sleep.enable = false; + suspend.enable = false; + hibernate.enable = false; + hybrid-sleep.enable = false; + }; }; system.stateVersion = lib.mkForce "23.05"; - services.getty.autologinUser = lib.mkForce "swarsel"; networking = { hostName = "live"; - wireless.enable = lib.mkForce false; - firewall.enable = true; + wireless.enable = false; }; - - swarselsystems = { - wallpaper = ../../wallpaper/lenovowp.png; - hasBluetooth = true; - hasFingerprint = true; - impermanence = false; - initialSetup = true; - isBtrfs = false; - }; - - home-manager.users.swarsel.swarselsystems = { - isLaptop = false; - isNixos = true; - isBtrfs = false; - startup = [ - { command = "nextcloud --background"; } - { command = "vesktop --start-minimized --enable-speech-dispatcher --ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime"; } - { command = "element-desktop --hidden --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu-driver-bug-workarounds"; } - { command = "ANKI_WAYLAND=1 anki"; } - { command = "OBSIDIAN_USE_WAYLAND=1 obsidian"; } - { command = "nm-applet"; } - { command = "teams-for-linux"; } - { command = "1password"; } - { command = "feishin"; } - ]; - }; } @@ -2081,6 +2077,139 @@ This utility checks if there are updated packages in nixpkgs-unstable. It does s } #+end_src +**** bootstrap + +This program sets up a new NixOS host. + +#+begin_src shell :tangle scripts/bootstrap.sh + # highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/scripts/bootstrap-nixos.sh + set -eo pipefail + + target_hostname="" + target_destination="" + target_user="swarsel" + ssh_port="22" + temp=$(mktemp -d) + + function help_and_exit() { + echo + echo "Remotely installs NixOS on a target machine using this nix-config." + echo + echo "USAGE: $0 -n -d [OPTIONS]" + echo + echo "ARGS:" + echo " -n specify target_hostname of the target host to deploy the nixos config on." + echo " -d specify ip or url to the target host." + echo " target during install process." + echo + echo "OPTIONS:" + echo " -u specify target_user with sudo access. nix-config will be cloned to their home." + echo " Default='${target_user}'." + echo " --port specify the ssh port to use for remote access. Default=${ssh_port}." + echo " --impermanence Use this flag if the target machine has impermanence enabled. WARNING: Assumes /persist path." + echo " --debug Enable debug mode." + echo " -h | --help Print this help." + exit 0 + } + + function cleanup() { + rm -rf "$temp" + } + trap cleanup exit + + function red() { + echo -e "\x1B[31m[!] $1 \x1B[0m" + if [ -n "${2-}" ]; then + echo -e "\x1B[31m[!] $($2) \x1B[0m" + fi + } + function green() { + echo -e "\x1B[32m[+] $1 \x1B[0m" + if [ -n "${2-}" ]; then + echo -e "\x1B[32m[+] $($2) \x1B[0m" + fi + } + function yellow() { + echo -e "\x1B[33m[*] $1 \x1B[0m" + if [ -n "${2-}" ]; then + echo -e "\x1B[33m[*] $($2) \x1B[0m" + fi + } + + function yes_or_no() { + echo -en "\x1B[32m[+] $* [y/n] (default: y): \x1B[0m" + while true; do + read -rp "" yn + yn=${yn:-y} + case $yn in + [Yy]*) return 0 ;; + [Nn]*) return 1 ;; + esac + done + } + + while [[ $# -gt 0 ]]; do + case "$1" in + -n) + shift + target_hostname=$1 + ;; + -d) + shift + target_destination=$1 + ;; + -u) + shift + target_user=$1 + ;; + --port) + shift + ssh_port=$1 + ;; + --temp-override) + shift + temp=$1 + ;; + --debug) + set -x + ;; + -h | --help) help_and_exit ;; + ,*) + echo "Invalid option detected." + help_and_exit + ;; + esac + shift + done + + ssh_cmd="ssh -oport=${ssh_port} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -t $target_user@$target_destination" + # ssh_root_cmd=$(echo "$ssh_cmd" | sed "s|${target_user}@|root@|") # uses @ in the sed switch to avoid it triggering on the $ssh_key value + ssh_root_cmd=${ssh_cmd/${target_user}@/root@} + + scp_cmd="scp -oport=${ssh_port} -o StrictHostKeyChecking=no" + + git_root=$(git rev-parse --show-toplevel) + + green "Wiping known_hosts of $target_destination" + sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts + + green "Generating hardware-config.nix for $target_hostname and adding it to the nix-config." + $ssh_root_cmd "nixos-generate-config --no-filesystems --root /mnt" + mkdir profiles/"$target_hostname" + $scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "${git_root}"/profiles/"$target_hostname"/hardware-configuration.nix +#+end_src + + +#+begin_src nix :tangle pkgs/bootstrap/default.nix + { writeShellApplication, openssh }: + + writeShellApplication { + name = "bootstrap"; + runtimeInputs = [ openssh ]; + text = builtins.readFile ../../scripts/bootstrap.sh; + } +#+end_src + *** Overlays (additions, overrides, nixpkgs-stable) :PROPERTIES: @@ -5945,6 +6074,74 @@ Options that I need specifically at work. There are more options at [[#h:f0b2ea9 } #+end_src +**** Minimal Install + + These options are really only to be used on the iso image in order to run nixos-anywhere. + +#+begin_src nix :tangle profiles/optional/nixos/minimal.nix + { self, lib, pkgs, config, ... }: + { + + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + warn-dirty = false; + }; + + boot = { + # initrd.systemd.enable = true; + kernelPackages = pkgs.linuxPackages_latest; + supportedFilesystems = lib.mkForce [ "brtfs" "vfat" ]; + loader = { + efi.canTouchEfiVariables = true; + systemd-boot = { + enable = true; + configurationLimit = lib.mkDefault 5; + consoleMode = lib.mkDefault "max"; + }; + }; + }; + + services = { + qemuGuest.enable = true; + openssh = { + enable = true; + ports = lib.mkDefault [ 22 ]; + settings.PermitRootLogin = "yes"; + authorizedKeysFiles = lib.mkForce [ + "/etc/ssh/authorized_keys.d/%u" + ]; + }; + }; + + security.pam = { + sshAgentAuth.enable = true; + services = { + sudo.u2fAuth = true; + }; + }; + + environment.systemPackages = with pkgs; [ + curl + rsync + ssh-to-age + sops + vim + just + ]; + + programs = { + git.enable = true; + zsh.enable = lib.mkDefault true; + }; + + fileSystems."/boot".options = [ "umask=0077" ]; + + networking.networkmanager.enable = true; + + + } +#+end_src + ** Home-manager :PROPERTIES: :CUSTOM_ID: h:08ded95b-9c43-475d-a0b2-fc088a512287 diff --git a/flake.nix b/flake.nix index 4c6732f..af3ee34 100644 --- a/flake.nix +++ b/flake.nix @@ -218,8 +218,12 @@ live = lib.nixosSystem { specialArgs = { inherit inputs outputs; }; system = "x86_64-linux"; - modules = nixModules ++ [ - (nixpkgs + "/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix") + modules = [ + { + _module.args = { inherit self; }; + } + "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix" + "${nixpkgs}/nixos/modules/installer/cd-dvd/channel.nix" ./profiles/live ]; }; diff --git a/justfile b/justfile new file mode 100644 index 0000000..34cd4c2 --- /dev/null +++ b/justfile @@ -0,0 +1,21 @@ +default: + @just --list + +check: + nix flake check --keep-going + +check-trace: + nix flake check --show-trace + +update: + nix flake update + +iso: + rm -rf result + nix build .#nixosConfigurations.iso.config.system.build.isoImage && ln -sf result/iso/*.iso latest.iso + +iso-install DRIVE: iso + sudo dd if=$(eza --sort changed result/iso/*.iso | tail -n1) of={{DRIVE}} bs=4M status=progress oflag=sync + +sync USER HOST: + rsync -av --filter=':- .gitignore' -e "ssh -l {{USER}}" . {{USER}}@{{HOST}}:.dotfiles/ diff --git a/pkgs/bootstrap/default.nix b/pkgs/bootstrap/default.nix new file mode 100644 index 0000000..2f7062f --- /dev/null +++ b/pkgs/bootstrap/default.nix @@ -0,0 +1,7 @@ +{ writeShellApplication, openssh }: + +writeShellApplication { + name = "bootstrap"; + runtimeInputs = [ openssh ]; + text = builtins.readFile ../../scripts/bootstrap.sh; +} diff --git a/profiles/common/disks/btrfs-luks.nix b/profiles/common/disks/btrfs-luks.nix new file mode 100644 index 0000000..107ee28 --- /dev/null +++ b/profiles/common/disks/btrfs-luks.nix @@ -0,0 +1,89 @@ +# NOTE: ... is needed because dikso passes diskoFile +{ lib +, pkgs +, disk ? "/dev/vda" +, withSwap ? false +, swapSize +, config +, ... +}: +{ + disko.devices = { + disk = { + disk0 = { + type = "disk"; + device = disk; + content = { + type = "gpt"; + partitions = { + ESP = { + priority = 1; + name = "ESP"; + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ "defaults" ]; + }; + }; + luks = { + size = "100%"; + content = { + type = "luks"; + name = "cryptroot"; + passwordFile = "/tmp/disko-password"; # this is populated by bootstrap-nixos.sh + settings = { + allowDiscards = true; + # https://github.com/hmajid2301/dotfiles/blob/a0b511c79b11d9b4afe2a5e2b7eedb2af23e288f/systems/x86_64-linux/framework/disks.nix#L36 + crypttabExtraOpts = [ + "fido2-device=auto" + "token-timeout=10" + ]; + }; + # Subvolumes must set a mountpoint in order to be mounted, + # unless their parent is mounted + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; # force overwrite + subvolumes = { + "@root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "@persist" = { + mountpoint = "${config.hostSpec.persistFolder}"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "@nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + "@swap" = lib.mkIf withSwap { + mountpoint = "/.swapvol"; + swap.swapfile.size = "${swapSize}G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; + + environment.systemPackages = [ + pkgs.yubikey-manager # For luks fido2 enrollment before full install + ]; +} diff --git a/profiles/common/nixos/packages.nix b/profiles/common/nixos/packages.nix index e7f77dd..f09506d 100644 --- a/profiles/common/nixos/packages.nix +++ b/profiles/common/nixos/packages.nix @@ -28,6 +28,9 @@ nix-index + # better make for general tasks + just + # keyboards qmk vial diff --git a/profiles/live/default.nix b/profiles/live/default.nix index 163e16c..09d228e 100644 --- a/profiles/live/default.nix +++ b/profiles/live/default.nix @@ -1,76 +1,68 @@ -{ inputs, outputs, config, pkgs, lib, ... }: +{ self, inputs, config, pkgs, lib, ... }: +let + pubKeys = lib.filesystem.listFilesRecursive "${self}/secrets/keys/ssh"; +in { imports = [ - # ../optional/nixos/steam.nix - # ../optional/nixos/virtualbox.nix - # ../optional/nixos/vmware.nix - ../optional/nixos/autologin.nix - ../optional/nixos/nswitch-rcm.nix - # ../optional/nixos/work.nix + inputs.lanzaboote.nixosModules.lanzaboote + inputs.disko.nixosModules.disko + inputs.impermanence.nixosModules.impermanence + inputs.sops-nix.nixosModules.sops - inputs.home-manager.nixosModules.home-manager - { - home-manager.users.swarsel.imports = outputs.mixedModules ++ [ - ../optional/home/gaming.nix - # ../optional/home/work.nix - ] ++ (builtins.attrValues outputs.homeManagerModules); - } - ] ++ (builtins.attrValues outputs.nixosModules); + ../optional/nixos/minimal.nix + ]; + + + isoImage = { + makeEfiBootable = true; + makeUsbBootable = true; + squashfsCompression = "zstd -Xcompression-level 3"; + }; nixpkgs = { - inherit (outputs) overlays; - config = { - allowUnfree = true; - allowBroken = true; + hostPlatform = lib.mkDefault "x86_64-linux"; + config.allowUnfree = true; + }; + + services.getty.autologinUser = lib.mkForce "swarsel"; + + users = { + groups.swarsel = { }; + users = { + swarsel = { + name = "swarsel"; + group = "swarsel"; + isNormalUser = true; + shell = pkgs.zsh; + password = "setup"; # this is overwritten after install + openssh.authorizedKeys.keys = lib.lists.forEach pubKeys (key: builtins.readFile key); + }; + root = { + shell = pkgs.zsh; + password = lib.mkForce config.users.users.swarsel.password; # this is overwritten after install + openssh.authorizedKeys.keys = config.users.users.swarsel.openssh.authorizedKeys.keys; + }; }; }; - isoImage.makeEfiBootable = true; - isoImage.makeUsbBootable = true; - - networking.networkmanager.wifi.scanRandMacAddress = false; - - boot = { - loader.efi.canTouchEfiVariables = true; - kernelPackages = pkgs.linuxPackages_latest; + systemd = { + services.sshd.wantedBy = lib.mkForce [ "multi-user.target" ]; + targets = { + sleep.enable = false; + suspend.enable = false; + hibernate.enable = false; + hybrid-sleep.enable = false; + }; }; system.stateVersion = lib.mkForce "23.05"; - services.getty.autologinUser = lib.mkForce "swarsel"; networking = { hostName = "live"; - wireless.enable = lib.mkForce false; - firewall.enable = true; + wireless.enable = false; }; - - swarselsystems = { - wallpaper = ../../wallpaper/lenovowp.png; - hasBluetooth = true; - hasFingerprint = true; - impermanence = false; - initialSetup = true; - isBtrfs = false; - }; - - home-manager.users.swarsel.swarselsystems = { - isLaptop = false; - isNixos = true; - isBtrfs = false; - startup = [ - { command = "nextcloud --background"; } - { command = "vesktop --start-minimized --enable-speech-dispatcher --ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime"; } - { command = "element-desktop --hidden --enable-features=UseOzonePlatform --ozone-platform=wayland --disable-gpu-driver-bug-workarounds"; } - { command = "ANKI_WAYLAND=1 anki"; } - { command = "OBSIDIAN_USE_WAYLAND=1 obsidian"; } - { command = "nm-applet"; } - { command = "teams-for-linux"; } - { command = "1password"; } - { command = "feishin"; } - ]; - }; } diff --git a/profiles/optional/nixos/minimal.nix b/profiles/optional/nixos/minimal.nix new file mode 100644 index 0000000..bca0e08 --- /dev/null +++ b/profiles/optional/nixos/minimal.nix @@ -0,0 +1,60 @@ +{ self, lib, pkgs, config, ... }: +{ + + nix.settings = { + experimental-features = [ "nix-command" "flakes" ]; + warn-dirty = false; + }; + + boot = { + # initrd.systemd.enable = true; + kernelPackages = pkgs.linuxPackages_latest; + supportedFilesystems = lib.mkForce [ "brtfs" "vfat" ]; + loader = { + efi.canTouchEfiVariables = true; + systemd-boot = { + enable = true; + configurationLimit = lib.mkDefault 5; + consoleMode = lib.mkDefault "max"; + }; + }; + }; + + services = { + qemuGuest.enable = true; + openssh = { + enable = true; + ports = lib.mkDefault [ 22 ]; + settings.PermitRootLogin = "yes"; + authorizedKeysFiles = lib.mkForce [ + "/etc/ssh/authorized_keys.d/%u" + ]; + }; + }; + + security.pam = { + sshAgentAuth.enable = true; + services = { + sudo.u2fAuth = true; + }; + }; + + environment.systemPackages = with pkgs; [ + curl + rsync + ssh-to-age + sops + vim + ]; + + programs = { + git.enable = true; + zsh.enable = lib.mkDefault true; + }; + + fileSystems."/boot".options = [ "umask=0077" ]; + + networking.networkmanager.enable = true; + + +} diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100644 index 0000000..7a82b53 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,115 @@ +# highly inspired by https://github.com/EmergentMind/nix-config/blob/dev/scripts/bootstrap-nixos.sh +set -eo pipefail + +target_hostname="" +target_destination="" +target_user="swarsel" +ssh_port="22" +temp=$(mktemp -d) + +function help_and_exit() { + echo + echo "Remotely installs NixOS on a target machine using this nix-config." + echo + echo "USAGE: $0 -n -d [OPTIONS]" + echo + echo "ARGS:" + echo " -n specify target_hostname of the target host to deploy the nixos config on." + echo " -d specify ip or url to the target host." + echo " target during install process." + echo + echo "OPTIONS:" + echo " -u specify target_user with sudo access. nix-config will be cloned to their home." + echo " Default='${target_user}'." + echo " --port specify the ssh port to use for remote access. Default=${ssh_port}." + echo " --impermanence Use this flag if the target machine has impermanence enabled. WARNING: Assumes /persist path." + echo " --debug Enable debug mode." + echo " -h | --help Print this help." + exit 0 +} + +function cleanup() { + rm -rf "$temp" +} +trap cleanup exit + +function red() { + echo -e "\x1B[31m[!] $1 \x1B[0m" + if [ -n "${2-}" ]; then + echo -e "\x1B[31m[!] $($2) \x1B[0m" + fi +} +function green() { + echo -e "\x1B[32m[+] $1 \x1B[0m" + if [ -n "${2-}" ]; then + echo -e "\x1B[32m[+] $($2) \x1B[0m" + fi +} +function yellow() { + echo -e "\x1B[33m[*] $1 \x1B[0m" + if [ -n "${2-}" ]; then + echo -e "\x1B[33m[*] $($2) \x1B[0m" + fi +} + +function yes_or_no() { + echo -en "\x1B[32m[+] $* [y/n] (default: y): \x1B[0m" + while true; do + read -rp "" yn + yn=${yn:-y} + case $yn in + [Yy]*) return 0 ;; + [Nn]*) return 1 ;; + esac + done +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -n) + shift + target_hostname=$1 + ;; + -d) + shift + target_destination=$1 + ;; + -u) + shift + target_user=$1 + ;; + --port) + shift + ssh_port=$1 + ;; + --temp-override) + shift + temp=$1 + ;; + --debug) + set -x + ;; + -h | --help) help_and_exit ;; + *) + echo "Invalid option detected." + help_and_exit + ;; + esac + shift +done + +ssh_cmd="ssh -oport=${ssh_port} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -t $target_user@$target_destination" +# ssh_root_cmd=$(echo "$ssh_cmd" | sed "s|${target_user}@|root@|") # uses @ in the sed switch to avoid it triggering on the $ssh_key value +ssh_root_cmd=${ssh_cmd/${target_user}@/root@} + +scp_cmd="scp -oport=${ssh_port} -o StrictHostKeyChecking=no" + +git_root=$(git rev-parse --show-toplevel) + +green "Wiping known_hosts of $target_destination" +sed -i "/$target_hostname/d; /$target_destination/d" ~/.ssh/known_hosts + +green "Generating hardware-config.nix for $target_hostname and adding it to the nix-config." +$ssh_root_cmd "nixos-generate-config --no-filesystems --root /mnt" +mkdir profiles/"$target_hostname" +$scp_cmd root@"$target_destination":/mnt/etc/nixos/hardware-configuration.nix "${git_root}"/profiles/"$target_hostname"/hardware-configuration.nix