Specialisation: Difference between revisions

From NixOS Wiki
imported>Benjaminl
Mention the --specialisation flag for nixos-rebuild
Fin444 (talk | contribs)
No edit summary
 
(7 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{Expansion|Configuration with and for GRUB could use explaining here}}
{{Expansion|Configuration with and for GRUB could use explaining here}}


Specialisations allow you, to define variations of your config within itself (even completely different ones). Within a generation of your config you can then choose between specialisations at boot-time or switch them at runtime using activation scripts.
Specialisations allow you to define variations of your system configuration. For instance, if you don't usually use GPU, you might create a base system with your GPU disabled and create a dedicated specialization with Nvidia/AMD drivers installed - later, during boot, you can choose which configuration you want to boot into this time.
 
Previously this feature was called "children" because a specialised configuration is defined by its "parent" configuration. Afterwards it was called "nesting", because this feature essentially allows nested configurations. Finally it was renamed to todays "specialisation". [2]


== Config ==
== Config ==
Line 40: Line 38:
{{Note|At times, you may want to overwrite values in specialisations which you have already defined in your parent configuration. To solve this problem in <code>chani</code> example, the parent configuration could define <code>services.xserver.desktopManager.plasma5.enable &#61; false;</code> in an overwritable manner using <code>mkDefault</code> and similar [3]: <code>services.xserver.desktopManager.plasma5.enable &#61; mkDefault false;</code>}}
{{Note|At times, you may want to overwrite values in specialisations which you have already defined in your parent configuration. To solve this problem in <code>chani</code> example, the parent configuration could define <code>services.xserver.desktopManager.plasma5.enable &#61; false;</code> in an overwritable manner using <code>mkDefault</code> and similar [3]: <code>services.xserver.desktopManager.plasma5.enable &#61; mkDefault false;</code>}}


== Special case: the default non-specialised entry ==
== Special case: the default non-specialized entry ==


Specialisations are receiving options in addition to your default configuration, but what if you want to have options in your default configuration that shouldn't be pulled by the specialisations?
Specializations are receiving options in addition to your default configuration, but what if you want to have options in your default configuration that shouldn't be pulled by the specializations?


There is a specific syntax to declare options that apply to the case environment "not specialised" and that won't be pulled by other specialisations. You need to wrap the options into a new file that is imported into your configuration.nix file
Use the conditional <code>config.specialisation != {}</code> to declare values for the non-specialized case. For example, you could write a module (as variable, or separate file), imported from <code>configuration.nix</code> via <code>imports = [...]</code> like this:


<syntaxHighlight lang=nix>
<syntaxHighlight lang=nix>
Line 52: Line 50:


     # example
     # example
     hardware.opengl.extraPackages = with pkgs; [ vaapiIntel libvdpau-va-gl vaapiVdpau ];
     hardware.opengl.extraPackages = with pkgs; [ vaapiIntel vaapiVdpau ];
   };
   };
})
})
</syntaxHighlight>
</syntaxHighlight>


== Boot entries ==
However, if there are no specialisations defined, then <code>config.specialisation != {}</code> always evaluate to <code>false</code>.


For every generation of your config, a boot menu entry is generated. When using specialisations, an additional entry is generated for it, per generation.
== Activating a specialization ==


TODO: how to use grub submenus
After rebuilding your system, you can choose a specialisation during boot; it's also possible to switch into a specialisation at runtime - following the example above, we'd run:


== Runtime activation ==
<syntaxHighlight lang=console>
$ nixos-rebuild switch --specialisation chani
</syntaxHighlight>


Taking the <code>chani</code> specialisation from our example, we can activate it at runtime (comparable to <code>nixos-rebuild switch</code>), by running <code>/nix/var/nix/profiles/system/specialisation/chani/bin/switch-to-configuration switch</code>. <code>nixos-rebuild switch</code> also supports a <code>--specalisation</code> flag, which we can use like this: <code>nixos-rebuild switch --specialisation chani</code>.
Note that not all configurations can be fully switched into at runtime - e.g. if your specialization uses a different kernel, switching into it will not actually reload the kernel (but if you were to restart your computer and pick the specialisation from the boot menu, the alternative kernel would get loaded).


== Further reading ==
== Further reading ==

Latest revision as of 01:26, 7 November 2024

Specialisations allow you to define variations of your system configuration. For instance, if you don't usually use GPU, you might create a base system with your GPU disabled and create a dedicated specialization with Nvidia/AMD drivers installed - later, during boot, you can choose which configuration you want to boot into this time.

Config

Specialisations are defined with the following options [1]: https://search.nixos.org/options?from=0&size=50&sort=relevance&query=specialisation

specialisation = {
  chani.configuration = {
    services.xserver.desktopManager.plasma5.enable = true;
  };

  paul = {
    inheritParentConfig = false;
    configuration = {
      system.nixos.tags = [ "paul" ];
      services.xserver.desktopManager.gnome.enable = true;
      users.users.paul = {
        isNormalUser = true;
        uid = 1002;
        extraGroups = [ "networkmanager" "video" ];
      };
      services.xserver.displayManager.autoLogin = {
        enable = true;
        user = "paul";
      };
      environment.systemPackages = with pkgs; [
        dune-release
      ];
    };
  };
};

In this example, the chani specialisation inherits the parent config (that contains the specialisation directive), but additionally activates the plasma5 desktop. The paul specialisation on the other hand does not inheritParentConfig and defines its own one from scratch instead.

Note: At times, you may want to overwrite values in specialisations which you have already defined in your parent configuration. To solve this problem in chani example, the parent configuration could define services.xserver.desktopManager.plasma5.enable = false; in an overwritable manner using mkDefault and similar [3]: services.xserver.desktopManager.plasma5.enable = mkDefault false;

Special case: the default non-specialized entry

Specializations are receiving options in addition to your default configuration, but what if you want to have options in your default configuration that shouldn't be pulled by the specializations?

Use the conditional config.specialisation != {} to declare values for the non-specialized case. For example, you could write a module (as variable, or separate file), imported from configuration.nix via imports = [...] like this:

({ lib, config, pkgs, ... }: {
  config = lib.mkIf (config.specialisation != {}) {
    # Config that should only apply to the default system, not the specialised ones

    # example
    hardware.opengl.extraPackages = with pkgs; [ vaapiIntel vaapiVdpau ];
  };
})

However, if there are no specialisations defined, then config.specialisation != {} always evaluate to false.

Activating a specialization

After rebuilding your system, you can choose a specialisation during boot; it's also possible to switch into a specialisation at runtime - following the example above, we'd run:

$ nixos-rebuild switch --specialisation chani

Note that not all configurations can be fully switched into at runtime - e.g. if your specialization uses a different kernel, switching into it will not actually reload the kernel (but if you were to restart your computer and pick the specialisation from the boot menu, the alternative kernel would get loaded).

Further reading

[1] https://www.tweag.io/blog/2022-08-18-nixos-specialisations/

[2] https://discourse.nixos.org/t/nixos-specialisations-how-do-you-use-them/10367/4

[3] https://discourse.nixos.org/t/what-does-mkdefault-do-exactly/9028