lol

Merge pull request #263462 from nikstur/rebuildable-system

Rebuildable system & appliance

authored by

Robert Hensing and committed by
GitHub
8b385c91 6dd28903

+160 -39
+21
nixos/doc/manual/development/non-switchable-systems.section.md
··· 1 + # Non Switchable Systems {#sec-non-switchable-system} 2 + 3 + In certain systems, most notably image based appliances, updates are handled 4 + outside the system. This means that you do not need to rebuild your 5 + configuration on the system itself anymore. 6 + 7 + If you want to build such a system, you can use the `image-based-appliance` 8 + profile: 9 + 10 + ```nix 11 + { modulesPath, ... }: { 12 + imports = [ "${modulesPath}/profiles/image-based-appliance.nix" ] 13 + } 14 + ``` 15 + 16 + The most notable deviation of this profile from a standard NixOS configuration 17 + is that after building it, you cannot switch *to* the configuration anymore. 18 + The profile sets `config.system.switch.enable = false;`, which excludes 19 + `switch-to-configuration`, the central script called by `nixos-rebuild`, from 20 + your system. Removing this script makes the image lighter and slightly more 21 + secure.
+1
nixos/doc/manual/development/what-happens-during-a-system-switch.chapter.md
··· 55 55 ```{=include=} sections 56 56 unit-handling.section.md 57 57 activation-script.section.md 58 + non-switchable-systems.section.md 58 59 ```
+5
nixos/doc/manual/release-notes/rl-2311.section.md
··· 345 345 346 346 ## Other Notable Changes {#sec-release-23.11-notable-changes} 347 347 348 + - A new option `system.switch.enable` was added. By default, this is option is 349 + enabled. Disabling it makes the system unable to be reconfigured via 350 + `nixos-rebuild`. This is good for image based appliances where updates are 351 + handled outside the image. 352 + 348 353 - The Cinnamon module now enables XDG desktop integration by default. If you are experiencing collisions related to xdg-desktop-portal-gtk you can safely remove `xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];` from your NixOS configuration. 349 354 350 355 - GNOME, Pantheon, Cinnamon module no longer forces Qt applications to use Adwaita style since it was buggy and is no longer maintained upstream (specifically, Cinnamon now defaults to the gtk2 style instead, following the default in Linux Mint). If you still want it, you can add the following options to your configuration but it will probably be eventually removed:
+1
nixos/modules/module-list.nix
··· 1408 1408 ./system/activation/activatable-system.nix 1409 1409 ./system/activation/activation-script.nix 1410 1410 ./system/activation/specialisation.nix 1411 + ./system/activation/switchable-system.nix 1411 1412 ./system/activation/bootspec.nix 1412 1413 ./system/activation/top-level.nix 1413 1414 ./system/boot/binfmt.nix
+26
nixos/modules/profiles/image-based-appliance.nix
··· 1 + # This profile sets up a sytem for image based appliance usage. An appliance is 2 + # installed as an image, cannot be re-built, has no Nix available, and is 3 + # generally not meant for interactive use. Updates to such an appliance are 4 + # handled by updating whole partition images via a tool like systemd-sysupdate. 5 + 6 + { lib, modulesPath, ... }: 7 + 8 + { 9 + 10 + # Appliances are always "minimal". 11 + imports = [ 12 + "${modulesPath}/profiles/minimal.nix" 13 + ]; 14 + 15 + # The system cannot be rebuilt. 16 + nix.enable = false; 17 + system.switch.enable = false; 18 + 19 + # The system is static. 20 + users.mutableUsers = false; 21 + 22 + # The system avoids interpreters as much as possible to reduce its attack 23 + # surface. 24 + boot.initrd.systemd.enable = lib.mkDefault true; 25 + networking.useNetworkd = lib.mkDefault true; 26 + }
+9
nixos/modules/profiles/minimal.nix
··· 18 18 19 19 documentation.nixos.enable = mkDefault false; 20 20 21 + # Perl is a default package. 22 + environment.defaultPackages = mkDefault [ ]; 23 + 24 + # The lessopen package pulls in Perl. 25 + programs.less.lessopen = mkDefault null; 26 + 27 + # This pulls in nixos-containers which depends on Perl. 28 + boot.enableContainers = mkDefault false; 29 + 21 30 programs.command-not-found.enable = mkDefault false; 22 31 23 32 services.logrotate.enable = mkDefault false;
+26 -39
nixos/modules/system/activation/activatable-system.nix
··· 1 - { config, lib, pkgs, ... }: 1 + { options, config, lib, pkgs, ... }: 2 2 3 3 let 4 4 inherit (lib) 5 5 mkOption 6 - optionalString 7 6 types 8 7 ; 9 - 10 - perlWrapped = pkgs.perl.withPackages (p: with p; [ ConfigIniFiles FileSlurp ]); 11 8 12 9 systemBuilderArgs = { 13 10 activationScript = config.system.activationScripts.script; 14 11 dryActivationScript = config.system.dryActivationScript; 15 12 }; 16 13 17 - systemBuilderCommands = '' 18 - echo "$activationScript" > $out/activate 19 - echo "$dryActivationScript" > $out/dry-activate 20 - substituteInPlace $out/activate --subst-var-by out ''${!toplevelVar} 21 - substituteInPlace $out/dry-activate --subst-var-by out ''${!toplevelVar} 22 - chmod u+x $out/activate $out/dry-activate 23 - unset activationScript dryActivationScript 24 - 25 - mkdir $out/bin 26 - substitute ${./switch-to-configuration.pl} $out/bin/switch-to-configuration \ 27 - --subst-var out \ 28 - --subst-var-by toplevel ''${!toplevelVar} \ 29 - --subst-var-by coreutils "${pkgs.coreutils}" \ 30 - --subst-var-by distroId ${lib.escapeShellArg config.system.nixos.distroId} \ 31 - --subst-var-by installBootLoader ${lib.escapeShellArg config.system.build.installBootLoader} \ 32 - --subst-var-by localeArchive "${config.i18n.glibcLocales}/lib/locale/locale-archive" \ 33 - --subst-var-by perl "${perlWrapped}" \ 34 - --subst-var-by shell "${pkgs.bash}/bin/sh" \ 35 - --subst-var-by su "${pkgs.shadow.su}/bin/su" \ 36 - --subst-var-by systemd "${config.systemd.package}" \ 37 - --subst-var-by utillinux "${pkgs.util-linux}" \ 38 - ; 39 - 40 - chmod +x $out/bin/switch-to-configuration 41 - ${optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) '' 42 - if ! output=$(${perlWrapped}/bin/perl -c $out/bin/switch-to-configuration 2>&1); then 43 - echo "switch-to-configuration syntax is not valid:" 44 - echo "$output" 45 - exit 1 46 - fi 47 - ''} 48 - ''; 49 - 50 14 in 51 15 { 52 16 options = { ··· 60 24 do, but for image based systems, this may not be needed or not be desirable. 61 25 ''; 62 26 }; 27 + system.activatableSystemBuilderCommands = options.system.systemBuilderCommands // { 28 + description = lib.mdDoc '' 29 + Like `system.systemBuilderCommands`, but only for the commands that are 30 + needed *both* when the system is activatable and when it isn't. 31 + 32 + Disclaimer: This option might go away in the future. It might be 33 + superseded by separating switch-to-configuration into a separate script 34 + which will make this option superfluous. See 35 + https://github.com/NixOS/nixpkgs/pull/263462#discussion_r1373104845 for 36 + a discussion. 37 + ''; 38 + }; 63 39 system.build.separateActivationScript = mkOption { 64 40 type = types.package; 65 41 description = '' ··· 71 47 }; 72 48 }; 73 49 config = { 74 - system.systemBuilderCommands = lib.mkIf config.system.activatable systemBuilderCommands; 50 + system.activatableSystemBuilderCommands = '' 51 + echo "$activationScript" > $out/activate 52 + echo "$dryActivationScript" > $out/dry-activate 53 + substituteInPlace $out/activate --subst-var-by out ''${!toplevelVar} 54 + substituteInPlace $out/dry-activate --subst-var-by out ''${!toplevelVar} 55 + chmod u+x $out/activate $out/dry-activate 56 + unset activationScript dryActivationScript 57 + ''; 58 + 59 + system.systemBuilderCommands = lib.mkIf 60 + config.system.activatable 61 + config.system.activatableSystemBuilderCommands; 75 62 system.systemBuilderArgs = lib.mkIf config.system.activatable 76 63 (systemBuilderArgs // { 77 64 toplevelVar = "out"; ··· 86 73 }) 87 74 '' 88 75 mkdir $out 89 - ${systemBuilderCommands} 76 + ${config.system.activatableSystemBuilderCommands} 90 77 ''; 91 78 }; 92 79 }
+55
nixos/modules/system/activation/switchable-system.nix
··· 1 + { config, lib, pkgs, ... }: 2 + 3 + let 4 + 5 + perlWrapped = pkgs.perl.withPackages (p: with p; [ ConfigIniFiles FileSlurp ]); 6 + 7 + in 8 + 9 + { 10 + 11 + options = { 12 + system.switch.enable = lib.mkOption { 13 + type = lib.types.bool; 14 + default = true; 15 + description = lib.mdDoc '' 16 + Whether to include the capability to switch configurations. 17 + 18 + Disabling this makes the system unable to be reconfigured via `nixos-rebuild`. 19 + 20 + This is good for image based appliances where updates are handled 21 + outside the image. Reducing features makes the image lighter and 22 + slightly more secure. 23 + ''; 24 + }; 25 + }; 26 + 27 + config = lib.mkIf config.system.switch.enable { 28 + system.activatableSystemBuilderCommands = '' 29 + mkdir $out/bin 30 + substitute ${./switch-to-configuration.pl} $out/bin/switch-to-configuration \ 31 + --subst-var out \ 32 + --subst-var-by toplevel ''${!toplevelVar} \ 33 + --subst-var-by coreutils "${pkgs.coreutils}" \ 34 + --subst-var-by distroId ${lib.escapeShellArg config.system.nixos.distroId} \ 35 + --subst-var-by installBootLoader ${lib.escapeShellArg config.system.build.installBootLoader} \ 36 + --subst-var-by localeArchive "${config.i18n.glibcLocales}/lib/locale/locale-archive" \ 37 + --subst-var-by perl "${perlWrapped}" \ 38 + --subst-var-by shell "${pkgs.bash}/bin/sh" \ 39 + --subst-var-by su "${pkgs.shadow.su}/bin/su" \ 40 + --subst-var-by systemd "${config.systemd.package}" \ 41 + --subst-var-by utillinux "${pkgs.util-linux}" \ 42 + ; 43 + 44 + chmod +x $out/bin/switch-to-configuration 45 + ${lib.optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) '' 46 + if ! output=$(${perlWrapped}/bin/perl -c $out/bin/switch-to-configuration 2>&1); then 47 + echo "switch-to-configuration syntax is not valid:" 48 + echo "$output" 49 + exit 1 50 + fi 51 + ''} 52 + ''; 53 + }; 54 + 55 + }
+1
nixos/tests/all-tests.nix
··· 582 582 node-red = handleTest ./node-red.nix {}; 583 583 nomad = handleTest ./nomad.nix {}; 584 584 non-default-filesystems = handleTest ./non-default-filesystems.nix {}; 585 + non-switchable-system = runTest ./non-switchable-system.nix; 585 586 noto-fonts = handleTest ./noto-fonts.nix {}; 586 587 noto-fonts-cjk-qt-default-weight = handleTest ./noto-fonts-cjk-qt-default-weight.nix {}; 587 588 novacomd = handleTestOn ["x86_64-linux"] ./novacomd.nix {};
+15
nixos/tests/non-switchable-system.nix
··· 1 + { lib, ... }: 2 + 3 + { 4 + name = "non-switchable-system"; 5 + 6 + meta.maintainers = with lib.maintainers; [ nikstur ]; 7 + 8 + nodes.machine = { 9 + system.switch.enable = false; 10 + }; 11 + 12 + testScript = '' 13 + machine.succeed("test ! -e /run/current-system/bin/switch-to-configuration") 14 + ''; 15 + }