Distributions Linux

NixOS : Guide sur cette distribution déclarative

Cet article a été mis à jour, vous consultez ici une archive de cet article!
Table des matières

nixos-logo



Introduction



NixOS est une distribution Linux assez innovante qui se distingue par une approche différente de la gestion des paquets et de la configuration du système.
NixOS permet une gestion "déclarative" des configurations, à travers un ou plusieurs fichiers de configuration centraux.
Ça facilite la reproduction des environnements d'une machine à l'autre.

On va pouvoir aussi, entre deux modifications du système revenir rapidement à l'état précédent. On est un peu dans le même concept que les distribs atomique, mais avec en plus une configuration déclarative.

Pour résumer, c'est une distribution gérée avec un Ansible intégré pour ceux qui connaissent Ansible.

Installation



Il y a 3 images disponibles en téléchargement sur le site de NixOS (https://nixos.org/download ):
- GNOME
- KDE Plasma
- Minimale

Installation graphique



Voulant un environement de bureau GNOME, je suis parti sur l'image GNOME, ce qui m'offre, après une installation graphique, via Calamarès.
Ca permet de dégrossir une installation rapidement.

Si on veut utiliser NixOS en mode "serveur" ou avec un autre environnement de bureau, on fera l'installation minimale.

Installation minimale



A venir

Concepts sur la modification



Fichier configuration.nix



Le fichier de configuration principal est /etc/nixos/configuration.nix

Il contient ceci :
Code BASH :
# Edit this configuration file to define what should be installed on
# your system.  Help is available in the configuration.nix(5) man page
# and in the NixOS manual (accessible by running ‘nixos-help’).
 
{ config, pkgs, ... }:
 
{
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
    ];
 
  # Bootloader.
  boot.loader.systemd-boot.enable = true;
  boot.loader.efi.canTouchEfiVariables = true;
 
  networking.hostName = "nixos-twitch"; # Define your hostname.
  # networking.wireless.enable = true;  # Enables wireless support via wpa_supplicant.
 
  # Configure network proxy if necessary
  # networking.proxy.default = "http://user:password@proxy:port/";
  # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
 
  # Enable networking
  networking.networkmanager.enable = true;
 
  # Set your time zone.
  time.timeZone = "Europe/Paris";
 
  # Select internationalisation properties.
  i18n.defaultLocale = "fr_FR.UTF-8";
 
  i18n.extraLocaleSettings = {
    LC_ADDRESS = "fr_FR.UTF-8";
    LC_IDENTIFICATION = "fr_FR.UTF-8";
    LC_MEASUREMENT = "fr_FR.UTF-8";
    LC_MONETARY = "fr_FR.UTF-8";
    LC_NAME = "fr_FR.UTF-8";
    LC_NUMERIC = "fr_FR.UTF-8";
    LC_PAPER = "fr_FR.UTF-8";
    LC_TELEPHONE = "fr_FR.UTF-8";
    LC_TIME = "fr_FR.UTF-8";
  };
 
  # Enable the X11 windowing system.
  services.xserver.enable = true;
 
  # Enable the GNOME Desktop Environment.
  services.xserver.displayManager.gdm.enable = true;
  services.xserver.desktopManager.gnome.enable = true;
 
  # Configure keymap in X11
  services.xserver.xkb = {
    layout = "fr";
    variant = "azerty";
  };
 
  # Configure console keymap
  console.keyMap = "fr";
 
  # Enable CUPS to print documents.
  services.printing.enable = true;
 
  # Enable sound with pipewire.
  hardware.pulseaudio.enable = false;
  security.rtkit.enable = true;
  services.pipewire = {
    enable = true;
    alsa.enable = true;
    alsa.support32Bit = true;
    pulse.enable = true;
  };
 
  # Enable touchpad support (enabled default in most desktopManager).
  # services.xserver.libinput.enable = true;
 
  # Define a user account. Don't forget to set a password with ‘passwd’.
  users.users.adrien = {
    isNormalUser = true;
    description = "adrien";
    extraGroups = [ "networkmanager" "wheel" ];
    packages = with pkgs; [
    #  thunderbird
    ];
  };
 
  # Install firefox.
  programs.firefox.enable = true;
 
  # Allow unfree packages
  nixpkgs.config.allowUnfree = true;
 
  # List packages installed in system profile. To search, run:
  # $ nix search wget
  environment.systemPackages = with pkgs; [
  #  vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default.
  #  wget
  ];
 
  # List services that you want to enable:
 
  # Enable the OpenSSH daemon.
  services.openssh.enable = true;
 
  # Open ports in the firewall.
  # networking.firewall.allowedTCPPorts = [ ... ];
  # networking.firewall.allowedUDPPorts = [ ... ];
  # Or disable the firewall altogether.
  networking.firewall.enable = false;
 
  # This value determines the NixOS release from which the default
  # settings for stateful data, like file locations and database versions
  # on your system were taken. It‘s perfectly fine and recommended to leave
  # this value at the release version of the first install of this system.
  # Before changing this value read the documentation for this option
  # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html).
  system.stateVersion = "24.05"; # Did you read the comment?
 
}
 


