From e6dff14d733f83b81eeb5becaf5103d48fb38007 Mon Sep 17 00:00:00 2001 From: Niklas Gollenstede Date: Fri, 1 Sep 2023 17:01:13 +0200 Subject: [PATCH] remove nofail mount option, import/export things --- README.md | 2 +- flake.nix | 2 +- lib/nixos.nix | 6 +++-- lib/setup-scripts/maintenance.sh | 2 +- modules/README.md | 43 -------------------------------- modules/filesystem.nix.md | 6 +++-- modules/setup/keystore.nix.md | 2 +- modules/setup/temproot.nix.md | 4 +-- 8 files changed, 14 insertions(+), 53 deletions(-) delete mode 100644 modules/README.md diff --git a/README.md b/README.md index 0202888..7f9f61e 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ nix run .'#'hostname -- --help ``` [`config.installer.commands.*`](./modules/installer.nix.md) can be used to run host-specific commands at various points of the installation, and additional `config.installer.scripts` can [add or replace](./lib/setup-scripts/README.md) new and existing setup commands or functions. - +This mechanism has been used to, for example, [automatically deploy](https://github.com/NiklasGollenstede/nix-wiplib/blob/master/modules/hardware/hetzner-vps.nix.md#installation--testing) locally built system images tp Hetzner VPSes. ## Repo Layout/Contents diff --git a/flake.nix b/flake.nix index 518f28f..ce8928f 100644 --- a/flake.nix +++ b/flake.nix @@ -21,7 +21,7 @@ in [ # Run »nix flake show --allow-import-from-derivation« to see what this me (lib.self.mkSystemsFlake { inherit inputs; buildPlatform = "aarch64-linux"; renameOutputs = name: "arm:${name}"; }) # nixosConfigurations.arm:* apps.*-linux.arm:* devShells.*-linux.arm:* packages.*-linux.arm:all-systems # Any packages touched by the ./overlays/: (lib.fun.forEachSystem [ "aarch64-linux" "x86_64-linux" ] (localSystem: let # packages.*-linux.* - packages = lib.fun.getModifiedPackages (lib.fun.importPkgs inputs { system = localSystem; }) overlays; + packages = builtins.removeAttrs (lib.fun.getModifiedPackages (lib.fun.importPkgs inputs { system = localSystem; }) overlays) [ "libblockdev" ]; in { packages = packages // { default = self.packages.${localSystem}.all-systems; }; })) ]); } diff --git a/lib/nixos.nix b/lib/nixos.nix index bb5105f..d9f8367 100644 --- a/lib/nixos.nix +++ b/lib/nixos.nix @@ -117,6 +117,8 @@ in rec { nixosSystem ? inputs.nixpkgs.lib.nixosSystem, # If provided, this will be set as »config.nixpkgs.buildPlatform« for all hosts, which in turn enables cross-compilation for all hosts whose »config.nixpkgs.hostPlatform« (the architecture they will run on) does not expand to the same value. Without this, building for other platforms may still work (slowly) if »boot.binfmt.emulatedSystems« on the building system is configured for the respective target(s). buildPlatform ? null, + ## The platforms for which the setup scripts (installation & maintenance/debugging) will be defined. SHould include the ».buildPlatform« and/or the target system's »config.nixpkgs.hostPlatform«. + setupPlatforms ? if inputs?systems then import inputs.systems else [ "aarch64-linux" "x86_64-linux" ], ## If provided, then change the name of each output attribute by passing it through this function. Allows exporting of multiple variants of a repo's hosts from a single flake (by then merging the results): renameOutputs ? false, ... }: let @@ -130,7 +132,7 @@ in rec { nixosConfigurations = if builtins.isList systems then mergeAttrsUnique (map (systems: mkNixosConfigurations (otherArgs // systems)) systems) else mkNixosConfigurations (otherArgs // systems); in let outputs = { inherit nixosConfigurations; - } // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (buildSystem: let + } // (forEachSystem setupPlatforms (buildSystem: let pkgs = (import inputs.nixpkgs { inherit overlays; system = buildSystem; }); tools = lib.unique (map (p: p.outPath) (lib.filter lib.isDerivation pkgs.stdenv.allowedRequisites)); in rec { @@ -156,7 +158,7 @@ in rec { })); in if renameOutputs == false then outputs else { nixosConfigurations = mapMergeUnique (k: v: { ${renameOutputs k} = v; }) outputs.nixosConfigurations; - } // (forEachSystem [ "aarch64-linux" "x86_64-linux" ] (buildSystem: { + } // (forEachSystem setupPlatforms (buildSystem: { apps = mapMergeUnique (k: v: { ${renameOutputs k} = v; }) outputs.apps.${buildSystem}; packages.${renameOutputs "all-systems"} = outputs.packages.${buildSystem}.all-systems; checks.${renameOutputs "all-systems"} = outputs.checks.${buildSystem}.all-systems; diff --git a/lib/setup-scripts/maintenance.sh b/lib/setup-scripts/maintenance.sh index 430e926..28ef5ff 100644 --- a/lib/setup-scripts/maintenance.sh +++ b/lib/setup-scripts/maintenance.sh @@ -148,7 +148,7 @@ function run-qemu { fi # TODO: network bridging: - #[[ @{config.networking.hostId} =~ ^(.)(.)(.)(.)(.)(.)(.)(.)$ ]] ; mac=$( printf "52:54:%s%s:%s%s:%s%s:%s%s" "${BASH_REMATCH[@]:1}" ) + #[[ @{config.networking.hostId} =~ ^(.)(.)(.)(.)(.)(.)(.)(.)$ ]] && mac=$( printf "52:54:%s%s:%s%s:%s%s:%s%s" "${BASH_REMATCH[@]:1}" ) || { echo 'Invalid hostId' &>2 ; return; } #qemu+=( -netdev bridge,id=enp0s3,macaddr=$mac -device virtio-net-pci,netdev=hn0,id=nic1 ) # To pass a USB device (e.g. a YubiKey for unlocking), add pass »--usb-port=${bus}-${port}«, where bus and port refer to the physical USB port »/sys/bus/usb/devices/${bus}-${port}« (see »lsusb -tvv«). E.g.: »--usb-port=3-1.1.1.4« diff --git a/modules/README.md b/modules/README.md deleted file mode 100644 index 15cd187..0000000 --- a/modules/README.md +++ /dev/null @@ -1,43 +0,0 @@ - -# NixOS Modules - -A NixOS module is a collection of any number of NixOS option definitions and value assignments to those or other options. -While the set of imported modules, and thereby that of the defined options, is static (in this case starting with the modules passed to `mkNixosSystem` in `../flake.nix`), the value assignments can generally be contingent on other values (as long as there are no logical loops), making for highly flexible system constructions. -Since modules can't be imported (or excluded) dynamically, most modules have an `enable` option, which, if false, effectively disables whatever that module does. - -Ultimately, the goal of a NixOS configuration is to build an operating system, which is basically a structured collection of program and configuration files. -To that end, there are a number of pre-defined options (in `nixpkgs`) that collect programs, create and write configuration files (primarily in `/etc`), compose a boot loader, etc. -Other modules use those options to manipulate how the system is built. - - -## Template - -Here is a skeleton structure for writing a new `.nix.md`: - -````md -/* - -# TODO: title - -TODO: documentation - -## Implementation - -```nix -#*/# end of MarkDown, beginning of NixOS module: -dirname: inputs: { config, pkgs, lib, ... }: let lib = inputs.self.lib.__internal__; in let - prefix = inputs.config.prefix; - cfg = config.${prefix}.${TODO: name}; -in { - - options.${prefix} = { ${TODO: name} = { - enable = lib.mkEnableOption "TODO: what"; - # TODO: more options - }; }; - - config = lib.mkIf cfg.enable (lib.mkMerge [ ({ - # TODO: implementation - }) ]); - -} -```` diff --git a/modules/filesystem.nix.md b/modules/filesystem.nix.md index b53f88c..33e764a 100644 --- a/modules/filesystem.nix.md +++ b/modules/filesystem.nix.md @@ -16,11 +16,13 @@ in { options = { fileSystems = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule [ { options = { ${preMountCommands} = lib.mkOption { description = '' - Commands to be run as root every time before mounting this filesystem, but after all its dependents were mounted (TODO: or does this run just once per boot?). + Commands to be run as root every time before mounting this filesystem **via systemd**, but after all its dependents were mounted. This does not order itself before or after `systemd-fsck@''${utils.escapeSystemdPath device}.service`. This is not implemented for mounts in the initrd (those that are `neededForBoot`) yet. - Note that if a symlink exists at a mount point when systemd's fstab-generator runs, it will read/resolve the symlink and use that as the mount point, resulting in mismatching unit names for that mount, effectively disabling its `${preMountCommands}`. + Note that if a symlink exists at a mount point when systemd's fstab-generator runs, it will read/resolve the symlink and use the link's target as the mount point, resulting in mismatching unit names for that mount, effectively disabling its `.${preMountCommands}`. + This does not (apparently and unfortunately) run when mounting via the `mount` command (and probably not with the `mount` system call either). ''; type = lib.types.lines; default = ""; }; + #Also, trying to create the "device" of a "nofail" mount will not work with `mount`, as it will not even attempt to mount anything (and thus not run the `.${preMountCommands}`) if the "device" is missing. }; } ]); }; }; diff --git a/modules/setup/keystore.nix.md b/modules/setup/keystore.nix.md index 23f5ac7..650c877 100644 --- a/modules/setup/keystore.nix.md +++ b/modules/setup/keystore.nix.md @@ -18,7 +18,7 @@ The attribute value in the `.keys` keys specification dictates how the key is ac The format of the key specification is `method[=args]`, where `method` is the suffix of a bash function call `gen-key-` (the default functions are in [`add-key.sh`](../../lib/setup-scripts/add-key.sh), but others could be added to the installer), and `args` is the second argument to the respective function (often a `:` separated list of arguments, but some methods don't need any arguments at all). Most key generation methods only make sense in some key usage contexts. A `random` key is impossible to provide to unlock the keystore (which it is stored in), but is well suited to unlock other devices (if the keystore has backups); conversely a USB-partition can be used to headlessly unlock the keystore, but would be redundant for any further devices, as it would also be copied into the keystore. -If the module is `enable`d, a partition and LUKS device `keystore-...` gets configured and the contents of the installation time keystore is copied to it (in its entirety, including intermediate or derived keys and those unlocking the keystore itself (TODO: this could be optimized)). +If the module is `enable`d, a partition and LUKS device `keystore-...` gets configured and the contents of the installation time keystore is copied to it (in its entirety, including intermediate or derived keys and those unlocking the keystore itself). This LUKS device is then configured to be unlocked (using any of the key methods specified for it -- by default, key slot 0 is set to the `hostname`) before anything else during boot, and closed before leaving the initramfs phase. Any number of other devices may thus specify paths in the keystore as keylocation to be unlocked during boot without needing to prompt for further secrets, and without exposing the keys to the running system. diff --git a/modules/setup/temproot.nix.md b/modules/setup/temproot.nix.md index 612431f..8c8d8d6 100644 --- a/modules/setup/temproot.nix.md +++ b/modules/setup/temproot.nix.md @@ -229,9 +229,9 @@ in { fileSystems = { # this does get applied early # (on systems without hardware clock, this allows systemd to provide an at least monolithic time after restarts) - "/var/lib/systemd/timesync" = { device = "/local/var/lib/systemd/timesync"; options = [ "bind" "nofail" ]; }; # TODO: add »neededForBoot = true«? + "/var/lib/systemd/timesync" = { device = "/local/var/lib/systemd/timesync"; options = [ "bind" ]; }; # TODO: add »neededForBoot = true«? # save persistent timer states - "/var/lib/systemd/timers" = { device = "/local/var/lib/systemd/timers"; options = [ "bind" "nofail" ]; }; # TODO: add »neededForBoot = true«? + "/var/lib/systemd/timers" = { device = "/local/var/lib/systemd/timers"; options = [ "bind" ]; }; # TODO: add »neededForBoot = true«? }; security.sudo.extraConfig = "Defaults lecture=never"; # default is »once«, but we'd forget that we did that