| Title: NixOS specific feature: specialisations | |
| Author: Solène | |
| Date: 29 August 2022 | |
| Tags: nixos nix tweag | |
| Description: This blog post explains how to use NixOS' unique feature | |
| called specialisation | |
| # Credits | |
| This blog post is a republication of the article I published on my | |
| employer's blog under CC BY 4.0. I'm grateful to be allowed to publish | |
| NixOS related content there, but also to be able to reuse it here! | |
| License CC by 4.0 | |
| Original publication place: Tweag I/O - NixOS Specialisations | |
| After the publication of the original post, the NixOS wiki got updated | |
| to contain most of this content, I added some extra bits for the | |
| specific use case of "options for the non-specialisation that shouldn't | |
| be inherited by specialisations" that wasn't convered in this text. | |
| NixOS wiki: Specialisation | |
| # Introduction | |
| I often wished to be able to define different boot entries for | |
| different uses of my computer, be it for separating professional and | |
| personal use, testing kernels or using special hardware. NixOS has a | |
| unique feature that solves this problem in a clever way — NixOS | |
| specialisations. | |
| A NixOS specialisation is a mechanism to describe additional boot | |
| entries when building your system, with specific changes applied on top | |
| of your non-specialised configuration. | |
| # When do you need specialisations | |
| You may have hardware occasionally connected to your computer, and some | |
| of these devices may require incompatible changes to your day-to-day | |
| configuration. Specialisations can create a new boot entry you can use | |
| when starting your computer with your specific hardware connected. This | |
| is common for people with external GPUs (Graphical Processing Unit), | |
| and the reason why I first used specialisations. | |
| With NixOS, when I need my external GPU, I connect it to my computer | |
| and simply reboot my system. I choose the eGPU specialisation in my | |
| boot menu, and it just works. My boot menu looks like the following: | |
| NixOS specialisation shown in Grub | |
| You can also define a specialisation which will boot into a different | |
| kernel, giving you a safe opportunity to try a new version while | |
| keeping a fallback environment with the regular kernel. | |
| We can push the idea further by using a single computer for | |
| professional and personal use. Specialisations can have their own | |
| users, services, packages and requirements. This would create a hard | |
| separation without using multiple operating systems. However, by | |
| default, such a setup would be more practical than secure. While your | |
| users would only exist in one specialisation at a time, both users’ | |
| data are stored on the same partition, so one user could be exploited | |
| by an attacker to reach the other user’s data. | |
| In a follow-up blog post, I will describe a secure setup using multiple | |
| encrypted partitions with different passphrases, all managed using | |
| specialisations with a single NixOS configuration. This will be quite | |
| awesome :) | |
| # How to use specialisations | |
| As an example, we will create two specialisations, one having the user | |
| Chani using the desktop environment Plasma, and the other with the user | |
| Paul using the desktop environment Gnome. Auto login at boot will be | |
| set for both users in their own specialisations. Our user Paul will | |
| need an extra system-wide package, for example dune-release. | |
| Specialisations can use any argument that would work in the top-level | |
| configuration, so we are not limited in terms of what can be changed. | |
| NixOS manual: Configuration options | |
| If you want to try, add the following code to your configuration.nix | |
| file. | |
| ```nix | |
| specialisation = { | |
| chani.configuration = { | |
| system.nixos.tags = [ "chani" ]; | |
| services.xserver.desktopManager.plasma5.enable = true; | |
| users.users.chani = { | |
| isNormalUser = true; | |
| uid = 1001; | |
| extraGroups = [ "networkmanager" "video" ]; | |
| }; | |
| services.xserver.displayManager.autoLogin = { | |
| enable = true; | |
| user = "chani"; | |
| }; | |
| }; | |
| paul.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 | |
| ]; | |
| }; | |
| }; | |
| ``` | |
| After applying the changes, run "nix-rebuild boot" as root. Upon | |
| reboot, in the GRUB menu, you will notice a two extra boot entries | |
| named “chani” and “paul” just above the last boot entry for | |
| your non-specialised system. | |
| Rebuilding the system will also create scripts to switch from a | |
| configuration to another, specialisations are no exception. | |
| Run | |
| "/nix/var/nix/profiles/system/specialisation/chani/bin/switch-to-config | |
| uration switch" to switch to the chani specialisation. | |
| When using the switch scripts, keep in mind that you may not have | |
| exactly the same environment as if you rebooted into the specialisation | |
| as some changes may be only applied on boot. | |
| # Conclusion | |
| Specialisations are a perfect solution to easily manage multiple boot | |
| entries with different configurations. It is the way to go when | |
| experimenting with your system, or when you occasionally need specific | |
| changes to your regular system. |