Les commentaires sont assez explicites.

Fichier hardware-configuration.nix



Il y a une référence dans le fichier principal au fichier hardware-configuration.nix.

Ce fichier sera différent suivant les machines.

Il prend en compte le partitionnement, les pilotes matériels, le réseau par exemple :
Code BASH :
# Do not modify this file!  It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations.  Please make changes
# to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, modulesPath, ... }:
 
{
  imports =
    [ (modulesPath + "/profiles/qemu-guest.nix")
    ];
 
  boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
  boot.initrd.kernelModules = [ ];
  boot.kernelModules = [ "kvm-intel" ];
  boot.extraModulePackages = [ ];
 
  fileSystems."/" =
    { device = "/dev/disk/by-uuid/cc0b1b57-1e2a-49fe-896c-17ea6da1f4d3";
      fsType = "ext4";
    };
 
  fileSystems."/boot" =
    { device = "/dev/disk/by-uuid/3B88-DF40";
      fsType = "vfat";
      options = [ "fmask=0077" "dmask=0077" ];
    };
 
  swapDevices = [ ];
 
  # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
  # (the default) this is the recommended approach. When using systemd-networkd it's
  # still possible to use this option, but it's recommended to use it in conjunction
  # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
  networking.useDHCP = lib.mkDefault true;
  # networking.interfaces.ens18.useDHCP = lib.mkDefault true;
 
  nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
 


Créer ses propres configurations .nix



Les fichiers intégrés sont à placer dans /etc/nixos, c'est plus propre.

On pourra intégrer d'autres fichiers de configuration dans le fichier configuration.nix. Par exemple, intégrer un fichier adrien.nix, on ajoutera la référence dans la section imports :
Code BASH :
  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      ./adrien.nix
    ];


Appliquer les modifications



Après chaque modification de la configuration, il sera nécessaire d'appliquer la configuration.
Cela sera à faire quand on modifie un paramétrage ou qu'on ajoute / supprime des logiciels.

La commande à invoquer sera :
Code BASH :
sudo nixos-rebuild switch


Gérer NixOS



Mettre à jour NixOS



Dans un premier temps, on met à jour la liste des logiciels :
Code BASH :
sudo nix-channel --update


Pour appliquer la mise à jour :
Code BASH :
sudo nixos-rebuild switch


On peut faire du 2 en 1 avec :
Code BASH :
sudo nixos-rebuild switch --upgrade


Et pour prendre en compte les modifications, on devra redémarrer:
Code BASH :
sudo systemctl reboot


Upgrade : Changer de branche



L'upgrade du système se fait en suivant les notes de version de la nouvelle version.
Ici un exemple de mise à niveau de 24.05 à 24.11.

On prendra soin de vérifier s'il y a des changements à faire dans les fichiers de configuration avant.

On repère le channel sur lequel on est avec :
Code BASH :
nix-channel --list | grep nixos


Ce qui renvoie :
Code TEXT :
nixos https://nixos.org/channels/nixos-24.05


On bascule sur le nouveau channel via :
Code BASH :
nix-channel --add https://channels.nixos.org/nixos-24.11 nixos


On applique la mise à niveau :
Code BASH :
sudo nixos-rebuild switch --upgrade

