diff --git a/doc/release-notes/rl-2611.section.md b/doc/release-notes/rl-2611.section.md index 2b0ef6f04f07..750693bb6c98 100644 --- a/doc/release-notes/rl-2611.section.md +++ b/doc/release-notes/rl-2611.section.md @@ -10,6 +10,7 @@ +- Paths under `/etc/xdg/` from packages in `environment.systemPackages` are no longer linked into the global `/etc/` by default. Modules depending on such directories must declare them explicitly using `environment.pathsToLink`. - `databricks-cli` has been updated from `0.290.2` to `1.x.x`, the first major release. OAuth tokens for interactive logins (`auth_type = databricks-cli`) are now stored in the OS-native secure store by default (Secret Service on Linux) instead of `~/.databricks/token-cache.json`; cached tokens from older versions are not migrated, so run `databricks auth login` once per profile after upgrading. To keep the previous file-backed storage, set `DATABRICKS_AUTH_STORAGE=plaintext` or add `auth_storage = plaintext` under `[__settings__]` in `~/.databrickscfg`. Additionally, the `vector_search_endpoints` DABs resource renamed `min_qps` to `target_qps` (and the `vector-search-endpoints` command renamed `--min-qps` to `--target-qps`). See the [upstream changelog](https://github.com/databricks/cli/blob/main/CHANGELOG.md) for details. - `hurl` has been updated to `8.x.x` which has some breaking changes. See [upstream changelog](https://github.com/Orange-OpenSource/hurl/releases/tag/8.0.0) for details. diff --git a/nixos/modules/config/system-path.nix b/nixos/modules/config/system-path.nix index c014f00da605..5776c8ede413 100644 --- a/nixos/modules/config/system-path.nix +++ b/nixos/modules/config/system-path.nix @@ -187,7 +187,6 @@ in environment.pathsToLink = [ "/bin" - "/etc/xdg" "/etc/gtk-2.0" "/etc/gtk-3.0" "/lib" # FIXME: remove and update debug-info.nix diff --git a/nixos/modules/config/xdg/autostart.nix b/nixos/modules/config/xdg/autostart.nix index 46c90ae1793a..a266b046de1a 100644 --- a/nixos/modules/config/xdg/autostart.nix +++ b/nixos/modules/config/xdg/autostart.nix @@ -22,8 +22,6 @@ }; config = { - # FIXME this does not actually work because "/etc/xdg" is linked - # unconditionally in `nixos/modules/config/system-path.nix` environment.pathsToLink = lib.mkIf config.xdg.autostart.install [ "/etc/xdg/autostart" ]; diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index f242cb8c6a5b..b53365ff26cf 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -763,6 +763,7 @@ in ]; }; serviceConfig.Type = "oneshot"; + serviceConfig.EnvironmentFile = "-/etc/switch-root.conf"; description = "NixOS Activation"; script = # bash @@ -770,6 +771,14 @@ in set -uo pipefail export PATH="/bin:${cfg.package.util-linux}/bin" + # A non-NixOS closure (e.g. init=/bin/sh) has no prepare-root; + # initrd-find-nixos-closure records this as a non-empty NEW_INIT. + # Skip activation and let initrd-switch-root hand over to it directly. + if [ -n "''${NEW_INIT:-}" ]; then + echo "$NEW_INIT is not a NixOS system - not activating" + exit 0 + fi + closure="$(realpath /nixos-closure)" # Initialize the system diff --git a/nixos/modules/system/etc/etc-activation.nix b/nixos/modules/system/etc/etc-activation.nix index b00c25e37802..31842fc9c0c6 100644 --- a/nixos/modules/system/etc/etc-activation.nix +++ b/nixos/modules/system/etc/etc-activation.nix @@ -71,6 +71,10 @@ RequiresMountsFor = [ "/sysroot/nix/store" ]; + # find-etc only creates this symlink for a NixOS init. For a + # non-NixOS init= (e.g. init=/bin/sh) it is absent, so skip the + # mount instead of failing the whole initrd. + ConditionPathExists = "/etc-metadata-image"; }; requires = [ config.boot.initrd.systemd.services.initrd-find-etc.name @@ -123,6 +127,8 @@ "/run/nixos-etc-metadata" ]; DefaultDependencies = false; + # Skip for a non-NixOS init=, see the metadata mount above. + ConditionPathExists = "/etc-basedir"; }; } ]; @@ -140,6 +146,8 @@ # before the overlay is mounted. "/run/nixos-etc-metadata" ]; + # Skip for a non-NixOS init=, see the metadata mount above. + ConditionPathExists = "/etc-metadata-image"; }; serviceConfig = { Type = "oneshot"; diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index bfbea79b97ff..9398eb6b7fb7 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -1643,6 +1643,7 @@ in "i686-linux" ] ./initrd-network-openvpn { systemdStage1 = true; }; systemd-initrd-networkd-ssh = runTest ./systemd-initrd-networkd-ssh.nix; + systemd-initrd-non-nixos = runTest ./systemd-initrd-non-nixos.nix; systemd-initrd-shutdown = runTest { imports = [ ./systemd-shutdown.nix ]; _module.args.systemdStage1 = true; diff --git a/nixos/tests/systemd-initrd-non-nixos.nix b/nixos/tests/systemd-initrd-non-nixos.nix new file mode 100644 index 000000000000..0f564af6504a --- /dev/null +++ b/nixos/tests/systemd-initrd-non-nixos.nix @@ -0,0 +1,68 @@ +{ lib, pkgs, ... }: +let + marker = "REACHED NON-NIXOS INIT AS PID 1"; + + # A non-NixOS init (no prepare-root). We use a store path, not literal + # /bin/sh: a fresh disk has no /bin/sh yet (it is created by the activation a + # non-NixOS init skips), while the store is always mounted; init=/bin/sh works + # the same on a real system. Writes a marker, then stays alive so PID 1 lives. + nonNixosInit = pkgs.writeShellScriptBin "non-nixos" '' + echo "${marker}" > /dev/console + exec ${pkgs.coreutils}/bin/sleep infinity + ''; + + common = { + boot.initrd.systemd.enable = true; + + virtualisation = { + # tmpfs root, like real non-NixOS closure init= microvm consumers. + diskImage = null; + + graphics = false; + }; + + # Speed up wait_for_console. + boot.consoleLogLevel = lib.mkForce 3; + boot.initrd.systemd.managerEnvironment.SYSTEMD_LOG_LEVEL = "warning"; + + # switch-root needs an os-release on the target root. A real system has one + # on disk; our fresh tmpfs does not, so create it. + boot.initrd.systemd.tmpfiles.settings."10-os-release"."/sysroot/etc/os-release".f = { + mode = "0644"; + argument = "ID=test-non-nixos"; + }; + }; +in +{ + name = "systemd-initrd-non-nixos"; + + nodes = { + bashActivation = common; + + nixosInit = { + imports = [ common ]; + system.nixos-init.enable = true; + system.etc.overlay.enable = true; + services.userborn.enable = true; + }; + }; + + testScript = '' + import os + + # The last init= on the cmdline wins; QEMU_KERNEL_PARAMS is appended after + # the default one, so this boots our non-NixOS init. + os.environ["QEMU_KERNEL_PARAMS"] = "init=${lib.getExe nonNixosInit}" + + start_all() + + # If a code path does not skip the non-NixOS init, switch-root is blocked and + # the machine drops to emergency mode: the marker never appears and the wait + # times out. + with subtest("bash initrd-nixos-activation skips a non-NixOS init"): + bashActivation.wait_for_console_text("${marker}", timeout=300) + + with subtest("nixos-init switches to a non-NixOS init directly"): + nixosInit.wait_for_console_text("${marker}", timeout=300) + ''; +} diff --git a/pkgs/by-name/ni/nixos-init/src/find_etc.rs b/pkgs/by-name/ni/nixos-init/src/find_etc.rs index 8b994e1d7534..d06f7bbb0114 100644 --- a/pkgs/by-name/ni/nixos-init/src/find_etc.rs +++ b/pkgs/by-name/ni/nixos-init/src/find_etc.rs @@ -3,7 +3,7 @@ use std::{os::unix, path::Path}; use anyhow::{Context, Result}; use crate::config::Config; -use crate::{SYSROOT_PATH, find_toplevel_in_prefix, resolve_in_prefix}; +use crate::{SYSROOT_PATH, find_init_in_prefix, resolve_in_prefix, verify_init_is_nixos}; /// Entrypoint for the `find-etc` binary. /// @@ -12,7 +12,20 @@ use crate::{SYSROOT_PATH, find_toplevel_in_prefix, resolve_in_prefix}; /// This avoids needing a reference to the toplevel embedded in the initrd and thus reduces the /// need to re-build it. pub fn find_etc() -> Result<()> { - let toplevel = find_toplevel_in_prefix(SYSROOT_PATH)?; + let init_in_sysroot = + find_init_in_prefix(SYSROOT_PATH).context("Failed to find init in sysroot")?; + + // A non-NixOS init= (e.g. init=/bin/sh) has no etc metadata image. Skip + // without creating the symlinks: the etc-overlay mounts are gated on them + // and so skip too, and initrd-init switches root to the init directly. + let Ok(toplevel) = verify_init_is_nixos(SYSROOT_PATH, &init_in_sysroot) else { + log::info!( + "{} is not a NixOS system - not setting up the etc overlay.", + init_in_sysroot.display() + ); + return Ok(()); + }; + let config = Config::from_toplevel(&toplevel, SYSROOT_PATH)?; let basedir = config diff --git a/pkgs/by-name/ni/nixos-init/src/lib.rs b/pkgs/by-name/ni/nixos-init/src/lib.rs index c781757c9b82..bbb4abdb829b 100644 --- a/pkgs/by-name/ni/nixos-init/src/lib.rs +++ b/pkgs/by-name/ni/nixos-init/src/lib.rs @@ -27,16 +27,6 @@ pub use crate::{ pub const SYSROOT_PATH: &str = "/sysroot"; -/// Find the path to the toplevel closure of the system in a prefix. -/// -/// Uses the `init=` parameter on the kernel command-line. -/// -/// Returns the relative path of the init to the prefix, e.g. without the `/sysroot` prefix. -pub fn find_toplevel_in_prefix(prefix: &str) -> Result { - let init_in_sysroot = find_init_in_prefix(prefix)?; - verify_init_is_nixos(prefix, init_in_sysroot) -} - /// Verify that an init path is inside a `NixOS` toplevel directory. /// /// If the path is verified, returns the path to the toplevel. @@ -87,20 +77,16 @@ pub fn find_init_in_prefix(prefix: &str) -> Result { } /// Extract the value of the `init` parameter from the given kernel `cmdline`. +/// +/// If `init=` appears multiple times the last one wins, matching the kernel. +/// This is what makes appending `init=/bin/sh` at the boot prompt work even +/// though the boot entry already has an `init=`. fn extract_init(cmdline: &str) -> Result { - let init_params: Vec<&str> = cmdline + let init = cmdline .split_ascii_whitespace() - .filter(|p| p.starts_with("init=")) - .collect(); - - if init_params.len() != 1 { - bail!("Expected exactly one init param on kernel cmdline: {cmdline}") - } - - let init = init_params - .first() - .and_then(|s| s.split('=').next_back()) - .context("Failed to extract init path from kernel cmdline: {cmdline}")?; + .filter_map(|p| p.strip_prefix("init=")) + .next_back() + .with_context(|| format!("No init= parameter on kernel cmdline: {cmdline}"))?; Ok(PathBuf::from(init)) } @@ -129,4 +115,25 @@ mod tests { Ok(()) } + + #[test] + fn test_extract_init_single() { + assert_eq!( + extract_init("root=fstab init=/nix/store/xxx-nixos/init quiet").unwrap(), + PathBuf::from("/nix/store/xxx-nixos/init") + ); + } + + #[test] + fn test_extract_init_last_wins() { + assert_eq!( + extract_init("init=/nix/store/xxx-nixos/init init=/bin/sh").unwrap(), + PathBuf::from("/bin/sh") + ); + } + + #[test] + fn test_extract_init_missing() { + assert!(extract_init("root=fstab quiet").is_err()); + } } diff --git a/pkgs/by-name/st/strace/package.nix b/pkgs/by-name/st/strace/package.nix index 86f8b0fa4c42..77345bd6a3ae 100644 --- a/pkgs/by-name/st/strace/package.nix +++ b/pkgs/by-name/st/strace/package.nix @@ -11,11 +11,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "strace"; - version = "7.0"; + version = "7.1"; src = fetchurl { url = "https://strace.io/files/${finalAttrs.version}/strace-${finalAttrs.version}.tar.xz"; - hash = "sha256-bJJBm+Py7FYLMXKKRlIhfFmGTIZCunsbN3GxsBOtB0s="; + hash = "sha256-gXQ+zypbRBhrL1A4r9yL7aflxwrtFbT7+8xuns4kSQ8="; }; separateDebugInfo = true; diff --git a/pkgs/os-specific/linux/kernel/kernels-org.json b/pkgs/os-specific/linux/kernel/kernels-org.json index 43db58a4181e..54ff5434cfe3 100644 --- a/pkgs/os-specific/linux/kernel/kernels-org.json +++ b/pkgs/os-specific/linux/kernel/kernels-org.json @@ -5,43 +5,43 @@ "lts": false }, "6.1": { - "version": "6.1.175", - "hash": "sha256:11fapr04y96p9ja6mfzm7bcd3zb4dzyw6qrh7c11bss9wjlq9s9p", + "version": "6.1.176", + "hash": "sha256:1xj4ms4gd8ghd0l0dzsyi762dgpdrmqhc3f0arrp7sa0p8npf6da", "lts": true }, "5.15": { - "version": "5.15.209", - "hash": "sha256:1d0yhbpqlkr1znahky15dfavr6dzb3wb8c15k9qqvkf2xb3pfv9l", + "version": "5.15.210", + "hash": "sha256:008a55av0x9fa3fspcz43sycik143gqxg2agcalrax2yw5ma82wi", "lts": true }, "5.10": { - "version": "5.10.258", - "hash": "sha256:1rdldzb3g33v6zvcmxafqpkjgqpp4n5qlxwb77wfd5jpzhgcnz4y", + "version": "5.10.259", + "hash": "sha256:02dn8rf9p0afkl8kbdv28ijq974zfnv8zdsqcqbmapjm19c8wpma", "lts": true }, "6.6": { - "version": "6.6.142", - "hash": "sha256:0w1bdzp9x1sqcr9xlk7dvylhs7kycghjabfgd3iv49ydfmx61xmj", + "version": "6.6.143", + "hash": "sha256:0ci9b6kjp7r2xwqifs2963l9ihk2rllk4zpl2kgzbny0r66izkns", "lts": true }, "6.12": { - "version": "6.12.93", - "hash": "sha256:18sg154hqw8l98pfim2hjm1y604h5dwn9gj3gyncas8bgjl4h9j9", + "version": "6.12.94", + "hash": "sha256:1ln83ljmc7wr1nrjjq1hp1m1vx54j7i6i15m3hqb73a1p4ra5679", "lts": true }, "6.18": { - "version": "6.18.35", - "hash": "sha256:0dpjprjzc4w44kw49jcgx1ffrm6gxn2gsnsz3hhmw4hr4a9h51pp", + "version": "6.18.36", + "hash": "sha256:0kn4r43lnd5nb5c298b30030qyaxv05s7k40n9si1j3iyk4qdazv", "lts": true }, "7.0": { - "version": "7.0.12", - "hash": "sha256:1nk5lans9qg1avmmcwyadfps43d3hyjz9a5gjyvsc77w3sjckvap", + "version": "7.0.13", + "hash": "sha256:04wrz38ldls7pv1yxa1m7p2hqn1731l93xnz93fs7b0nyz8fv09w", "lts": false }, "7.1": { - "version": "7.1", - "hash": "sha256:18344l5fv3hgsqjrjr3dgg96lll7f294qq11lg40sydygxwl87v9", + "version": "7.1.1", + "hash": "sha256:0z8x6wafxzc5vkim9jh8wpycdkk9y5bpxgsirmdpyznw84szl5aj", "lts": false } }