staging-nixos merge for 2026-01-23 (#483049)
This commit is contained in:
@@ -38,6 +38,10 @@
|
||||
|
||||
- [Dawarich](https://dawarich.app/), a self-hostable location history tracker. Available as [services.dawarich](#opt-services.dawarich.enable).
|
||||
|
||||
- [Howdy](https://github.com/boltgolt/howdy), a Windows Hello™ style facial authentication program for Linux.
|
||||
|
||||
- [linux-enable-ir-emitter](https://github.com/EmixamPP/linux-enable-ir-emitter), a tool used to set up IR cameras, used with Howdy.
|
||||
|
||||
- [udp-over-tcp](https://github.com/mullvad/udp-over-tcp), a tunnel for proxying UDP traffic over a TCP stream. Available as `services.udp-over-tcp`.
|
||||
|
||||
- [Komodo Periphery](https://github.com/moghtech/komodo), a multi-server Docker and Git deployment agent by Komodo. Available as [services.komodo-periphery](#opt-services.komodo-periphery.enable).
|
||||
@@ -52,6 +56,8 @@
|
||||
|
||||
- `services.tandoor-recipes` now uses a sub-directory for media files by default starting with `26.05`. Existing setups should move media files out of the data directory and adjust `services.tandoor-recipes.extraConfig.MEDIA_ROOT` accordingly. See [Migrating media files for pre 26.05 installations](#module-services-tandoor-recipes-migrating-media).
|
||||
|
||||
- The packages `iw` and `wirelesstools` (`iwconfig`, `iwlist`, etc.) are no longer installed implicitly if wireless networking has been enabled.
|
||||
|
||||
- `services.kubernetes.addons.dns.coredns` has been renamed to `services.kubernetes.addons.dns.corednsImage` and now expects a
|
||||
package instead of attrs. Now, by default, nixpkgs.coredns in conjunction with dockerTools.buildImage is used, instead
|
||||
of pulling the upstream container image from Docker Hub. If you want the old behavior, you can set:
|
||||
|
||||
@@ -878,6 +878,7 @@
|
||||
./services/misc/languagetool.nix
|
||||
./services/misc/leaps.nix
|
||||
./services/misc/lifecycled.nix
|
||||
./services/misc/linux-enable-ir-emitter.nix
|
||||
./services/misc/litellm.nix
|
||||
./services/misc/llama-cpp.nix
|
||||
./services/misc/local-content-share.nix
|
||||
@@ -1489,6 +1490,7 @@
|
||||
./services/security/hockeypuck.nix
|
||||
./services/security/hologram-agent.nix
|
||||
./services/security/hologram-server.nix
|
||||
./services/security/howdy
|
||||
./services/security/infnoise.nix
|
||||
./services/security/intune.nix
|
||||
./services/security/jitterentropy-rngd.nix
|
||||
|
||||
@@ -322,6 +322,28 @@ let
|
||||
'';
|
||||
};
|
||||
|
||||
howdy = {
|
||||
enable = lib.mkOption {
|
||||
default = config.security.pam.howdy.enable;
|
||||
defaultText = lib.literalExpression "config.security.pam.howdy.enable";
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Whether to enable the Howdy PAM module.
|
||||
|
||||
If set, users can be authenticated using Howdy, the Windows
|
||||
Hello™-style facial authentication service.
|
||||
'';
|
||||
};
|
||||
control = lib.mkOption {
|
||||
default = config.security.pam.howdy.control;
|
||||
defaultText = lib.literalExpression "config.security.pam.howdy.control";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
This option sets the PAM "control" used for this module.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
oathAuth = lib.mkOption {
|
||||
default = config.security.pam.oath.enable;
|
||||
defaultText = lib.literalExpression "config.security.pam.oath.enable";
|
||||
@@ -951,6 +973,12 @@ let
|
||||
control = "sufficient";
|
||||
modulePath = "${config.services.fprintd.package}/lib/security/pam_fprintd.so";
|
||||
}
|
||||
{
|
||||
name = "howdy";
|
||||
enable = cfg.howdy.enable;
|
||||
control = cfg.howdy.control;
|
||||
modulePath = "${config.services.howdy.package}/lib/security/pam_howdy.so";
|
||||
}
|
||||
]
|
||||
++
|
||||
# Modules in this block require having the password set in PAM_AUTHTOK.
|
||||
@@ -1797,6 +1825,28 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.howdy = {
|
||||
enable = lib.mkOption {
|
||||
default = config.services.howdy.enable;
|
||||
defaultText = lib.literalExpression "config.services.howdy.enable";
|
||||
type = lib.types.bool;
|
||||
description = ''
|
||||
Whether to enable the Howdy PAM module.
|
||||
|
||||
If set, users can be authenticated using Howdy, the Windows
|
||||
Hello™-style facial authentication service.
|
||||
'';
|
||||
};
|
||||
control = lib.mkOption {
|
||||
default = config.services.howdy.control;
|
||||
defaultText = lib.literalExpression "config.services.howdy.control";
|
||||
type = lib.types.str;
|
||||
description = ''
|
||||
This option sets the PAM "control" used for this module.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
security.pam.krb5 = {
|
||||
enable = lib.mkOption {
|
||||
default = config.security.krb5.enable;
|
||||
|
||||
71
nixos/modules/services/misc/linux-enable-ir-emitter.nix
Normal file
71
nixos/modules/services/misc/linux-enable-ir-emitter.nix
Normal file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.linux-enable-ir-emitter;
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.linux-enable-ir-emitter = {
|
||||
enable = lib.mkEnableOption "" // {
|
||||
description = ''
|
||||
Whether to enable IR emitter hardware. Designed to be used with the
|
||||
Howdy facial authentication. After enabling the service, configure
|
||||
the emitter with `sudo linux-enable-ir-emitter configure`.
|
||||
'';
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "linux-enable-ir-emitter" { } // {
|
||||
description = ''
|
||||
Package to use for the Linux Enable IR Emitter service.
|
||||
'';
|
||||
};
|
||||
|
||||
device = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "video2";
|
||||
description = ''
|
||||
IR camera device to depend on. For example, for `/dev/video2`
|
||||
the value would be `video2`. Find this with the command
|
||||
{command}`realpath /dev/v4l/by-path/<generated-driver-name>`.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
|
||||
# https://github.com/EmixamPP/linux-enable-ir-emitter/blob/7e3a6527ef2efccabaeefc5a93c792628325a8db/sources/systemd/linux-enable-ir-emitter.service
|
||||
systemd.services.linux-enable-ir-emitter =
|
||||
let
|
||||
targets = [
|
||||
"suspend.target"
|
||||
"sleep.target"
|
||||
"hybrid-sleep.target"
|
||||
"hibernate.target"
|
||||
"suspend-then-hibernate.target"
|
||||
];
|
||||
in
|
||||
{
|
||||
description = "Enable the infrared emitter";
|
||||
# Added to match
|
||||
# https://github.com/EmixamPP/linux-enable-ir-emitter/blob/6.1.2/boot_service/systemd/linux-enable-ir-emitter.service
|
||||
# Prevents the program fail to detect the IR camera until a service
|
||||
# restart.
|
||||
preStart = ''
|
||||
${pkgs.kmod}/bin/modprobe uvcvideo
|
||||
sleep 1
|
||||
'';
|
||||
script = "${lib.getExe cfg.package} --verbose run";
|
||||
serviceConfig.StateDirectory = "linux-enable-ir-emitter";
|
||||
serviceConfig.LogsDirectory = "linux-enable-ir-emitter";
|
||||
|
||||
wantedBy = targets ++ [ "multi-user.target" ];
|
||||
after = targets ++ [ "dev-${cfg.device}.device" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
122
nixos/modules/services/security/howdy/default.nix
Normal file
122
nixos/modules/services/security/howdy/default.nix
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
cfg = config.services.howdy;
|
||||
settingsType = pkgs.formats.ini { };
|
||||
|
||||
default_config = {
|
||||
core = {
|
||||
detection_notice = false;
|
||||
timeout_notice = true;
|
||||
no_confirmation = false;
|
||||
suppress_unknown = false;
|
||||
abort_if_ssh = true;
|
||||
abort_if_lid_closed = true;
|
||||
disabled = false;
|
||||
use_cnn = false;
|
||||
workaround = "off";
|
||||
};
|
||||
|
||||
video = {
|
||||
certainty = 3.5;
|
||||
timeout = 4;
|
||||
device_path = "/dev/video2";
|
||||
warn_no_device = true;
|
||||
max_height = 320;
|
||||
frame_width = -1;
|
||||
frame_height = -1;
|
||||
dark_threshold = 60;
|
||||
recording_plugin = "opencv";
|
||||
device_format = "v4l2";
|
||||
force_mjpeg = false;
|
||||
exposure = -1;
|
||||
device_fps = -1;
|
||||
rotate = 0;
|
||||
};
|
||||
|
||||
snapshots = {
|
||||
save_failed = false;
|
||||
save_successful = false;
|
||||
};
|
||||
|
||||
rubberstamps = {
|
||||
enabled = false;
|
||||
stamp_rules = "nod 5s failsafe min_distance=12";
|
||||
};
|
||||
|
||||
debug = {
|
||||
end_report = false;
|
||||
verbose_stamps = false;
|
||||
gtk_stdout = false;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.howdy = {
|
||||
enable = lib.mkEnableOption "" // {
|
||||
description = ''
|
||||
Whether to enable Howdy and its PAM module for face recognition. See
|
||||
`services.linux-enable-ir-emitter` for enabling the IR emitter support.
|
||||
|
||||
::: {.caution}
|
||||
Howdy is not a safe alternative to unlocking with your password. It
|
||||
can be fooled using a well-printed photo.
|
||||
|
||||
Do **not** use it as the sole authentication method for your system.
|
||||
:::
|
||||
|
||||
::: {.note}
|
||||
By default, the {option}`config.services.howdy.control` option is set
|
||||
to `"required"`, meaning it will act as a second-factor authentication
|
||||
in most services. To change this, set the option to `"sufficient"`.
|
||||
:::
|
||||
'';
|
||||
};
|
||||
|
||||
package = lib.mkPackageOption pkgs "howdy" { };
|
||||
|
||||
control = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "required";
|
||||
description = ''
|
||||
PAM control flag to use for Howdy.
|
||||
|
||||
Sets the {option}`security.pam.howdy.control` option.
|
||||
|
||||
Refer to {manpage}`pam.conf(5)` for options.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
inherit (settingsType) type;
|
||||
default = default_config;
|
||||
description = ''
|
||||
Howdy configuration file. Refer to
|
||||
<https://github.com/boltgolt/howdy/blob/d3ab99382f88f043d15f15c1450ab69433892a1c/howdy/src/config.ini>
|
||||
for options.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkMerge [
|
||||
(lib.mkIf cfg.enable {
|
||||
environment.systemPackages = [ cfg.package ];
|
||||
environment.etc."howdy/config.ini".source = settingsType.generate "howdy-config.ini" cfg.settings;
|
||||
assertions = [
|
||||
{
|
||||
assertion = !(builtins.elem "v4l2loopback" config.boot.kernelModules);
|
||||
message = "Adding 'v4l2loopback' to `boot.kernelModules` causes Howdy to no longer work. Consider adding 'v4l2loopback' to `boot.extraModulePackages` instead.";
|
||||
}
|
||||
];
|
||||
})
|
||||
{
|
||||
services.howdy.settings = lib.mapAttrsRecursive (name: lib.mkDefault) default_config;
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -49,20 +49,22 @@ in
|
||||
config =
|
||||
let
|
||||
activationScript = lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
(pkgs.writeShellApplication {
|
||||
name = "activate";
|
||||
text = config.system.activationScripts.script;
|
||||
checkPhase = "";
|
||||
bashOptions = [ ];
|
||||
}
|
||||
}).overrideAttrs
|
||||
{ preferLocalBuild = true; }
|
||||
);
|
||||
dryActivationScript = lib.getExe (
|
||||
pkgs.writeShellApplication {
|
||||
(pkgs.writeShellApplication {
|
||||
name = "dry-activate";
|
||||
text = config.system.dryActivationScript;
|
||||
checkPhase = "";
|
||||
bashOptions = [ ];
|
||||
}
|
||||
}).overrideAttrs
|
||||
{ preferLocalBuild = true; }
|
||||
);
|
||||
in
|
||||
{
|
||||
|
||||
@@ -185,7 +185,7 @@ in
|
||||
# If networkmanager is enabled, ask it to interface with resolved.
|
||||
networking.networkmanager.dns = "systemd-resolved";
|
||||
|
||||
networking.resolvconf.package = pkgs.systemd;
|
||||
networking.resolvconf.package = config.systemd.package;
|
||||
|
||||
nix.firewall.extraNftablesRules = [
|
||||
"ip daddr { 127.0.0.53, 127.0.0.54 } udp dport 53 accept comment \"systemd-resolved listening IPs\""
|
||||
|
||||
@@ -213,6 +213,12 @@ let
|
||||
# Capsule support
|
||||
"capsule@.service"
|
||||
"capsule.slice"
|
||||
|
||||
# Factory reset
|
||||
"factory-reset.target"
|
||||
"systemd-factory-reset-request.service"
|
||||
"systemd-factory-reset-reboot.service"
|
||||
"systemd-tpm2-clear.service"
|
||||
]
|
||||
++ cfg.additionalUpstreamSystemUnits;
|
||||
|
||||
@@ -222,6 +228,7 @@ let
|
||||
"local-fs.target.wants"
|
||||
"multi-user.target.wants"
|
||||
"timers.target.wants"
|
||||
"factory-reset.target.wants"
|
||||
];
|
||||
|
||||
proxy_env = config.networking.proxy.envVars;
|
||||
|
||||
@@ -65,6 +65,8 @@ let
|
||||
"syslog.socket"
|
||||
"systemd-ask-password-console.path"
|
||||
"systemd-ask-password-console.service"
|
||||
"systemd-factory-reset-complete.service"
|
||||
"factory-reset-now.target"
|
||||
"systemd-fsck@.service"
|
||||
"systemd-halt.service"
|
||||
"systemd-hibernate-resume.service"
|
||||
@@ -555,6 +557,7 @@ in
|
||||
"${cfg.package}/lib/systemd/systemd-sysctl"
|
||||
"${cfg.package}/lib/systemd/systemd-bsod"
|
||||
"${cfg.package}/lib/systemd/systemd-sysroot-fstab-check"
|
||||
"${cfg.package}/lib/systemd/systemd-factory-reset"
|
||||
|
||||
# generators
|
||||
"${cfg.package}/lib/systemd/system-generators/systemd-debug-generator"
|
||||
@@ -562,6 +565,7 @@ in
|
||||
"${cfg.package}/lib/systemd/system-generators/systemd-gpt-auto-generator"
|
||||
"${cfg.package}/lib/systemd/system-generators/systemd-hibernate-resume-generator"
|
||||
"${cfg.package}/lib/systemd/system-generators/systemd-run-generator"
|
||||
"${cfg.package}/lib/systemd/system-generators/systemd-factory-reset-generator"
|
||||
|
||||
# utilities needed by systemd
|
||||
"${cfg.package.util-linux}/bin/mount"
|
||||
|
||||
@@ -1770,13 +1770,9 @@ in
|
||||
|
||||
environment.corePackages = [
|
||||
pkgs.host
|
||||
pkgs.hostname-debian
|
||||
pkgs.hostname
|
||||
pkgs.iproute2
|
||||
pkgs.iputils
|
||||
]
|
||||
++ optionals config.networking.wireless.enable [
|
||||
pkgs.wirelesstools # FIXME: obsolete?
|
||||
pkgs.iw
|
||||
pkgs.iputils # ping
|
||||
]
|
||||
++ bridgeStp;
|
||||
|
||||
|
||||
@@ -1107,6 +1107,9 @@ in
|
||||
nixos-rebuild-specialisations = runTestOn [ "x86_64-linux" ] {
|
||||
imports = [ ./nixos-rebuild-specialisations.nix ];
|
||||
};
|
||||
nixos-rebuild-store-path = runTestOn [ "x86_64-linux" ] {
|
||||
imports = [ ./nixos-rebuild-store-path.nix ];
|
||||
};
|
||||
nixos-rebuild-target-host = runTest {
|
||||
imports = [ ./nixos-rebuild-target-host.nix ];
|
||||
};
|
||||
|
||||
101
nixos/tests/nixos-rebuild-store-path.nix
Normal file
101
nixos/tests/nixos-rebuild-store-path.nix
Normal file
@@ -0,0 +1,101 @@
|
||||
{ hostPkgs, ... }:
|
||||
{
|
||||
name = "nixos-rebuild-store-path";
|
||||
|
||||
# TODO: remove overlay from nixos/modules/profiles/installation-device.nix
|
||||
# make it a _small package instead, then remove pkgsReadOnly = false;.
|
||||
node.pkgsReadOnly = false;
|
||||
|
||||
nodes = {
|
||||
machine =
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
imports = [
|
||||
../modules/profiles/installation-device.nix
|
||||
../modules/profiles/base.nix
|
||||
];
|
||||
|
||||
nix.settings = {
|
||||
substituters = lib.mkForce [ ];
|
||||
hashed-mirrors = null;
|
||||
connect-timeout = 1;
|
||||
};
|
||||
|
||||
system.includeBuildDependencies = true;
|
||||
|
||||
system.extraDependencies = [
|
||||
# Not part of the initial build apparently?
|
||||
pkgs.grub2
|
||||
];
|
||||
|
||||
system.switch.enable = true;
|
||||
|
||||
virtualisation = {
|
||||
cores = 2;
|
||||
memorySize = 4096;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
let
|
||||
configFile =
|
||||
hostname:
|
||||
hostPkgs.writeText "configuration.nix" # nix
|
||||
''
|
||||
{ lib, pkgs, ... }: {
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
<nixpkgs/nixos/modules/testing/test-instrumentation.nix>
|
||||
];
|
||||
|
||||
boot.loader.grub = {
|
||||
enable = true;
|
||||
device = "/dev/vda";
|
||||
forceInstall = true;
|
||||
};
|
||||
|
||||
documentation.enable = false;
|
||||
|
||||
networking.hostName = "${hostname}";
|
||||
}
|
||||
'';
|
||||
|
||||
in
|
||||
# python
|
||||
''
|
||||
machine.start()
|
||||
machine.succeed("udevadm settle")
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
|
||||
machine.succeed("nixos-generate-config")
|
||||
|
||||
with subtest("Build configuration without switching"):
|
||||
machine.copy_from_host(
|
||||
"${configFile "store-path-test"}",
|
||||
"/etc/nixos/configuration.nix",
|
||||
)
|
||||
store_path = machine.succeed("nix-build '<nixpkgs/nixos>' -A system --no-out-link").strip()
|
||||
machine.succeed(f"test -f {store_path}/nixos-version")
|
||||
|
||||
with subtest("Switch using --store-path"):
|
||||
machine.succeed(f"nixos-rebuild switch --store-path {store_path}")
|
||||
hostname = machine.succeed("cat /etc/hostname").strip()
|
||||
assert hostname == "store-path-test", f"Expected hostname 'store-path-test', got '{hostname}'"
|
||||
|
||||
with subtest("Test using --store-path"):
|
||||
machine.copy_from_host(
|
||||
"${configFile "store-path-test-2"}",
|
||||
"/etc/nixos/configuration.nix",
|
||||
)
|
||||
store_path_2 = machine.succeed("nix-build '<nixpkgs/nixos>' -A system --no-out-link").strip()
|
||||
machine.succeed(f"nixos-rebuild test --store-path {store_path_2}")
|
||||
hostname = machine.succeed("cat /etc/hostname").strip()
|
||||
assert hostname == "store-path-test-2", f"Expected hostname 'store-path-test-2', got '{hostname}'"
|
||||
|
||||
with subtest("Ensure --store-path rejects invalid combinations"):
|
||||
machine.fail(f"nixos-rebuild switch --store-path {store_path} --rollback")
|
||||
machine.fail(f"nixos-rebuild switch --store-path {store_path} --flake .")
|
||||
machine.fail(f"nixos-rebuild build --store-path {store_path}")
|
||||
'';
|
||||
}
|
||||
@@ -277,4 +277,106 @@ in
|
||||
assert "Adding new partition 2 to partition table." in systemd_repart_logs
|
||||
'';
|
||||
};
|
||||
|
||||
factory-reset = makeTest {
|
||||
name = "systemd-repart-factory-reset";
|
||||
meta.maintainers = with maintainers; [ willibutz ];
|
||||
|
||||
nodes.machine =
|
||||
{ pkgs, lib, ... }:
|
||||
{
|
||||
imports = [ common ];
|
||||
|
||||
virtualisation = {
|
||||
useEFIBoot = true;
|
||||
tpm.enable = true;
|
||||
efi.OVMF = pkgs.OVMFFull;
|
||||
useDefaultFilesystems = false;
|
||||
fileSystems = {
|
||||
"/state" = {
|
||||
device = "/dev/mapper/state";
|
||||
fsType = "ext4";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
boot = {
|
||||
loader.systemd-boot.enable = true;
|
||||
|
||||
initrd = {
|
||||
systemd = {
|
||||
enable = true;
|
||||
# avoids reaching cryptsetup.target before recreation of the
|
||||
# "state" volume completed, during the factory reset
|
||||
services.systemd-repart.before = [
|
||||
"systemd-cryptsetup@state.service"
|
||||
];
|
||||
repart = {
|
||||
enable = true;
|
||||
extraArgs = [
|
||||
"--tpm2-pcrs=platform-code"
|
||||
];
|
||||
};
|
||||
};
|
||||
luks.devices = lib.mkVMOverride {
|
||||
state = {
|
||||
device = "/dev/disk/by-partlabel/state";
|
||||
crypttabExtraOpts = [ "tpm2-device=auto" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.repart.partitions = {
|
||||
"10-esp".Type = "esp";
|
||||
"20-root".Type = "linux-generic";
|
||||
"30-state" = {
|
||||
Type = "linux-generic";
|
||||
Label = "state";
|
||||
Format = "ext4";
|
||||
Encrypt = "tpm2";
|
||||
SizeMinBytes = "64M";
|
||||
SizeMaxBytes = "64M";
|
||||
FactoryReset = true;
|
||||
};
|
||||
};
|
||||
|
||||
# doesn't actually reboot through the service because otherwise the test
|
||||
# instrumentation becomes very unreliable, instead uses machine.reboot()
|
||||
systemd.services.systemd-factory-reset-reboot.enable = false;
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
# python
|
||||
''
|
||||
${useDiskImage {
|
||||
inherit (nodes) machine;
|
||||
sizeDiff = "+64M";
|
||||
}}
|
||||
|
||||
machine.start(allow_reboot=True)
|
||||
machine.wait_for_unit("default.target")
|
||||
|
||||
first_uuid = machine.succeed("blkid -s UUID -o value /dev/disk/by-label/state")
|
||||
|
||||
machine.succeed("mountpoint /state")
|
||||
machine.succeed("touch /state/foo")
|
||||
|
||||
with subtest("factory reset requested through target"):
|
||||
machine.systemctl("start factory-reset.target")
|
||||
|
||||
# reboot manually to keep control over test vm
|
||||
machine.reboot()
|
||||
machine.wait_for_unit("default.target")
|
||||
|
||||
with subtest("state partition recreated and empty after reset"):
|
||||
second_uuid = machine.succeed("blkid -s UUID -o value /dev/disk/by-label/state")
|
||||
t.assertNotEqual(first_uuid, second_uuid)
|
||||
|
||||
machine.succeed("mountpoint /state")
|
||||
machine.fail("test -e /state/foo")
|
||||
'';
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -79,6 +79,13 @@ stdenv.mkDerivation rec {
|
||||
|
||||
makeFlags = [ "udevruledir=$(out)/lib/udev/rules.d" ];
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
"dev"
|
||||
"man"
|
||||
"lib"
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
doInstallCheck = true;
|
||||
|
||||
166
pkgs/by-name/ho/howdy/package.nix
Normal file
166
pkgs/by-name/ho/howdy/package.nix
Normal file
@@ -0,0 +1,166 @@
|
||||
{
|
||||
stdenv,
|
||||
lib,
|
||||
copyDesktopItems,
|
||||
fetchFromGitHub,
|
||||
fetchpatch,
|
||||
fetchurl,
|
||||
bzip2,
|
||||
gobject-introspection,
|
||||
imagemagick,
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
wrapGAppsHook3,
|
||||
makeDesktopItem,
|
||||
makeWrapper,
|
||||
fmt,
|
||||
gettext,
|
||||
gtk3,
|
||||
inih,
|
||||
libevdev,
|
||||
pam,
|
||||
python3,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "howdy";
|
||||
version = "3.0.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "boltgolt";
|
||||
repo = "howdy";
|
||||
# The 3.0.0 release does not have a corresponding tag yet.
|
||||
# The maintainer was asked to provide one here https://github.com/boltgolt/howdy/pull/1023#issuecomment-3722339500
|
||||
rev = "d3ab99382f88f043d15f15c1450ab69433892a1c";
|
||||
hash = "sha256-Xd/uScMnX1GMwLD5GYSbE2CwEtzrhwHocsv0ESKV8IM=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Allows specifying whether to install config file. Paired with the
|
||||
# `install_config` meson option. Needed to disallow installing the config
|
||||
# file in `/etc/howdy`, as it is not allowed by the Nix sandbox. A NixOS
|
||||
# module creates `/etc/howdy` and the config file of course.
|
||||
# PR sent upstream https://github.com/boltgolt/howdy/pull/1050
|
||||
(fetchpatch {
|
||||
url = "https://github.com/boltgolt/howdy/commit/1f3b83e2db5a8dfd9c7c88706ecce033e154060a.patch";
|
||||
hash = "sha256-OIN8A4q0zjtMOMzZgBqrKy2qOD8BDPB+euG6zerFbCE=";
|
||||
})
|
||||
|
||||
# Fix python path for howdy-gtk. Uses python from meson option instead of
|
||||
# the system installation (which is not defined in this package).
|
||||
# PR sent upstream https://github.com/boltgolt/howdy/pull/1049
|
||||
(fetchpatch {
|
||||
url = "https://github.com/boltgolt/howdy/commit/b056724f84361dc6150554e7a806152af032c54b.patch";
|
||||
hash = "sha256-ZOb+QmWagKWtyXI0Xg00tnw8UP8uDWw7wb4Fwjy3VeE=";
|
||||
})
|
||||
];
|
||||
|
||||
mesonFlags = lib.concatLists [
|
||||
(lib.mapAttrsToList lib.mesonOption {
|
||||
config_dir = "/etc/howdy";
|
||||
python_path = "${finalAttrs.finalPackage.pythonEnv}/bin/python";
|
||||
user_models_dir = "/var/lib/howdy/models";
|
||||
})
|
||||
(lib.mapAttrsToList lib.mesonBool {
|
||||
install_config = false;
|
||||
with_polkit = true;
|
||||
})
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
bzip2
|
||||
copyDesktopItems
|
||||
gobject-introspection
|
||||
imagemagick
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
wrapGAppsHook3
|
||||
makeWrapper
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
fmt
|
||||
gettext
|
||||
gtk3
|
||||
inih
|
||||
libevdev
|
||||
pam
|
||||
];
|
||||
|
||||
desktopItems = [
|
||||
(makeDesktopItem {
|
||||
name = "howdy";
|
||||
exec = "howdy-gtk";
|
||||
icon = "howdy";
|
||||
comment = "Howdy facial authentication";
|
||||
desktopName = "Howdy";
|
||||
genericName = "Facial authentication";
|
||||
categories = [
|
||||
"System"
|
||||
"Security"
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
postInstall = ''
|
||||
# install dlib data
|
||||
rm -rf $out/share/dlib-data/*
|
||||
${lib.concatStrings (
|
||||
lib.mapAttrsToList (n: v: ''
|
||||
bzip2 -dc ${v} > $out/share/dlib-data/${n}.dat
|
||||
'') finalAttrs.finalPackage.passthru.dlibModels
|
||||
)}
|
||||
|
||||
for size in 16 24 32 48 64 128 256 512; do
|
||||
mkdir -p $out/share/icons/hicolor/"$size"x"$size"/apps
|
||||
magick -background none "$out/share/howdy-gtk/logo.png" -resize "$size"x"$size" $out/share/icons/hicolor/"$size"x"$size"/apps/howdy.png
|
||||
done
|
||||
|
||||
chmod +x $out/lib/howdy-gtk/init.py
|
||||
'';
|
||||
|
||||
pythonEnv = python3.buildEnv.override {
|
||||
extraLibs = lib.attrVals finalAttrs.finalPackage.passthru.pythonDeps python3.pkgs;
|
||||
makeWrapperArgs = [
|
||||
"--set"
|
||||
"OMP_NUM_THREADS"
|
||||
"1"
|
||||
];
|
||||
};
|
||||
|
||||
passthru = {
|
||||
pythonDeps = [
|
||||
"dlib"
|
||||
"elevate"
|
||||
"face-recognition"
|
||||
"keyboard"
|
||||
"opencv4Full"
|
||||
"pycairo"
|
||||
"pygobject3"
|
||||
];
|
||||
dlibModels = lib.mapAttrs (
|
||||
name: hash:
|
||||
fetchurl {
|
||||
name = "howdy-${name}.dat";
|
||||
url = "https://github.com/davisking/dlib-models/raw/daf943f7819a3dda8aec4276754ef918dc26491f/${name}.dat.bz2";
|
||||
inherit hash;
|
||||
}
|
||||
) finalAttrs.finalPackage.passthru.dlibModelsHashes;
|
||||
dlibModelsHashes = {
|
||||
dlib_face_recognition_resnet_model_v1 = "sha256-q7H2EEHkNEZYVc6Bwr1UboMNKLy+2NJ/++W7QIsRVTo=";
|
||||
mmod_human_face_detector = "sha256-256eQPCSwRjV6z5kOTWyFoOBcHk1WVFVQcVqK1DZ/IQ=";
|
||||
shape_predictor_5_face_landmarks = "sha256-bnh7vr9cnv23k/bNHwIyMMRBMwZgXyTymfEoaflapHI=";
|
||||
};
|
||||
};
|
||||
|
||||
meta = {
|
||||
description = "Windows Hello™ style facial authentication for Linux";
|
||||
homepage = "https://github.com/boltgolt/howdy";
|
||||
license = lib.licenses.mit;
|
||||
mainProgram = "howdy";
|
||||
platforms = lib.platforms.linux;
|
||||
maintainers = with lib.maintainers; [ fufexan ];
|
||||
};
|
||||
})
|
||||
62
pkgs/by-name/li/linux-enable-ir-emitter/package.nix
Normal file
62
pkgs/by-name/li/linux-enable-ir-emitter/package.nix
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
makeWrapper,
|
||||
fetchFromGitHub,
|
||||
meson,
|
||||
ninja,
|
||||
pkg-config,
|
||||
argparse,
|
||||
gtk3,
|
||||
python3,
|
||||
spdlog,
|
||||
usbutils,
|
||||
yaml-cpp,
|
||||
}:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "linux-enable-ir-emitter";
|
||||
version = "6.1.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "EmixamPP";
|
||||
repo = "linux-enable-ir-emitter";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-wSmWebX4H3Hj8bbFoVMq3DY3i/nKkQaeu3mXX0o6IaY=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
makeWrapper
|
||||
meson
|
||||
ninja
|
||||
pkg-config
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
argparse
|
||||
gtk3
|
||||
spdlog
|
||||
usbutils
|
||||
yaml-cpp
|
||||
python3.pkgs.opencv4Full
|
||||
];
|
||||
|
||||
mesonFlags = lib.lists.flatten [
|
||||
(lib.attrsets.mapAttrsToList lib.strings.mesonOption {
|
||||
config_dir = "/var/lib";
|
||||
localstatedir = "/var";
|
||||
})
|
||||
(lib.attrsets.mapAttrsToList lib.strings.mesonBool {
|
||||
create_config_dir = false;
|
||||
create_log_dir = false;
|
||||
})
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "Provides support for infrared cameras that are not directly enabled out-of-the box";
|
||||
homepage = "https://github.com/EmixamPP/linux-enable-ir-emitter";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ fufexan ];
|
||||
mainProgram = "linux-enable-ir-emitter";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
})
|
||||
@@ -3,6 +3,7 @@
|
||||
stdenv,
|
||||
util-linux,
|
||||
coreutils,
|
||||
fetchgit,
|
||||
fetchurl,
|
||||
groff,
|
||||
system-sendmail,
|
||||
@@ -16,9 +17,10 @@ stdenv.mkDerivation rec {
|
||||
pname = "mdadm";
|
||||
version = "4.4";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://kernel/linux/utils/raid/mdadm/mdadm-${version}.tar.xz";
|
||||
sha256 = "sha256-m0iPNe0VPfmZJLX+Qe7TgOhRLejxihGGKMrN1oGx1XM=";
|
||||
src = fetchgit {
|
||||
url = "https://git.kernel.org/pub/scm/utils/mdadm/mdadm.git";
|
||||
tag = "mdadm-${version}";
|
||||
hash = "sha256-jGmc8fkJM0V9J7V7tQPXSF/WD0kzyEAloBAwaAFenS0=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
installShellFiles,
|
||||
}:
|
||||
let
|
||||
version = "0.5.1";
|
||||
version = "0.5.2";
|
||||
in
|
||||
rustPlatform.buildRustPackage rec {
|
||||
inherit version;
|
||||
@@ -18,10 +18,10 @@ rustPlatform.buildRustPackage rec {
|
||||
owner = "rust-lang";
|
||||
repo = "mdBook";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-t7Qou3H6dlO97puWQGkPlyb0jjpGoYCrz041iZWWL/s=";
|
||||
hash = "sha256-gyjD47ZR9o2lIxipzesyJ6mxb9J9W+WS77TNWhKHP6U=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-bJr0u025syrP/LGgIbXD0mRvQrvnnOntiaAfr/9tQ90=";
|
||||
cargoHash = "sha256-230KljOUSrDy8QCQki7jvJvdAsjVlUEjKDNVyTF4tWs=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
|
||||
@@ -43,7 +43,9 @@ stdenv.mkDerivation rec {
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
"doc"
|
||||
"info"
|
||||
"man"
|
||||
];
|
||||
|
||||
configureFlags = [
|
||||
|
||||
@@ -21,7 +21,7 @@ nixos-rebuild - reconfigure a NixOS machine
|
||||
_nixos-rebuild_ \[--verbose] [--quiet] [--max-jobs MAX_JOBS] [--cores CORES] [--log-format LOG_FORMAT] [--keep-going] [--keep-failed] [--fallback] [--repair] [--option OPTION OPTION] [--builders BUILDERS] [--include INCLUDE]++
|
||||
\[--print-build-logs] [--show-trace] [--accept-flake-config] [--refresh] [--impure] [--offline] [--no-net] [--recreate-lock-file] [--no-update-lock-file] [--no-write-lock-file] [--no-registries] [--commit-lock-file]++
|
||||
\[--update-input UPDATE_INPUT] [--override-input OVERRIDE_INPUT OVERRIDE_INPUT] [--no-build-output] [--use-substitutes] [--help] [--debug] [--file FILE] [--attr ATTR] [--flake [FLAKE]] [--no-flake] [--install-bootloader]++
|
||||
\[--profile-name PROFILE_NAME] [--specialisation SPECIALISATION] [--rollback] [--upgrade] [--upgrade-all] [--json] [--ask-sudo-password] [--sudo] [--no-reexec]++
|
||||
\[--profile-name PROFILE_NAME] [--specialisation SPECIALISATION] [--rollback] [--store-path STORE_PATH] [--upgrade] [--upgrade-all] [--json] [--ask-sudo-password] [--sudo] [--no-reexec]++
|
||||
\[--build-host BUILD_HOST] [--target-host TARGET_HOST] [--no-build-nix] [--image-variant IMAGE_VARIANT]++
|
||||
\[{switch,boot,test,build,edit,repl,dry-build,dry-run,dry-activate,build-image,build-vm,build-vm-with-bootloader,list-generations}]
|
||||
|
||||
@@ -182,6 +182,20 @@ It must be one of the following:
|
||||
(The previous configuration is defined as the one before the “current”
|
||||
generation of the Nix profile _/nix/var/nix/profiles/system_.)
|
||||
|
||||
*--store-path* _path_
|
||||
Use a pre-built NixOS system store path at _path_ instead of evaluating
|
||||
and building from the configuration. This skips the evaluation and build
|
||||
phases entirely. The path must be a valid NixOS system closure
|
||||
(containing _nixos-version_ and _bin/switch-to-configuration_).
|
||||
|
||||
This is useful for deploying closures that were built elsewhere, such as
|
||||
in CI systems or on remote build machines.
|
||||
|
||||
Can only be used with *switch*, *boot*, *test*, and *dry-activate*
|
||||
actions. Mutually exclusive with *--rollback*, *--flake*, *--file*, and
|
||||
*--attr*. The *--build-host* option is ignored when *--store-path* is
|
||||
specified.
|
||||
|
||||
*--builders* _builder-spec_
|
||||
Allow ad-hoc remote builders for building the new system. This requires
|
||||
the user executing *nixos-rebuild* (usually root) to be configured as a
|
||||
|
||||
@@ -98,6 +98,7 @@ python3Packages.buildPythonApplication rec {
|
||||
# FIXME: this test is disabled since it times out in @ofborg
|
||||
# nixos-rebuild-install-bootloader
|
||||
nixos-rebuild-specialisations
|
||||
nixos-rebuild-store-path
|
||||
nixos-rebuild-target-host
|
||||
;
|
||||
repl = callPackage ./tests/repl.nix { };
|
||||
|
||||
@@ -136,6 +136,11 @@ def get_parser() -> tuple[argparse.ArgumentParser, dict[str, argparse.ArgumentPa
|
||||
action="store_true",
|
||||
help="Roll back to the previous configuration",
|
||||
)
|
||||
main_parser.add_argument(
|
||||
"--store-path",
|
||||
metavar="PATH",
|
||||
help="Use a pre-built NixOS system store path instead of building",
|
||||
)
|
||||
main_parser.add_argument(
|
||||
"--upgrade",
|
||||
action="store_true",
|
||||
@@ -269,6 +274,22 @@ def parse_args(
|
||||
if args.flake and (args.file or args.attr):
|
||||
parser.error("--flake cannot be used with --file or --attr")
|
||||
|
||||
if args.store_path:
|
||||
if args.rollback:
|
||||
parser.error("--store-path and --rollback are mutually exclusive")
|
||||
if args.flake or args.file or args.attr:
|
||||
parser.error("--store-path cannot be used with --flake, --file, or --attr")
|
||||
if args.action not in (
|
||||
Action.SWITCH.value,
|
||||
Action.BOOT.value,
|
||||
Action.TEST.value,
|
||||
Action.DRY_ACTIVATE.value,
|
||||
):
|
||||
parser.error(f"--store-path cannot be used with '{args.action}'")
|
||||
if args.flake is None:
|
||||
# Disable flake auto-detection since we're using a pre-built store path
|
||||
args.flake = False
|
||||
|
||||
return args, grouped_nix_args
|
||||
|
||||
|
||||
@@ -297,7 +318,7 @@ def execute(argv: list[str]) -> None:
|
||||
build_attr = BuildAttr.from_arg(args.attr, args.file)
|
||||
flake = Flake.from_arg(args.flake, target_host)
|
||||
|
||||
if can_run and not flake:
|
||||
if can_run and not flake and not args.store_path:
|
||||
services.write_version_suffix(grouped_nix_args)
|
||||
|
||||
match action:
|
||||
|
||||
@@ -224,7 +224,7 @@ def copy_closure(
|
||||
)
|
||||
|
||||
match (to_host, from_host):
|
||||
case (None, None):
|
||||
case (x, y) if x == y:
|
||||
return
|
||||
case (Remote(_) as host, None) | (None, Remote(_) as host):
|
||||
nix_copy_closure(host, to=bool(to_host))
|
||||
|
||||
@@ -290,7 +290,14 @@ def build_and_activate_system(
|
||||
grouped_nix_args=grouped_nix_args,
|
||||
)
|
||||
|
||||
if args.rollback:
|
||||
if args.store_path:
|
||||
path_to_config = Path(args.store_path)
|
||||
nix.copy_closure(
|
||||
path_to_config,
|
||||
to_host=target_host,
|
||||
copy_flags=grouped_nix_args.copy_flags,
|
||||
)
|
||||
elif args.rollback:
|
||||
path_to_config = _rollback_system(
|
||||
action=action,
|
||||
args=args,
|
||||
|
||||
@@ -34,6 +34,30 @@ def test_parse_args() -> None:
|
||||
nr.parse_args(["nixos-rebuild", "edit", "--attr", "attr"])
|
||||
assert e.value.code == 2
|
||||
|
||||
# --store-path validation tests
|
||||
with pytest.raises(SystemExit) as e:
|
||||
nr.parse_args(
|
||||
["nixos-rebuild", "switch", "--store-path", "/nix/store/foo", "--rollback"]
|
||||
)
|
||||
assert e.value.code == 2
|
||||
|
||||
with pytest.raises(SystemExit) as e:
|
||||
nr.parse_args(
|
||||
["nixos-rebuild", "switch", "--store-path", "/nix/store/foo", "--flake"]
|
||||
)
|
||||
assert e.value.code == 2
|
||||
|
||||
with pytest.raises(SystemExit) as e:
|
||||
nr.parse_args(["nixos-rebuild", "build", "--store-path", "/nix/store/foo"])
|
||||
assert e.value.code == 2
|
||||
|
||||
# --store-path should disable flake auto-detection
|
||||
r_store_path, _ = nr.parse_args(
|
||||
["nixos-rebuild", "switch", "--store-path", "/nix/store/foo"]
|
||||
)
|
||||
assert r_store_path.flake is False
|
||||
assert r_store_path.store_path == "/nix/store/foo"
|
||||
|
||||
r1, g1 = nr.parse_args(
|
||||
[
|
||||
"nixos-rebuild",
|
||||
@@ -1214,3 +1238,163 @@ def test_execute_test_rollback(
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@patch.dict(
|
||||
os.environ,
|
||||
{"NIXOS_REBUILD_I_UNDERSTAND_THE_CONSEQUENCES_PLEASE_BREAK_MY_SYSTEM": "1"},
|
||||
clear=True,
|
||||
)
|
||||
@patch("subprocess.run", autospec=True)
|
||||
def test_execute_switch_store_path(mock_run: Mock, tmp_path: Path) -> None:
|
||||
config_path = tmp_path / "test-system"
|
||||
config_path.mkdir()
|
||||
|
||||
mock_run.return_value = CompletedProcess([], 0)
|
||||
|
||||
nr.execute(
|
||||
[
|
||||
"nixos-rebuild",
|
||||
"switch",
|
||||
"--store-path",
|
||||
str(config_path),
|
||||
"--no-reexec",
|
||||
]
|
||||
)
|
||||
|
||||
# --store-path skips build and write_version_suffix, so only activation calls
|
||||
assert mock_run.call_count == 3
|
||||
mock_run.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
[
|
||||
"nix-env",
|
||||
"-p",
|
||||
Path("/nix/var/nix/profiles/system"),
|
||||
"--set",
|
||||
config_path,
|
||||
],
|
||||
check=True,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
call(
|
||||
["test", "-d", "/run/systemd/system"],
|
||||
check=False,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
call(
|
||||
[
|
||||
*nr.nix.SWITCH_TO_CONFIGURATION_CMD_PREFIX,
|
||||
config_path / "bin/switch-to-configuration",
|
||||
"switch",
|
||||
],
|
||||
check=True,
|
||||
**(
|
||||
DEFAULT_RUN_KWARGS
|
||||
| {
|
||||
"env": {
|
||||
"NIXOS_INSTALL_BOOTLOADER": "0",
|
||||
"NIXOS_REBUILD_I_UNDERSTAND_THE_CONSEQUENCES_PLEASE_BREAK_MY_SYSTEM": "1",
|
||||
}
|
||||
}
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@patch.dict(os.environ, {}, clear=True)
|
||||
@patch("subprocess.run", autospec=True)
|
||||
@patch(get_qualified_name(nr.services.cleanup_ssh), autospec=True)
|
||||
def test_execute_switch_store_path_target_host(
|
||||
mock_cleanup_ssh: Mock,
|
||||
mock_run: Mock,
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
config_path = tmp_path / "test-system"
|
||||
config_path.mkdir()
|
||||
|
||||
mock_run.return_value = CompletedProcess([], 0)
|
||||
|
||||
nr.execute(
|
||||
[
|
||||
"nixos-rebuild",
|
||||
"switch",
|
||||
"--store-path",
|
||||
str(config_path),
|
||||
"--target-host",
|
||||
"user@remote-host",
|
||||
"--sudo",
|
||||
"--no-reexec",
|
||||
]
|
||||
)
|
||||
|
||||
# --store-path skips build and write_version_suffix, so only copy/activation calls
|
||||
assert mock_run.call_count == 5
|
||||
mock_run.assert_has_calls(
|
||||
[
|
||||
call(
|
||||
["nix-copy-closure", "--to", "user@remote-host", config_path],
|
||||
check=True,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
call(
|
||||
[
|
||||
"ssh",
|
||||
*nr.process.SSH_DEFAULT_OPTS,
|
||||
"user@remote-host",
|
||||
"--",
|
||||
"test",
|
||||
"-f",
|
||||
str(config_path / "nixos-version"),
|
||||
],
|
||||
check=False,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
call(
|
||||
[
|
||||
"ssh",
|
||||
*nr.process.SSH_DEFAULT_OPTS,
|
||||
"user@remote-host",
|
||||
"--",
|
||||
"sudo",
|
||||
"nix-env",
|
||||
"-p",
|
||||
"/nix/var/nix/profiles/system",
|
||||
"--set",
|
||||
str(config_path),
|
||||
],
|
||||
check=True,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
call(
|
||||
[
|
||||
"ssh",
|
||||
*nr.process.SSH_DEFAULT_OPTS,
|
||||
"user@remote-host",
|
||||
"--",
|
||||
"test",
|
||||
"-d",
|
||||
"/run/systemd/system",
|
||||
],
|
||||
check=False,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
call(
|
||||
[
|
||||
"ssh",
|
||||
*nr.process.SSH_DEFAULT_OPTS,
|
||||
"user@remote-host",
|
||||
"--",
|
||||
"sudo",
|
||||
"env",
|
||||
"NIXOS_INSTALL_BOOTLOADER=0",
|
||||
*nr.nix.SWITCH_TO_CONFIGURATION_CMD_PREFIX,
|
||||
str(config_path / "bin/switch-to-configuration"),
|
||||
"switch",
|
||||
],
|
||||
check=True,
|
||||
**DEFAULT_RUN_KWARGS,
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "ruff";
|
||||
version = "0.14.13";
|
||||
version = "0.14.14";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "astral-sh";
|
||||
repo = "ruff";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-ComgiY6fvM2f3Ul8kTgykyktvxEHL85X5C1Tudi5ZB4=";
|
||||
hash = "sha256-h6XYWK6NxelLCfqG0geiAj3XbcqzbeFKeFMMDsy8fm8=";
|
||||
};
|
||||
|
||||
cargoBuildFlags = [ "--package=ruff" ];
|
||||
|
||||
cargoHash = "sha256-Vd9y9VQF7d62tjHJ0ikWlvV7+KDs4q61ld9yoJWaqpY=";
|
||||
cargoHash = "sha256-H5ZaBDV0YTdExu42Dt1Bq379vJ3FtddKtdLkMW+qC78=";
|
||||
|
||||
nativeBuildInputs = [ installShellFiles ];
|
||||
|
||||
|
||||
@@ -563,10 +563,6 @@ let
|
||||
# Enable CEC over DisplayPort
|
||||
DRM_DP_CEC = whenOlder "6.10" yes;
|
||||
DRM_DISPLAY_DP_AUX_CEC = whenAtLeast "6.10" yes;
|
||||
|
||||
# Required for Nova
|
||||
# FIXME: remove after https://gitlab.freedesktop.org/drm/rust/kernel/-/commit/3d3352e73a55a4ccf110f8b3419bbe2fbfd8a030 lands
|
||||
RUST_FW_LOADER_ABSTRACTIONS = lib.mkIf withRust (whenAtLeast "6.12" yes);
|
||||
}
|
||||
//
|
||||
lib.optionalAttrs
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
"lts": true
|
||||
},
|
||||
"6.12": {
|
||||
"version": "6.12.66",
|
||||
"hash": "sha256:1bvfadb5149sh927f8cbr1rnypn7v0h6znjdrc1mmc30q2hrff5s",
|
||||
"version": "6.12.67",
|
||||
"hash": "sha256:0cn42b7pam5ssk740s3d42sp3cggl923yvs67y5fz98z5v35v00n",
|
||||
"lts": true
|
||||
},
|
||||
"6.18": {
|
||||
"version": "6.18.6",
|
||||
"hash": "sha256:06x3z649mzwwkb1hvsy0yh7j5jk9qrnwqcmwy7dx8s1ggccrf927",
|
||||
"version": "6.18.7",
|
||||
"hash": "sha256:07lgbc0w7fd9akxmazhkpjgxhd3ffwh7in2nkchhdbprbk8s89mp",
|
||||
"lts": false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user