ça sera évidemment plus long qu'une mise à jour ou un ajout de logiciel, demandera plus d'espace libre et de ressources !

Et pour prendre en compte les modifications, on devra redémarrer:
Code BASH :
sudo systemctl reboot


Faire du ménage dans les images



Par défaut, les images anciennes sont gardées, ce qui permet de faire un rollback sur une config existante.

Pour supprimer les images de plus de 30j par exemple :
Code BASH :
nix-collect-garbage --delete-older-than 30d


Pour tout supprimer sauf l'image en cours :
Code BASH :
nix-collect-garbage -d


Eleménts de configuration



Ressources à connaitre



Quand on gèrera les configurations, on aura besoin de https://search.nixos.org/
Sur le site on a 2 sections : Options et Packages.

Les options dans NixOS sont des paramètres de configuration qui définissent le comportement du système ou des services. On y trouvera des configs pour :
- Activer des services
- Paramétrer des services
- Régler des éléments du système (zram, etc.)
- Installer des applications et régrer des paramétrages (vim, éditeur par défaut)

Les packages dans NixOS sont des paquets qu'on va installer sur le système, sous forme de liste. On les listera dans un pavé de configuration avec 1 paquet par ligne comme ceci par exemple :
Code TEXT :
  environment.systemPackages = with pkgs; [
    nmon
    libreoffice-fresh
    fastfetch
  ];


Attention, ce bloc est déjà défini dans configuration.nix, il ne doit pas être présent deux fois dans le même fichier !

Configuration du système



Voici un exemple de configuration du système :
Code TEXT :
  # Pour les VMS : 
  services.qemuGuest.enable = true;
  # Config systeme
  zramSwap.enable = true;
  boot.kernel.sysctl = { "vm.swappiness" = 5; } ;
  networking.enableIPv6 = false;
 


- J'active le service qemuGuest car je suis dans une VM sous Proxmox
- J'active zram, avec sa configuration par défaut (qui semble être 50% de la RAM)
- Je définit la valeur vm.swapiness à 5 au niveau du système
- Je désactive l'IPv6

Options pour des programmes



Voici un exemple de paquets qui nécessitent quelques options, installés sous la forme programs.XXX :
Code BASH :
  # Programmes
  programs.htop.enable = true;
  programs.vim.package = pkgs.vim-full;
  programs.vim.defaultEditor = true;
 


- htop a plusieurs options possibles de paramétrages, ici, je ne fais qu'installer le logiciel
- J'installe vim, avec tous les modules et je le défini comme éditeur par défaut (va modifier la variable EDITOR)

Installer des paquets



Voici un exemple pour installer des paquets.
On indiquera sue chaque nouvelle ligne (c'est plus propre) le nom des paquets à installer.
On le fera dans la section environment.systemPackages :

Code BASH :
  # Paquets qui n'ont pas d'options
  environment.systemPackages = with pkgs; [
    gnomeExtensions.dash-to-dock
    gnomeExtensions.appindicator
    gnome.gnome-tweaks
    gnome-extension-manager
    nmon
    libreoffice-fresh
    songrec
  ];


On trouvera le nom des paquets dans : https://search.nixos.org/packages

Exclure des paquets d'un groupe



Ici, un exemple d'excusion de logiciels.
Dans le fichier principal, j'ai GNOME qui est installé (c'est un métagroupe) : services.xserver.desktopManager.gnome.enable

Si on veut exclure dans ce paquet des paquets installés, on le fera ainsi :
Code BASH :
  # Exclure les logiciels de GNOME par défaut installés
  environment.gnome.excludePackages = with pkgs; [
    gnome-tour
    gnome.geary
  ];


Configuration de GNOME via dconf



Ici, un exemple de configuration de GNOME via dconf.
Dans cet exemple je modifie une valeur dconf :
Code BASH :
  # Config GNOME
  programs.dconf = {
    enable = true;
    profiles.user.databases = [
      {
        lockAll = true; # prevents overriding
        settings = {
          "org/gnome/desktop/wm/preferences" = {
            button-layout = ":minimize,maximize,close";
          };
        };
      }
    ];
  };


C'est l'équivalent de :
Code BASH :
gsettings set org.gnome.desktop.wm.preferences button-layout ":minimize,maximize,close"