diff options
Diffstat (limited to 'nixos')
26 files changed, 551 insertions, 441 deletions
diff --git a/nixos/doc/manual/development/option-types.section.md b/nixos/doc/manual/development/option-types.section.md index 9e2ecb8e35626..9e156ebff9d3e 100644 --- a/nixos/doc/manual/development/option-types.section.md +++ b/nixos/doc/manual/development/option-types.section.md @@ -99,6 +99,10 @@ merging is handled. problems. ::: +`types.pkgs` + +: A type for the top level Nixpkgs package set. + ### Numeric types {#sec-option-types-numeric} `types.int` diff --git a/nixos/doc/manual/release-notes/rl-2305.section.md b/nixos/doc/manual/release-notes/rl-2305.section.md index 6949edf2d1128..2d37362412824 100644 --- a/nixos/doc/manual/release-notes/rl-2305.section.md +++ b/nixos/doc/manual/release-notes/rl-2305.section.md @@ -114,6 +114,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [stargazer](https://sr.ht/~zethra/stargazer/), a fast and easy to use Gemini server. Available as [services.stargazer](#opt-services.stargazer.enable). +- [sniffnet](https://github.com/GyulyVGC/sniffnet), an application to monitor your network traffic. Available as [programs.sniffnet](#opt-programs.sniffnet.enable). + - [photoprism](https://photoprism.app/), a AI-Powered Photos App for the Decentralized Web. Available as [services.photoprism](options.html#opt-services.photoprism.enable). - [peroxide](https://github.com/ljanyst/peroxide), a fork of the official [ProtonMail bridge](https://github.com/ProtonMail/proton-bridge) that aims to be similar to [Hydroxide](https://github.com/emersion/hydroxide). Available as [services.peroxide](#opt-services.peroxide.enable). diff --git a/nixos/lib/eval-config.nix b/nixos/lib/eval-config.nix index 1e086271e5236..058ab7280ccc3 100644 --- a/nixos/lib/eval-config.nix +++ b/nixos/lib/eval-config.nix @@ -38,6 +38,8 @@ let pkgs_ = pkgs; in let + inherit (lib) optional; + evalModulesMinimal = (import ./default.nix { inherit lib; # Implicit use of feature is noted in implementation. @@ -47,15 +49,19 @@ let pkgsModule = rec { _file = ./eval-config.nix; key = _file; - config = { - # Explicit `nixpkgs.system` or `nixpkgs.localSystem` should override - # this. Since the latter defaults to the former, the former should - # default to the argument. That way this new default could propagate all - # they way through, but has the last priority behind everything else. - nixpkgs.system = lib.mkIf (system != null) (lib.mkDefault system); - - _module.args.pkgs = lib.mkIf (pkgs_ != null) (lib.mkForce pkgs_); - }; + config = lib.mkMerge ( + (optional (system != null) { + # Explicit `nixpkgs.system` or `nixpkgs.localSystem` should override + # this. Since the latter defaults to the former, the former should + # default to the argument. That way this new default could propagate all + # they way through, but has the last priority behind everything else. + nixpkgs.system = lib.mkDefault system; + }) + ++ + (optional (pkgs_ != null) { + _module.args.pkgs = lib.mkForce pkgs_; + }) + ); }; withWarnings = x: diff --git a/nixos/lib/testing/nodes.nix b/nixos/lib/testing/nodes.nix index c538ab468c526..6e439fd814db7 100644 --- a/nixos/lib/testing/nodes.nix +++ b/nixos/lib/testing/nodes.nix @@ -1,13 +1,22 @@ testModuleArgs@{ config, lib, hostPkgs, nodes, ... }: let - inherit (lib) mkOption mkForce optional types mapAttrs mkDefault mdDoc; - - system = hostPkgs.stdenv.hostPlatform.system; + inherit (lib) + literalExpression + literalMD + mapAttrs + mdDoc + mkDefault + mkIf + mkOption mkForce + optional + optionalAttrs + types + ; baseOS = import ../eval-config.nix { - inherit system; + system = null; # use modularly defined system inherit (config.node) specialArgs; modules = [ config.defaults ]; baseModules = (import ../../modules/module-list.nix) ++ @@ -17,11 +26,17 @@ let ({ config, ... }: { virtualisation.qemu.package = testModuleArgs.config.qemu.package; - + }) + (optionalAttrs (!config.node.pkgsReadOnly) { + key = "nodes.nix-pkgs"; + config = { # Ensure we do not use aliases. Ideally this is only set # when the test framework is used by Nixpkgs NixOS tests. nixpkgs.config.allowAliases = false; - }) + # TODO: switch to nixpkgs.hostPlatform and make sure containers-imperative test still evaluates. + nixpkgs.system = hostPkgs.stdenv.hostPlatform.system; + }; + }) testModuleArgs.config.extraBaseModules ]; }; @@ -68,6 +83,30 @@ in default = { }; }; + node.pkgs = mkOption { + description = mdDoc '' + The Nixpkgs to use for the nodes. + + Setting this will make the `nixpkgs.*` options read-only, to avoid mistakenly testing with a Nixpkgs configuration that diverges from regular use. + ''; + type = types.nullOr types.pkgs; + default = null; + defaultText = literalMD '' + `null`, so construct `pkgs` according to the `nixpkgs.*` options as usual. + ''; + }; + + node.pkgsReadOnly = mkOption { + description = mdDoc '' + Whether to make the `nixpkgs.*` options read-only. This is only relevant when [`node.pkgs`](#test-opt-node.pkgs) is set. + + Set this to `false` when any of the [`nodes`](#test-opt-nodes) needs to configure any of the `nixpkgs.*` options. This will slow down evaluation of your test a bit. + ''; + type = types.bool; + default = config.node.pkgs != null; + defaultText = literalExpression ''node.pkgs != null''; + }; + node.specialArgs = mkOption { type = types.lazyAttrsOf types.raw; default = { }; @@ -100,5 +139,11 @@ in config.nodes; passthru.nodes = config.nodesCompat; + + defaults = mkIf config.node.pkgsReadOnly { + nixpkgs.pkgs = config.node.pkgs; + imports = [ ../../modules/misc/nixpkgs/read-only.nix ]; + }; + }; } diff --git a/nixos/modules/config/gnu.nix b/nixos/modules/config/gnu.nix index d06b479e2af53..a47d299b226b5 100644 --- a/nixos/modules/config/gnu.nix +++ b/nixos/modules/config/gnu.nix @@ -29,7 +29,6 @@ # GNU GRUB, where available. boot.loader.grub.enable = !pkgs.stdenv.isAarch32; - boot.loader.grub.version = 2; # GNU lsh. services.openssh.enable = false; diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 3921bb61b91c3..e22bb866927ba 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -694,8 +694,6 @@ in } ]; - boot.loader.grub.version = 2; - # Don't build the GRUB menu builder script, since we don't need it # here and it causes a cyclic dependency. boot.loader.grub.enable = false; diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index c65898b261cb0..5d3d0216d20c9 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -651,7 +651,6 @@ EOF $bootLoaderConfig = <<EOF; # Use the GRUB 2 boot loader. boot.loader.grub.enable = true; - boot.loader.grub.version = 2; # boot.loader.grub.efiSupport = true; # boot.loader.grub.efiInstallAsRemovable = true; # boot.loader.efi.efiSysMountPoint = "/boot/efi"; diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix index 7f44c3f6f3f0e..55ec08acf4453 100644 --- a/nixos/modules/misc/nixpkgs.nix +++ b/nixos/modules/misc/nixpkgs.nix @@ -49,10 +49,10 @@ let merge = lib.mergeOneOption; }; - pkgsType = mkOptionType { - name = "nixpkgs"; + pkgsType = types.pkgs // { + # This type is only used by itself, so let's elaborate the description a bit + # for the purpose of documentation. description = "An evaluation of Nixpkgs; the top level attribute set of packages"; - check = builtins.isAttrs; }; # Whether `pkgs` was constructed by this module - not if nixpkgs.pkgs or diff --git a/nixos/modules/misc/nixpkgs/read-only.nix b/nixos/modules/misc/nixpkgs/read-only.nix new file mode 100644 index 0000000000000..2a783216a9d54 --- /dev/null +++ b/nixos/modules/misc/nixpkgs/read-only.nix @@ -0,0 +1,74 @@ +# A replacement for the traditional nixpkgs module, such that none of the modules +# can add their own configuration. This ensures that the Nixpkgs configuration is +# exactly as the user intends. +# This may also be used as a performance optimization when evaluating multiple +# configurations at once, with a shared `pkgs`. + +# This is a separate module, because merging this logic into the nixpkgs module +# is too burdensome, considering that it is already burdened with legacy. +# Moving this logic into a module does not lose any composition benefits, because +# its purpose is not something that composes anyway. + +{ lib, config, ... }: + +let + cfg = config.nixpkgs; + inherit (lib) mkOption types; + +in +{ + disabledModules = [ + ../nixpkgs.nix + ]; + options = { + nixpkgs = { + pkgs = mkOption { + type = lib.types.pkgs; + description = lib.mdDoc ''The pkgs module argument.''; + }; + config = mkOption { + internal = true; + type = types.unique { message = "nixpkgs.config is set to read-only"; } types.anything; + description = lib.mdDoc '' + The Nixpkgs `config` that `pkgs` was initialized with. + ''; + }; + overlays = mkOption { + internal = true; + type = types.unique { message = "nixpkgs.overlays is set to read-only"; } types.anything; + description = lib.mdDoc '' + The Nixpkgs overlays that `pkgs` was initialized with. + ''; + }; + hostPlatform = mkOption { + internal = true; + readOnly = true; + description = lib.mdDoc '' + The platform of the machine that is running the NixOS configuration. + ''; + }; + buildPlatform = mkOption { + internal = true; + readOnly = true; + description = lib.mdDoc '' + The platform of the machine that built the NixOS configuration. + ''; + }; + # NOTE: do not add the legacy options such as localSystem here. Let's keep + # this module simple and let module authors upgrade their code instead. + }; + }; + config = { + _module.args.pkgs = + # find mistaken definitions + builtins.seq cfg.config + builtins.seq cfg.overlays + builtins.seq cfg.hostPlatform + builtins.seq cfg.buildPlatform + cfg.pkgs; + nixpkgs.config = cfg.pkgs.config; + nixpkgs.overlays = cfg.pkgs.overlays; + nixpkgs.hostPlatform = cfg.pkgs.stdenv.hostPlatform; + nixpkgs.buildPlatform = cfg.pkgs.stdenv.buildPlatform; + }; +} diff --git a/nixos/modules/misc/nixpkgs/test.nix b/nixos/modules/misc/nixpkgs/test.nix index a6d8877ae0700..0536cfc9624a2 100644 --- a/nixos/modules/misc/nixpkgs/test.nix +++ b/nixos/modules/misc/nixpkgs/test.nix @@ -1,3 +1,5 @@ +# [nixpkgs]$ nix-build -A nixosTests.nixpkgs --show-trace + { evalMinimalConfig, pkgs, lib, stdenv }: let eval = mod: evalMinimalConfig { @@ -27,6 +29,47 @@ let let uncheckedEval = lib.evalModules { modules = [ ../nixpkgs.nix module ]; }; in map (ass: ass.message) (lib.filter (ass: !ass.assertion) uncheckedEval.config.assertions); + + readOnlyUndefined = evalMinimalConfig { + imports = [ ./read-only.nix ]; + }; + + readOnlyBad = evalMinimalConfig { + imports = [ ./read-only.nix ]; + nixpkgs.pkgs = { }; + }; + + readOnly = evalMinimalConfig { + imports = [ ./read-only.nix ]; + nixpkgs.pkgs = pkgs; + }; + + readOnlyBadConfig = evalMinimalConfig { + imports = [ ./read-only.nix ]; + nixpkgs.pkgs = pkgs; + nixpkgs.config.allowUnfree = true; # do in pkgs instead! + }; + + readOnlyBadOverlays = evalMinimalConfig { + imports = [ ./read-only.nix ]; + nixpkgs.pkgs = pkgs; + nixpkgs.overlays = [ (_: _: {}) ]; # do in pkgs instead! + }; + + readOnlyBadHostPlatform = evalMinimalConfig { + imports = [ ./read-only.nix ]; + nixpkgs.pkgs = pkgs; + nixpkgs.hostPlatform = "foo-linux"; # do in pkgs instead! + }; + + readOnlyBadBuildPlatform = evalMinimalConfig { + imports = [ ./read-only.nix ]; + nixpkgs.pkgs = pkgs; + nixpkgs.buildPlatform = "foo-linux"; # do in pkgs instead! + }; + + throws = x: ! (builtins.tryEval x).success; + in lib.recurseIntoAttrs { invokeNixpkgsSimple = @@ -65,5 +108,21 @@ lib.recurseIntoAttrs { nixpkgs.pkgs = pkgs; } == []; + + # Tests for the read-only.nix module + assert readOnly._module.args.pkgs.stdenv.hostPlatform.system == pkgs.stdenv.hostPlatform.system; + assert throws readOnlyBad._module.args.pkgs.stdenv; + assert throws readOnlyUndefined._module.args.pkgs.stdenv; + assert throws readOnlyBadConfig._module.args.pkgs.stdenv; + assert throws readOnlyBadOverlays._module.args.pkgs.stdenv; + assert throws readOnlyBadHostPlatform._module.args.pkgs.stdenv; + assert throws readOnlyBadBuildPlatform._module.args.pkgs.stdenv; + # read-only.nix does not provide legacy options, for the sake of simplicity + # If you're bothered by this, upgrade your configs to use the new *Platform + # options. + assert !readOnly.options.nixpkgs?system; + assert !readOnly.options.nixpkgs?localSystem; + assert !readOnly.options.nixpkgs?crossSystem; + pkgs.emptyFile; } diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4e0a44c409232..0b0634884c718 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -235,6 +235,7 @@ ./programs/singularity.nix ./programs/skim.nix ./programs/slock.nix + ./programs/sniffnet.nix ./programs/spacefm.nix ./programs/ssh.nix ./programs/starship.nix diff --git a/nixos/modules/programs/sniffnet.nix b/nixos/modules/programs/sniffnet.nix new file mode 100644 index 0000000000000..98e9f628a9bce --- /dev/null +++ b/nixos/modules/programs/sniffnet.nix @@ -0,0 +1,24 @@ +{ config, lib, pkgs, ... }: + +let + cfg = config.programs.sniffnet; +in + +{ + options = { + programs.sniffnet = { + enable = lib.mkEnableOption (lib.mdDoc "sniffnet"); + }; + }; + + config = lib.mkIf cfg.enable { + security.wrappers.sniffnet = { + owner = "root"; + group = "root"; + capabilities = "cap_net_raw,cap_net_admin=eip"; + source = "${pkgs.sniffnet}/bin/sniffnet"; + }; + }; + + meta.maintainers = with lib.maintainers; [ figsoda ]; +} diff --git a/nixos/modules/services/backup/automysqlbackup.nix b/nixos/modules/services/backup/automysqlbackup.nix index d0237f196a807..27bbff813b105 100644 --- a/nixos/modules/services/backup/automysqlbackup.nix +++ b/nixos/modules/services/backup/automysqlbackup.nix @@ -3,7 +3,7 @@ let inherit (lib) concatMapStringsSep concatStringsSep isInt isList literalExpression; - inherit (lib) mapAttrs mapAttrsToList mkDefault mkEnableOption mkIf mkOption optional types; + inherit (lib) mapAttrs mapAttrsToList mkDefault mkEnableOption mkIf mkOption mkRenamedOptionModule optional types; cfg = config.services.automysqlbackup; pkg = pkgs.automysqlbackup; @@ -26,6 +26,10 @@ let in { + imports = [ + (mkRenamedOptionModule [ "services" "automysqlbackup" "config" ] [ "services" "automysqlbackup" "settings" ]) + ]; + # interface options = { services.automysqlbackup = { @@ -40,7 +44,7 @@ in ''; }; - config = mkOption { + settings = mkOption { type = with types; attrsOf (oneOf [ str int bool (listOf str) ]); default = {}; description = lib.mdDoc '' @@ -112,7 +116,18 @@ in services.mysql.ensureUsers = optional (config.services.mysql.enable && cfg.config.mysql_dump_host == "localhost") { name = user; - ensurePermissions = { "*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT"; }; + ensurePermissions = { + "*.*" = "SELECT, SHOW VIEW, TRIGGER, LOCK TABLES, EVENT"; + + # https://forums.mysql.com/read.php?10,668311,668315#msg-668315 + "function sys.extract_table_from_file_name" = "execute"; + "function sys.format_path" = "execute"; + "function sys.format_statement" = "execute"; + "function sys.extract_schema_from_file_name" = "execute"; + "function sys.ps_thread_account" = "execute"; + "function sys.format_time" = "execute"; + "function sys.format_bytes" = "execute"; + }; }; }; diff --git a/nixos/modules/services/networking/harmonia.nix b/nixos/modules/services/networking/harmonia.nix index 0f9d328d0059b..144fa6c708e28 100644 --- a/nixos/modules/services/networking/harmonia.nix +++ b/nixos/modules/services/networking/harmonia.nix @@ -1,7 +1,6 @@ { config, pkgs, lib, ... }: let cfg = config.services.harmonia; - format = pkgs.formats.toml { }; in { @@ -12,21 +11,23 @@ in signKeyPath = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; - description = lib.mdDoc "Path to the signing key to use for signing the cache"; + description = lib.mdDoc "Path to the signing key that will be used for signing the cache"; }; package = lib.mkPackageOptionMD pkgs "harmonia" { }; settings = lib.mkOption { inherit (format) type; - description = lib.mdDoc "Settings to merge with the default configuration"; + default = { }; + description = lib.mdDoc '' + Settings to merge with the default configuration. + For the list of the default configuration, see <https://github.com/nix-community/harmonia/tree/master#configuration>. + ''; }; }; }; config = lib.mkIf cfg.enable { - services.harmonia.settings.bind = lib.mkDefault "[::]:5000"; - systemd.services.harmonia = { description = "harmonia binary cache service"; @@ -45,17 +46,14 @@ in serviceConfig = { ExecStart = lib.getExe cfg.package; - User = "harmonia"; Group = "harmonia"; DynamicUser = true; PrivateUsers = true; DeviceAllow = [ "" ]; UMask = "0066"; - RuntimeDirectory = "harmonia"; - LoadCredential = lib.optional (cfg.signKeyPath != null) "sign-key:${cfg.signKeyPath}"; - + LoadCredential = lib.mkIf (cfg.signKeyPath != null) [ "sign-key:${cfg.signKeyPath}" ]; SystemCallFilter = [ "@system-service" "~@privileged" @@ -74,7 +72,6 @@ in ProtectProc = "invisible"; RestrictNamespaces = true; SystemCallArchitectures = "native"; - PrivateNetwork = false; PrivateTmp = true; PrivateDevices = true; @@ -84,7 +81,6 @@ in ProtectHome = true; LockPersonality = true; RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; - LimitNOFILE = 65536; }; }; diff --git a/nixos/modules/services/networking/ssh/sshd.nix b/nixos/modules/services/networking/ssh/sshd.nix index 89ddf82152993..fd9650a058c2f 100644 --- a/nixos/modules/services/networking/ssh/sshd.nix +++ b/nixos/modules/services/networking/ssh/sshd.nix @@ -365,9 +365,6 @@ in "hmac-sha2-512-etm@openssh.com" "hmac-sha2-256-etm@openssh.com" "umac-128-etm@openssh.com" - "hmac-sha2-512" - "hmac-sha2-256" - "umac-128@openssh.com" ]; description = lib.mdDoc '' Allowed MACs diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix index 5c0a07fb51272..9f80b40d116c6 100644 --- a/nixos/modules/system/boot/loader/grub/grub.nix +++ b/nixos/modules/system/boot/loader/grub/grub.nix @@ -1,4 +1,4 @@ -{ config, lib, pkgs, ... }: +{ config, options, lib, pkgs, ... }: with lib; @@ -12,13 +12,8 @@ let # Package set of targeted architecture if cfg.forcei686 then pkgs.pkgsi686Linux else pkgs; - realGrub = if cfg.version == 1 then grubPkgs.grub - else if cfg.zfsSupport then grubPkgs.grub2.override { zfsSupport = true; } - else if cfg.trustedBoot.enable - then if cfg.trustedBoot.isHPLaptop - then grubPkgs.trustedGrub-for-HP - else grubPkgs.trustedGrub - else grubPkgs.grub2; + realGrub = if cfg.zfsSupport then grubPkgs.grub2.override { zfsSupport = true; } + else grubPkgs.grub2; grub = # Don't include GRUB if we're only generating a GRUB menu (e.g., @@ -28,8 +23,7 @@ let else realGrub; grubEfi = - # EFI version of Grub v2 - if cfg.efiSupport && (cfg.version == 2) + if cfg.efiSupport then realGrub.override { efiSupport = cfg.efiSupport; } else null; @@ -52,24 +46,24 @@ let fullName = lib.getName realGrub; fullVersion = lib.getVersion realGrub; grubEfi = f grubEfi; - grubTargetEfi = optionalString (cfg.efiSupport && (cfg.version == 2)) (f (grubEfi.grubTarget or "")); + grubTargetEfi = optionalString cfg.efiSupport (f (grubEfi.grubTarget or "")); bootPath = args.path; storePath = config.boot.loader.grub.storePath; bootloaderId = if args.efiBootloaderId == null then "${config.system.nixos.distroName}${efiSysMountPoint'}" else args.efiBootloaderId; timeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout; - users = if cfg.users == {} || cfg.version != 1 then cfg.users else throw "GRUB version 1 does not support user accounts."; theme = f cfg.theme; inherit efiSysMountPoint; inherit (args) devices; inherit (efi) canTouchEfiVariables; inherit (cfg) - version extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber + extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber extraGrubInstallArgs extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels - default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios; + default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios + users; path = with pkgs; makeBinPath ( [ coreutils gnused gnugrep findutils diffutils btrfs-progs util-linux mdadm ] - ++ optional (cfg.efiSupport && (cfg.version == 2)) efibootmgr + ++ optional cfg.efiSupport efibootmgr ++ optionals cfg.useOSProber [ busybox os-prober ]); font = if cfg.font == null then "" else (if lib.last (lib.splitString "." cfg.font) == "pf2" @@ -109,14 +103,8 @@ in }; version = mkOption { - default = 2; - example = 1; + visible = false; type = types.int; - description = lib.mdDoc '' - The version of GRUB to use: `1` for GRUB - Legacy (versions 0.9x), or `2` (the - default) for GRUB 2. - ''; }; device = mkOption { @@ -682,39 +670,6 @@ in ''; }; - trustedBoot = { - - enable = mkOption { - default = false; - type = types.bool; - description = lib.mdDoc '' - Enable trusted boot. GRUB will measure all critical components during - the boot process to offer TCG (TPM) support. - ''; - }; - - systemHasTPM = mkOption { - default = ""; - example = "YES_TPM_is_activated"; - type = types.str; - description = lib.mdDoc '' - Assertion that the target system has an activated TPM. It is a safety - check before allowing the activation of 'trustedBoot.enable'. TrustedBoot - WILL FAIL TO BOOT YOUR SYSTEM if no TPM is available. - ''; - }; - - isHPLaptop = mkOption { - default = false; - type = types.bool; - description = lib.mdDoc '' - Use a special version of TrustedGRUB that is needed by some HP laptops - and works only for the HP laptops. - ''; - }; - - }; - }; }; @@ -724,14 +679,7 @@ in config = mkMerge [ - { boot.loader.grub.splashImage = mkDefault ( - if cfg.version == 1 then pkgs.fetchurl { - url = "http://www.gnome-look.org/CONTENT/content-files/36909-soft-tux.xpm.gz"; - sha256 = "14kqdx2lfqvh40h6fjjzqgff1mwk74dmbjvmqphi6azzra7z8d59"; - } - # GRUB 1.97 doesn't support gzipped XPMs. - else defaultSplash); - } + { boot.loader.grub.splashImage = mkDefault defaultSplash; } (mkIf (cfg.splashImage == defaultSplash) { boot.loader.grub.backgroundColor = mkDefault "#2F302F"; @@ -789,10 +737,6 @@ in assertions = [ { - assertion = !cfg.zfsSupport || cfg.version == 2; - message = "Only GRUB version 2 provides ZFS support"; - } - { assertion = cfg.mirroredBoots != [ ]; message = "You must set the option ‘boot.loader.grub.devices’ or " + "'boot.loader.grub.mirroredBoots' to make the system bootable."; @@ -802,22 +746,6 @@ in message = "You cannot have duplicated devices in mirroredBoots"; } { - assertion = !cfg.trustedBoot.enable || cfg.version == 2; - message = "Trusted GRUB is only available for GRUB 2"; - } - { - assertion = !cfg.efiSupport || !cfg.trustedBoot.enable; - message = "Trusted GRUB does not have EFI support"; - } - { - assertion = !cfg.zfsSupport || !cfg.trustedBoot.enable; - message = "Trusted GRUB does not have ZFS support"; - } - { - assertion = !cfg.trustedBoot.enable || cfg.trustedBoot.systemHasTPM == "YES_TPM_is_activated"; - message = "Trusted GRUB can break the system! Confirm that the system has an activated TPM by setting 'systemHasTPM'."; - } - { assertion = cfg.efiInstallAsRemovable -> cfg.efiSupport; message = "If you wish to to use boot.loader.grub.efiInstallAsRemovable, then turn on boot.loader.grub.efiSupport"; } @@ -825,6 +753,10 @@ in assertion = cfg.efiInstallAsRemovable -> !config.boot.loader.efi.canTouchEfiVariables; message = "If you wish to to use boot.loader.grub.efiInstallAsRemovable, then turn off boot.loader.efi.canTouchEfiVariables"; } + { + assertion = !(options.boot.loader.grub.version.isDefined && cfg.version == 1); + message = "Support for version 0.9x of GRUB was removed after being unsupported upstream for around a decade"; + } ] ++ flip concatMap cfg.mirroredBoots (args: [ { assertion = args.devices != [ ]; @@ -844,6 +776,11 @@ in })); }) + (mkIf options.boot.loader.grub.version.isDefined { + warnings = [ '' + The boot.loader.grub.version option does not have any effect anymore, please remove it from your configuration. + '' ]; + }) ]; @@ -855,6 +792,10 @@ in (mkRenamedOptionModule [ "boot" "grubDevice" ] [ "boot" "loader" "grub" "device" ]) (mkRenamedOptionModule [ "boot" "bootMount" ] [ "boot" "loader" "grub" "bootDevice" ]) (mkRenamedOptionModule [ "boot" "grubSplashImage" ] [ "boot" "loader" "grub" "splashImage" ]) + (mkRemovedOptionModule [ "boot" "loader" "grub" "trustedBoot" ] '' + Support for Trusted GRUB has been removed, because the project + has been retired upstream. + '') (mkRemovedOptionModule [ "boot" "loader" "grub" "extraInitrd" ] '' This option has been replaced with the bootloader agnostic boot.initrd.secrets option. To migrate to the initrd secrets system, diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl index 2779f26aa1b62..cfccb93264bfd 100644 --- a/nixos/modules/system/boot/loader/grub/install-grub.pl +++ b/nixos/modules/system/boot/loader/grub/install-grub.pl @@ -61,7 +61,6 @@ sub runCommand { } my $grub = get("grub"); -my $grubVersion = int(get("version")); my $grubTarget = get("grubTarget"); my $extraConfig = get("extraConfig"); my $extraPrepareConfig = get("extraPrepareConfig"); @@ -96,9 +95,7 @@ my $theme = get("theme"); my $saveDefault = $defaultEntry eq "saved"; $ENV{'PATH'} = get("path"); -die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2; - -print STDERR "updating GRUB $grubVersion menu...\n"; +print STDERR "updating GRUB 2 menu...\n"; mkpath("$bootPath/grub", 0, 0700); @@ -176,76 +173,74 @@ sub GrubFs { } my $search = ""; - if ($grubVersion > 1) { - # ZFS is completely separate logic as zpools are always identified by a label - # or custom UUID - if ($fs->type eq 'zfs') { - my $sid = index($fs->device, '/'); - - if ($sid < 0) { - $search = '--label ' . $fs->device; - $path = '/@' . $path; - } else { - $search = '--label ' . substr($fs->device, 0, $sid); - $path = '/' . substr($fs->device, $sid) . '/@' . $path; + # ZFS is completely separate logic as zpools are always identified by a label + # or custom UUID + if ($fs->type eq 'zfs') { + my $sid = index($fs->device, '/'); + + if ($sid < 0) { + $search = '--label ' . $fs->device; + $path = '/@' . $path; + } else { + $search = '--label ' . substr($fs->device, 0, $sid); + $path = '/' . substr($fs->device, $sid) . '/@' . $path; + } + } else { + my %types = ('uuid' => '--fs-uuid', 'label' => '--label'); + + if ($fsIdentifier eq 'provided') { + # If the provided dev is identifying the partition using a label or uuid, + # we should get the label / uuid and do a proper search + my @matches = $fs->device =~ m/\/dev\/disk\/by-(label|uuid)\/(.*)/; + if ($#matches > 1) { + die "Too many matched devices" + } elsif ($#matches == 1) { + $search = "$types{$matches[0]} $matches[1]" } } else { - my %types = ('uuid' => '--fs-uuid', 'label' => '--label'); - - if ($fsIdentifier eq 'provided') { - # If the provided dev is identifying the partition using a label or uuid, - # we should get the label / uuid and do a proper search - my @matches = $fs->device =~ m/\/dev\/disk\/by-(label|uuid)\/(.*)/; - if ($#matches > 1) { - die "Too many matched devices" - } elsif ($#matches == 1) { - $search = "$types{$matches[0]} $matches[1]" - } - } else { - # Determine the identifying type - $search = $types{$fsIdentifier} . ' '; + # Determine the identifying type + $search = $types{$fsIdentifier} . ' '; - # Based on the type pull in the identifier from the system - my ($status, @devInfo) = runCommand("@utillinux@/bin/blkid", "-o", "export", @{[$fs->device]}); - if ($status != 0) { - die "Failed to get blkid info (returned $status) for @{[$fs->mount]} on @{[$fs->device]}"; - } - my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/; - if ($#matches != 0) { - die "Couldn't find a $types{$fsIdentifier} for @{[$fs->device]}\n" - } - $search .= $matches[0]; + # Based on the type pull in the identifier from the system + my ($status, @devInfo) = runCommand("@utillinux@/bin/blkid", "-o", "export", @{[$fs->device]}); + if ($status != 0) { + die "Failed to get blkid info (returned $status) for @{[$fs->mount]} on @{[$fs->device]}"; + } + my @matches = join("", @devInfo) =~ m/@{[uc $fsIdentifier]}=([^\n]*)/; + if ($#matches != 0) { + die "Couldn't find a $types{$fsIdentifier} for @{[$fs->device]}\n" } + $search .= $matches[0]; + } - # BTRFS is a special case in that we need to fix the referrenced path based on subvolumes - if ($fs->type eq 'btrfs') { - my ($status, @id_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "show", @{[$fs->mount]}); + # BTRFS is a special case in that we need to fix the referrenced path based on subvolumes + if ($fs->type eq 'btrfs') { + my ($status, @id_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "show", @{[$fs->mount]}); + if ($status != 0) { + die "Failed to retrieve subvolume info for @{[$fs->mount]}\n"; + } + my @ids = join("\n", @id_info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; + if ($#ids > 0) { + die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n" + } elsif ($#ids == 0) { + my ($status, @path_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "list", @{[$fs->mount]}); if ($status != 0) { - die "Failed to retrieve subvolume info for @{[$fs->mount]}\n"; + die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n"; } - my @ids = join("\n", @id_info) =~ m/^(?!\/\n).*Subvolume ID:[ \t\n]*([0-9]+)/s; - if ($#ids > 0) { - die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n" - } elsif ($#ids == 0) { - my ($status, @path_info) = runCommand("@btrfsprogs@/bin/btrfs", "subvol", "list", @{[$fs->mount]}); - if ($status != 0) { - die "Failed to find @{[$fs->mount]} subvolume id from btrfs\n"; - } - my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/; - if ($#paths > 0) { - die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n"; - } elsif ($#paths != 0) { - die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n"; - } - $path = "/$paths[0]$path"; + my @paths = join("", @path_info) =~ m/ID $ids[0] [^\n]* path ([^\n]*)/; + if ($#paths > 0) { + die "Btrfs returned multiple paths for a single subvolume id, mountpoint @{[$fs->mount]}\n"; + } elsif ($#paths != 0) { + die "Btrfs did not return a path for the subvolume at @{[$fs->mount]}\n"; } + $path = "/$paths[0]$path"; } } - if (not $search eq "") { - $search = "search --set=drive$driveid " . $search; - $path = "(\$drive$driveid)$path"; - $driveid += 1; - } + } + if (not $search eq "") { + $search = "search --set=drive$driveid " . $search; + $path = "(\$drive$driveid)$path"; + $driveid += 1; } return Grub->new(path => $path, search => $search); } @@ -258,166 +253,151 @@ if ($copyKernels == 0) { # Generate the header. my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n"; -if ($grubVersion == 1) { - # $defaultEntry might be "saved", indicating that we want to use the last selected configuration as default. - # Incidentally this is already the correct value for the grub 1 config to achieve this behaviour. - $conf .= " - default $defaultEntry - timeout $timeout - "; - if ($splashImage) { - copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath: $!\n"; - $conf .= "splashimage " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background.xpm.gz\n"; +my @users = (); +foreach my $user ($dom->findnodes('/expr/attrs/attr[@name = "users"]/attrs/attr')) { + my $name = $user->findvalue('@name') or die; + my $hashedPassword = $user->findvalue('./attrs/attr[@name = "hashedPassword"]/string/@value'); + my $hashedPasswordFile = $user->findvalue('./attrs/attr[@name = "hashedPasswordFile"]/string/@value'); + my $password = $user->findvalue('./attrs/attr[@name = "password"]/string/@value'); + my $passwordFile = $user->findvalue('./attrs/attr[@name = "passwordFile"]/string/@value'); + + if ($hashedPasswordFile) { + open(my $f, '<', $hashedPasswordFile) or die "Can't read file '$hashedPasswordFile'!"; + $hashedPassword = <$f>; + chomp $hashedPassword; + } + if ($passwordFile) { + open(my $f, '<', $passwordFile) or die "Can't read file '$passwordFile'!"; + $password = <$f>; + chomp $password; } -} - -else { - my @users = (); - foreach my $user ($dom->findnodes('/expr/attrs/attr[@name = "users"]/attrs/attr')) { - my $name = $user->findvalue('@name') or die; - my $hashedPassword = $user->findvalue('./attrs/attr[@name = "hashedPassword"]/string/@value'); - my $hashedPasswordFile = $user->findvalue('./attrs/attr[@name = "hashedPasswordFile"]/string/@value'); - my $password = $user->findvalue('./attrs/attr[@name = "password"]/string/@value'); - my $passwordFile = $user->findvalue('./attrs/attr[@name = "passwordFile"]/string/@value'); - - if ($hashedPasswordFile) { - open(my $f, '<', $hashedPasswordFile) or die "Can't read file '$hashedPasswordFile'!"; - $hashedPassword = <$f>; - chomp $hashedPassword; - } - if ($passwordFile) { - open(my $f, '<', $passwordFile) or die "Can't read file '$passwordFile'!"; - $password = <$f>; - chomp $password; - } - if ($hashedPassword) { - if (index($hashedPassword, "grub.pbkdf2.") == 0) { - $conf .= "\npassword_pbkdf2 $name $hashedPassword"; - } - else { - die "Password hash for GRUB user '$name' is not valid!"; - } - } - elsif ($password) { - $conf .= "\npassword $name $password"; + if ($hashedPassword) { + if (index($hashedPassword, "grub.pbkdf2.") == 0) { + $conf .= "\npassword_pbkdf2 $name $hashedPassword"; } else { - die "GRUB user '$name' has no password!"; + die "Password hash for GRUB user '$name' is not valid!"; } - push(@users, $name); } - if (@users) { - $conf .= "\nset superusers=\"" . join(' ',@users) . "\"\n"; - } - - if ($copyKernels == 0) { - $conf .= " - " . $grubStore->search; + elsif ($password) { + $conf .= "\npassword $name $password"; } - # FIXME: should use grub-mkconfig. - my $defaultEntryText = $defaultEntry; - if ($saveDefault) { - $defaultEntryText = "\"\${saved_entry}\""; + else { + die "GRUB user '$name' has no password!"; } - $conf .= " - " . $grubBoot->search . " - if [ -s \$prefix/grubenv ]; then - load_env - fi + push(@users, $name); +} +if (@users) { + $conf .= "\nset superusers=\"" . join(' ',@users) . "\"\n"; +} - # ‘grub-reboot’ sets a one-time saved entry, which we process here and - # then delete. - if [ \"\${next_entry}\" ]; then - set default=\"\${next_entry}\" - set next_entry= - save_env next_entry - set timeout=1 - set boot_once=true - else - set default=$defaultEntryText - set timeout=$timeout +if ($copyKernels == 0) { + $conf .= " + " . $grubStore->search; +} +# FIXME: should use grub-mkconfig. +my $defaultEntryText = $defaultEntry; +if ($saveDefault) { + $defaultEntryText = "\"\${saved_entry}\""; +} +$conf .= " + " . $grubBoot->search . " + if [ -s \$prefix/grubenv ]; then + load_env + fi + + # ‘grub-reboot’ sets a one-time saved entry, which we process here and + # then delete. + if [ \"\${next_entry}\" ]; then + set default=\"\${next_entry}\" + set next_entry= + save_env next_entry + set timeout=1 + set boot_once=true + else + set default=$defaultEntryText + set timeout=$timeout + fi + + function savedefault { + if [ -z \"\${boot_once}\"]; then + saved_entry=\"\${chosen}\" + save_env saved_entry fi + } - function savedefault { - if [ -z \"\${boot_once}\"]; then - saved_entry=\"\${chosen}\" - save_env saved_entry - fi - } - - # Setup the graphics stack for bios and efi systems - if [ \"\${grub_platform}\" = \"efi\" ]; then - insmod efi_gop - insmod efi_uga - else - insmod vbe + # Setup the graphics stack for bios and efi systems + if [ \"\${grub_platform}\" = \"efi\" ]; then + insmod efi_gop + insmod efi_uga + else + insmod vbe + fi +"; + +if ($font) { + copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n"; + $conf .= " + insmod font + if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then + insmod gfxterm + if [ \"\${grub_platform}\" = \"efi\" ]; then + set gfxmode=$gfxmodeEfi + set gfxpayload=$gfxpayloadEfi + else + set gfxmode=$gfxmodeBios + set gfxpayload=$gfxpayloadBios + fi + terminal_output gfxterm fi "; - - if ($font) { - copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n"; - $conf .= " - insmod font - if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then - insmod gfxterm - if [ \"\${grub_platform}\" = \"efi\" ]; then - set gfxmode=$gfxmodeEfi - set gfxpayload=$gfxpayloadEfi - else - set gfxmode=$gfxmodeBios - set gfxpayload=$gfxpayloadBios - fi - terminal_output gfxterm - fi - "; +} +if ($splashImage) { + # Keeps the image's extension. + my ($filename, $dirs, $suffix) = fileparse($splashImage, qr"\..[^.]*$"); + # The module for jpg is jpeg. + if ($suffix eq ".jpg") { + $suffix = ".jpeg"; } - if ($splashImage) { - # Keeps the image's extension. - my ($filename, $dirs, $suffix) = fileparse($splashImage, qr"\..[^.]*$"); - # The module for jpg is jpeg. - if ($suffix eq ".jpg") { - $suffix = ".jpeg"; - } - if ($backgroundColor) { - $conf .= " - background_color '$backgroundColor' - "; - } - copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n"; + if ($backgroundColor) { $conf .= " - insmod " . substr($suffix, 1) . " - if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then - set color_normal=white/black - set color_highlight=black/white - else - set menu_color_normal=cyan/blue - set menu_color_highlight=white/blue - fi + background_color '$backgroundColor' "; } + copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n"; + $conf .= " + insmod " . substr($suffix, 1) . " + if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then + set color_normal=white/black + set color_highlight=black/white + else + set menu_color_normal=cyan/blue + set menu_color_highlight=white/blue + fi + "; +} - rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" if -e "$bootPath/theme"; +rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" if -e "$bootPath/theme"; - if ($theme) { - # Copy theme - rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n"; - $conf .= " - # Sets theme. - set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt - export theme - # Load theme fonts, if any - "; +if ($theme) { + # Copy theme + rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n"; + $conf .= " + # Sets theme. + set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt + export theme + # Load theme fonts, if any + "; - find( { wanted => sub { - if ($_ =~ /\.pf2$/i) { - $font = File::Spec->abs2rel($File::Find::name, $theme); - $conf .= " - loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font - "; - } - }, no_chdir => 1 }, $theme ); - } + find( { wanted => sub { + if ($_ =~ /\.pf2$/i) { + $font = File::Spec->abs2rel($File::Find::name, $theme); + $conf .= " + loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font + "; + } + }, no_chdir => 1 }, $theme ); } $conf .= "$extraConfig\n"; @@ -494,31 +474,19 @@ sub addEntry { readFile("$path/kernel-params"); my $xenParams = $xen && -e "$path/xen-params" ? readFile("$path/xen-params") : ""; - if ($grubVersion == 1) { - $conf .= "title $name\n"; - $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; - $conf .= " kernel $xen $xenParams\n" if $xen; - $conf .= " " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n"; - $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; - if ($saveDefault) { - $conf .= " savedefault\n"; - } - $conf .= "\n"; - } else { - $conf .= "menuentry \"$name\" " . $options . " {\n"; - if ($saveDefault) { - $conf .= " savedefault\n"; - } - $conf .= $grubBoot->search . "\n"; - if ($copyKernels == 0) { - $conf .= $grubStore->search . "\n"; - } - $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; - $conf .= " multiboot $xen $xenParams\n" if $xen; - $conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n"; - $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; - $conf .= "}\n\n"; + $conf .= "menuentry \"$name\" " . $options . " {\n"; + if ($saveDefault) { + $conf .= " savedefault\n"; } + $conf .= $grubBoot->search . "\n"; + if ($copyKernels == 0) { + $conf .= $grubStore->search . "\n"; + } + $conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig; + $conf .= " multiboot $xen $xenParams\n" if $xen; + $conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n"; + $conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n"; + $conf .= "}\n\n"; } @@ -562,7 +530,7 @@ sub addProfile { my ($profile, $description) = @_; # Add entries for all generations of this profile. - $conf .= "submenu \"$description\" --class submenu {\n" if $grubVersion == 2; + $conf .= "submenu \"$description\" --class submenu {\n"; sub nrFromGen { my ($x) = @_; $x =~ /\/\w+-(\d+)-link/; return $1; } @@ -585,17 +553,15 @@ sub addProfile { addEntry("@distroName@ - Configuration " . nrFromGen($link) . " ($date - $version)", $link, $subEntryOptions, 0); } - $conf .= "}\n" if $grubVersion == 2; + $conf .= "}\n"; } addProfile "/nix/var/nix/profiles/system", "@distroName@ - All configurations"; -if ($grubVersion == 2) { - for my $profile (glob "/nix/var/nix/profiles/system-profiles/*") { - my $name = basename($profile); - next unless $name =~ /^\w+$/; - addProfile $profile, "@distroName@ - Profile '$name'"; - } +for my $profile (glob "/nix/var/nix/profiles/system-profiles/*") { + my $name = basename($profile); + next unless $name =~ /^\w+$/; + addProfile $profile, "@distroName@ - Profile '$name'"; } # extraPrepareConfig could refer to @bootPath@, which we have to substitute @@ -607,16 +573,14 @@ if ($extraPrepareConfig ne "") { } # write the GRUB config. -my $confFile = $grubVersion == 1 ? "$bootPath/grub/menu.lst" : "$bootPath/grub/grub.cfg"; +my $confFile = "$bootPath/grub/grub.cfg"; my $tmpFile = $confFile . ".tmp"; writeFile($tmpFile, $conf); # check whether to install GRUB EFI or not sub getEfiTarget { - if ($grubVersion == 1) { - return "no" - } elsif (($grub ne "") && ($grubEfi ne "")) { + if (($grub ne "") && ($grubEfi ne "")) { # EFI can only be installed when target is set; # A target is also required then for non-EFI grub if (($grubTarget eq "") || ($grubTargetEfi eq "")) { die } @@ -741,7 +705,7 @@ symlink "$bootPath", "$tmpDir/boot" or die "Failed to symlink $tmpDir/boot: $!"; if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) { foreach my $dev (@deviceTargets) { next if $dev eq "nodev"; - print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n"; + print STDERR "installing the GRUB 2 boot loader on $dev...\n"; my @command = ("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev), @extraGrubInstallArgs); if ($forceInstall eq "true") { push @command, "--force"; @@ -756,7 +720,7 @@ if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) { # install EFI GRUB if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) { - print STDERR "installing the GRUB $grubVersion EFI boot loader into $efiSysMountPoint...\n"; + print STDERR "installing the GRUB 2 boot loader into $efiSysMountPoint...\n"; my @command = ("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", @extraGrubInstallArgs); if ($forceInstall eq "true") { push @command, "--force"; diff --git a/nixos/modules/system/boot/loader/grub/ipxe.nix b/nixos/modules/system/boot/loader/grub/ipxe.nix index adddcbee0164d..d926b7ceaa6e6 100644 --- a/nixos/modules/system/boot/loader/grub/ipxe.nix +++ b/nixos/modules/system/boot/loader/grub/ipxe.nix @@ -46,11 +46,7 @@ in config = mkIf (builtins.length scripts != 0) { - boot.loader.grub.extraEntries = - if config.boot.loader.grub.version == 2 then - toString (map grubEntry scripts) - else - throw "iPXE is not supported with GRUB 1."; + boot.loader.grub.extraEntries = toString (map grubEntry scripts); boot.loader.grub.extraFiles = { "ipxe.lkrn" = "${pkgs.ipxe}/ipxe.lkrn"; } diff --git a/nixos/modules/system/boot/loader/grub/memtest.nix b/nixos/modules/system/boot/loader/grub/memtest.nix index ccb6e8cc3caf5..ee969e9bff5bf 100644 --- a/nixos/modules/system/boot/loader/grub/memtest.nix +++ b/nixos/modules/system/boot/loader/grub/memtest.nix @@ -84,15 +84,11 @@ in }) (mkIf (cfg.enable && !efiSupport) { - boot.loader.grub.extraEntries = - if config.boot.loader.grub.version == 2 then - '' - menuentry "Memtest86+" { - linux16 @bootRoot@/memtest.bin ${toString cfg.params} - } - '' - else - throw "Memtest86+ is not supported with GRUB 1."; + boot.loader.grub.extraEntries = '' + menuentry "Memtest86+" { + linux16 @bootRoot@/memtest.bin ${toString cfg.params} + } + ''; boot.loader.grub.extraFiles."memtest.bin" = "${memtest86}/memtest.bin"; }) diff --git a/nixos/modules/virtualisation/azure-common.nix b/nixos/modules/virtualisation/azure-common.nix index f29d368137ae0..cd1ffdb6cbcc3 100644 --- a/nixos/modules/virtualisation/azure-common.nix +++ b/nixos/modules/virtualisation/azure-common.nix @@ -12,7 +12,6 @@ with lib; # Generate a GRUB menu. boot.loader.grub.device = "/dev/sda"; - boot.loader.grub.version = 2; boot.loader.timeout = 0; boot.growPartition = true; diff --git a/nixos/modules/virtualisation/xen-domU.nix b/nixos/modules/virtualisation/xen-domU.nix index c00b984c2ce04..ce5a482b1145b 100644 --- a/nixos/modules/virtualisation/xen-domU.nix +++ b/nixos/modules/virtualisation/xen-domU.nix @@ -3,7 +3,6 @@ { ... }: { - boot.loader.grub.version = 2; boot.loader.grub.device = "nodev"; boot.initrd.kernelModules = diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 5ceb39d0be51d..9f35dca5cc4f1 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -46,7 +46,7 @@ let inherit (rec { doRunTest = arg: ((import ../lib/testing-python.nix { inherit system pkgs; }).evalTest { - imports = [ arg ]; + imports = [ arg readOnlyPkgs ]; }).config.result; findTests = tree: if tree?recurseForDerivations && tree.recurseForDerivations @@ -65,6 +65,23 @@ let runTestOn ; + # Using a single instance of nixpkgs makes test evaluation faster. + # To make sure we don't accidentally depend on a modified pkgs, we make the + # related options read-only. We need to test the right configuration. + # + # If your service depends on a nixpkgs setting, first try to avoid that, but + # otherwise, you can remove the readOnlyPkgs import and test your service as + # usual. + readOnlyPkgs = + # TODO: We currently accept this for nixosTests, so that the `pkgs` argument + # is consistent with `pkgs` in `pkgs.nixosTests`. Can we reinitialize + # it with `allowAliases = false`? + # warnIf pkgs.config.allowAliases "nixosTests: pkgs includes aliases." + { + _class = "nixosTest"; + node.pkgs = pkgs; + }; + in { # Testing the test driver @@ -267,7 +284,7 @@ in { gitdaemon = handleTest ./gitdaemon.nix {}; gitea = handleTest ./gitea.nix { giteaPackage = pkgs.gitea; }; github-runner = handleTest ./github-runner.nix {}; - gitlab = handleTest ./gitlab.nix {}; + gitlab = runTest ./gitlab.nix; gitolite = handleTest ./gitolite.nix {}; gitolite-fcgiwrap = handleTest ./gitolite-fcgiwrap.nix {}; glusterfs = handleTest ./glusterfs.nix {}; @@ -297,7 +314,7 @@ in { haste-server = handleTest ./haste-server.nix {}; haproxy = handleTest ./haproxy.nix {}; hardened = handleTest ./hardened.nix {}; - harmonia = handleTest ./harmonia.nix {}; + harmonia = runTest ./harmonia.nix; headscale = handleTest ./headscale.nix {}; healthchecks = handleTest ./web-apps/healthchecks.nix {}; hbase2 = handleTest ./hbase.nix { package=pkgs.hbase2; }; diff --git a/nixos/tests/gitlab.nix b/nixos/tests/gitlab.nix index c2a11bada0a35..672b497e7ec68 100644 --- a/nixos/tests/gitlab.nix +++ b/nixos/tests/gitlab.nix @@ -6,7 +6,10 @@ # - Creating Merge Requests and merging them # - Opening and closing issues. # - Downloading repository archives as tar.gz and tar.bz2 -import ./make-test-python.nix ({ pkgs, lib, ... }: +# Run with +# [nixpkgs]$ nix-build -A nixosTests.gitlab + +{ pkgs, lib, ... }: with lib; @@ -174,7 +177,7 @@ in { gitlab.wait_for_unit("gitlab.service") gitlab.wait_for_unit("gitlab-pages.service") gitlab.wait_for_unit("gitlab-sidekiq.service") - gitlab.wait_for_file("${nodes.gitlab.config.services.gitlab.statePath}/tmp/sockets/gitlab.socket") + gitlab.wait_for_file("${nodes.gitlab.services.gitlab.statePath}/tmp/sockets/gitlab.socket") gitlab.wait_until_succeeds("curl -sSf http://gitlab/users/sign_in") ''; @@ -419,15 +422,15 @@ in { + '' gitlab.systemctl("start gitlab-backup.service") gitlab.wait_for_unit("gitlab-backup.service") - gitlab.wait_for_file("${nodes.gitlab.config.services.gitlab.statePath}/backup/dump_gitlab_backup.tar") + gitlab.wait_for_file("${nodes.gitlab.services.gitlab.statePath}/backup/dump_gitlab_backup.tar") gitlab.systemctl("stop postgresql.service gitlab.target") gitlab.succeed( - "find ${nodes.gitlab.config.services.gitlab.statePath} -mindepth 1 -maxdepth 1 -not -name backup -execdir rm -r {} +" + "find ${nodes.gitlab.services.gitlab.statePath} -mindepth 1 -maxdepth 1 -not -name backup -execdir rm -r {} +" ) gitlab.succeed("systemd-tmpfiles --create") - gitlab.succeed("rm -rf ${nodes.gitlab.config.services.postgresql.dataDir}") + gitlab.succeed("rm -rf ${nodes.gitlab.services.postgresql.dataDir}") gitlab.systemctl("start gitlab-config.service gitaly.service gitlab-postgresql.service") - gitlab.wait_for_file("${nodes.gitlab.config.services.gitlab.statePath}/tmp/sockets/gitaly.socket") + gitlab.wait_for_file("${nodes.gitlab.services.gitlab.statePath}/tmp/sockets/gitaly.socket") gitlab.succeed( "sudo -u gitlab -H gitlab-rake gitlab:backup:restore RAILS_ENV=production BACKUP=dump force=yes" ) @@ -435,4 +438,4 @@ in { '' + waitForServices + test false; -}) +} diff --git a/nixos/tests/harmonia.nix b/nixos/tests/harmonia.nix index 95fb7ea18cf8d..6cf9ad4d23358 100644 --- a/nixos/tests/harmonia.nix +++ b/nixos/tests/harmonia.nix @@ -1,19 +1,21 @@ -import ./make-test-python.nix ({ pkgs, ... }: +{ pkgs, lib, ... }: + { name = "harmonia"; + nodes = { harmonia = { services.harmonia = { enable = true; - signKeyPath = pkgs.writeText "cache-key" - "cache.example.com-1:9FhO0w+7HjZrhvmzT1VlAZw4OSAlFGTgC24Seg3tmPl4gZBdwZClzTTHr9cVzJpwsRSYLTu7hEAQe3ljy92CWg=="; + signKeyPath = pkgs.writeText "cache-key" "cache.example.com-1:9FhO0w+7HjZrhvmzT1VlAZw4OSAlFGTgC24Seg3tmPl4gZBdwZClzTTHr9cVzJpwsRSYLTu7hEAQe3ljy92CWg=="; + settings.priority = 35; }; networking.firewall.allowedTCPPorts = [ 5000 ]; - system.extraDependencies = [ pkgs.hello ]; + system.extraDependencies = [ pkgs.emptyFile ]; }; - client01 = { lib, ... }: { + client01 = { nix.settings = { substituters = lib.mkForce [ "http://harmonia:5000" ]; trusted-public-keys = lib.mkForce [ "cache.example.com-1:eIGQXcGQpc00x6/XFcyacLEUmC07u4RAEHt5Y8vdglo=" ]; @@ -21,13 +23,15 @@ import ./make-test-python.nix ({ pkgs, ... }: }; }; - testScript = '' + testScript = { nodes, ... }: '' start_all() - client01.wait_until_succeeds("curl -f http://harmonia:5000/version") - client01.succeed("curl -f http://harmonia:5000/nix-cache-info") + harmonia.wait_for_unit("harmonia.service") + + client01.wait_until_succeeds("curl -f http://harmonia:5000/nix-cache-info | grep '${toString nodes.harmonia.services.harmonia.settings.priority}' >&2") + client01.succeed("curl -f http://harmonia:5000/version | grep '${nodes.harmonia.services.harmonia.package.version}' >&2") client01.succeed("cat /etc/nix/nix.conf >&2") - client01.wait_until_succeeds("nix-store --realise ${pkgs.hello} --store /root/other-store") + client01.succeed("nix-store --realise ${pkgs.emptyFile} --store /root/other-store") ''; -}) +} diff --git a/nixos/tests/installer.nix b/nixos/tests/installer.nix index 51d0d232ebbf6..28b93472263f4 100644 --- a/nixos/tests/installer.nix +++ b/nixos/tests/installer.nix @@ -10,7 +10,7 @@ with pkgs.lib; let # The configuration to install. - makeConfig = { bootLoader, grubVersion, grubDevice, grubIdentifier, grubUseEfi + makeConfig = { bootLoader, grubDevice, grubIdentifier, grubUseEfi , extraConfig, forceGrubReinstallCount ? 0 }: pkgs.writeText "configuration.nix" '' @@ -29,11 +29,6 @@ let ${optionalString systemdStage1 "boot.initrd.systemd.enable = true;"} ${optionalString (bootLoader == "grub") '' - boot.loader.grub.version = ${toString grubVersion}; - ${optionalString (grubVersion == 1) '' - boot.loader.grub.splashImage = null; - ''} - boot.loader.grub.extraConfig = "serial; terminal_output serial"; ${if grubUseEfi then '' boot.loader.grub.device = "nodev"; @@ -70,11 +65,11 @@ let # disk, and then reboot from the hard disk. It's parameterized with # a test script fragment `createPartitions', which must create # partitions and filesystems. - testScriptFun = { bootLoader, createPartitions, grubVersion, grubDevice, grubUseEfi + testScriptFun = { bootLoader, createPartitions, grubDevice, grubUseEfi , grubIdentifier, preBootCommands, postBootCommands, extraConfig , testSpecialisationConfig }: - let iface = if grubVersion == 1 then "ide" else "virtio"; + let iface = "virtio"; isEfi = bootLoader == "systemd-boot" || (bootLoader == "grub" && grubUseEfi); bios = if pkgs.stdenv.isAarch64 then "QEMU_EFI.fd" else "OVMF.fd"; in if !isEfi && !pkgs.stdenv.hostPlatform.isx86 then '' @@ -122,7 +117,7 @@ let machine.succeed("cat /mnt/etc/nixos/hardware-configuration.nix >&2") machine.copy_from_host( "${ makeConfig { - inherit bootLoader grubVersion grubDevice grubIdentifier + inherit bootLoader grubDevice grubIdentifier grubUseEfi extraConfig; } }", @@ -193,7 +188,7 @@ let # doesn't know about the host-guest sharing mechanism. machine.copy_from_host_via_shell( "${ makeConfig { - inherit bootLoader grubVersion grubDevice grubIdentifier + inherit bootLoader grubDevice grubIdentifier grubUseEfi extraConfig; forceGrubReinstallCount = 1; } @@ -222,7 +217,7 @@ let # doesn't know about the host-guest sharing mechanism. machine.copy_from_host_via_shell( "${ makeConfig { - inherit bootLoader grubVersion grubDevice grubIdentifier + inherit bootLoader grubDevice grubIdentifier grubUseEfi extraConfig; forceGrubReinstallCount = 2; } @@ -284,7 +279,7 @@ let { createPartitions, preBootCommands ? "", postBootCommands ? "", extraConfig ? "" , extraInstallerConfig ? {} , bootLoader ? "grub" # either "grub" or "systemd-boot" - , grubVersion ? 2, grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false + , grubDevice ? "/dev/vda", grubIdentifier ? "uuid", grubUseEfi ? false , enableOCR ? false, meta ? {} , testSpecialisationConfig ? false }: @@ -316,11 +311,9 @@ let # installer. This ensures the target disk (/dev/vda) is # the same during and after installation. virtualisation.emptyDiskImages = [ 512 ]; - virtualisation.rootDevice = - if grubVersion == 1 then "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive2" else "/dev/vdb"; + virtualisation.rootDevice = "/dev/vdb"; virtualisation.bootLoaderDevice = "/dev/vda"; - virtualisation.qemu.diskInterface = - if grubVersion == 1 then "scsi" else "virtio"; + virtualisation.qemu.diskInterface = "virtio"; # We don't want to have any networking in the guest whatsoever. # Also, if any vlans are enabled, the guest will reboot @@ -372,8 +365,7 @@ let # curl's tarball, we see what it's trying to download curl ] - ++ optional (bootLoader == "grub" && grubVersion == 1) pkgs.grub - ++ optionals (bootLoader == "grub" && grubVersion == 2) (let + ++ optionals (bootLoader == "grub") (let zfsSupport = lib.any (x: x == "zfs") (extraInstallerConfig.boot.supportedFilesystems or []); in [ @@ -392,7 +384,7 @@ let testScript = testScriptFun { inherit bootLoader createPartitions preBootCommands postBootCommands - grubVersion grubDevice grubIdentifier grubUseEfi extraConfig + grubDevice grubIdentifier grubUseEfi extraConfig testSpecialisationConfig; }; }; @@ -875,26 +867,6 @@ in { ''; }; - # Test a basic install using GRUB 1. - grub1 = makeInstallerTest "grub1" rec { - createPartitions = '' - machine.succeed( - "flock ${grubDevice} parted --script ${grubDevice} -- mklabel msdos" - + " mkpart primary linux-swap 1M 1024M" - + " mkpart primary ext2 1024M -1s", - "udevadm settle", - "mkswap ${grubDevice}-part1 -L swap", - "swapon -L swap", - "mkfs.ext3 -L nixos ${grubDevice}-part2", - "mount LABEL=nixos /mnt", - "mkdir -p /mnt/tmp", - ) - ''; - grubVersion = 1; - # /dev/sda is not stable, even when the SCSI disk number is. - grubDevice = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive1"; - }; - # Test using labels to identify volumes in grub simpleLabels = makeInstallerTest "simpleLabels" { createPartitions = '' diff --git a/nixos/tests/mysql/mysql-replication.nix b/nixos/tests/mysql/mysql-replication.nix index f6014019bd53a..8f1695eb97e27 100644 --- a/nixos/tests/mysql/mysql-replication.nix +++ b/nixos/tests/mysql/mysql-replication.nix @@ -42,7 +42,7 @@ let enable = true; replication.role = "slave"; replication.serverId = 2; - replication.masterHost = nodes.primary.config.networking.hostName; + replication.masterHost = nodes.primary.networking.hostName; replication.masterUser = replicateUser; replication.masterPassword = replicatePassword; }; @@ -54,7 +54,7 @@ let enable = true; replication.role = "slave"; replication.serverId = 3; - replication.masterHost = nodes.primary.config.networking.hostName; + replication.masterHost = nodes.primary.networking.hostName; replication.masterUser = replicateUser; replication.masterPassword = replicatePassword; }; |