[LINUX] Gérez de manière déclarative l'environnement avec Nix et home-manager

Si vous incluez le gestionnaire de paquets Nix, vous voulez certainement inclure home-manager. home-manager est un outil de gestion déclarative de l'environnement utilisateur à l'aide de nix.

--Package à installer

C'est un excellent outil qui vous permet de gérer divers paramètres utilisateur de manière déclarative dans un seul fichier.

Si vous ne mettez que nix et home-manager, ce n'est pas un rêve de terminer la configuration avec une seule commande même si vous passez au PC. (Je l'ai fait lorsque j'ai remplacé mon PC au travail.)

Pour plus de détails, reportez-vous à la page github home-manager ou au manuel. Comme vous pouvez le voir, c'est en anglais et c'est long, donc je vais juste résumer les points principaux pour moi.

Installation du gestionnaire à domicile

Vous avez besoin de Nix Package Manager pour utiliser home-manager, alors installez d'abord Nix.

> curl -L https://nixos.org/nix/install | sh
> nix-channel --add https://nixos.org/channels/nixpkgs-unstable nixpkgs
> nix-channel --update

Vous pouvez enregistrer un canal avec nixchannel --add <url> [channel-alias]. C'est comme enregistrer un référentiel.

Pour installer home-manager, abonnez-vous d'abord au canal home-manager.

> nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
> nix-channel --update

Ensuite, vous pouvez l'installer en tapant la commande suivante.

> nix-shell '<home-manager>' -A install

Gestion des packages

Pour configurer votre environnement utilisateur en utilisant home-manager, créez ~ / .config / nixpkgs / home.nix.

Par exemple, les paramètres suivants installent git et GNU / hello.

nix:.config/nixpkgs/home.nix


{ pkgs, ... }:
{
    #C'est la maison-Entre automatiquement lorsque le gestionnaire est installé
    programs.home-manager.enable = true;
    home.username = "hnakano";
    home.stateVersion = "20.09";

    #Déclarez le package à installer ici
    home.packages = [
        pkgs.git
        pkgs.hello
    ];
}

Tapez ensuite la commande suivante pour refléter les paramètres.

> home-manager switch

Ce fichier de configuration est écrit dans son propre langage appelé expression Nix. Pour être honnête, c'est presque comme json, donc vous n'avez pas à vous soucier trop de la grammaire, mais je vais expliquer la grammaire minimale pour ceux qui s'en soucient.

Grammaire minimale pour utiliser home-manager

repl Il existe une expression Nix repl. Vous pouvez entrer repl en tapant nix repl sur la ligne de commande.

> nix repl
Welcome to Nix version 2.3.7. Type :? for help.

nix-repl>

Tapez :? Pour obtenir de l'aide sur la commande repl. Vous pouvez quitter repl avec : q.

Type de base

Il existe des types numérique, booléen et chaîne. La concaténation de chaînes est «+».

nix-repl> 1 #interger
1

nix-repl> 3.14 #float
3.14

nix-repl> true #boolean
true

nix-repl> "hogehoge" #string
"hogehoge"

nix-repl> "hoge" + "fuga" #string concatenate
"hogefuga"

let ... in

Utilisez let ... in pour affecter une valeur à une variable. Faites attention à la position du point-virgule.

nix-repl> let x = 1; y = 2; z = x + y; in z * 2
6

Vous pouvez attribuer des valeurs uniquement dans repl sans utiliser let ... in. Cependant, veuillez noter que l'expression Nix normale ne peut pas être écrite de cette manière.

nix-repl> x = 3

nix-repl> y = 4

nix-repl> x + y
7

List

La liste est «[a b c]». Les délimiteurs d'élément sont des espaces demi-largeur ou des sauts de ligne. À propos, les types n'ont pas besoin de correspondre **

nix-repl> [ 1 "hoge" true ]
[ 1 "hoge" true ]

nix-repl> [
            1
            2
            3
          ]
[ 1 2 3 ]

Pour accéder aux éléments de la liste, utilisez la fonction intégrée builtins.elemAt. Aucune parenthèse n'est requise pour appliquer la fonction.

nix-repl> x = [ 1 2 3 ]

nix-repl> builtins.elemAt x 0
1

nix-repl> builtins.elemAt x 1
2

une fonction

Les fonctions Nix sont de la forme «arg: body». Le côté gauche des deux points est l'argument. La fonction à deux arguments est ʻarg1: arg2: body`.

nix-repl> hello =  x: "hello, " + x  

nix-repl> hello "world"
"hello, world"

Fondamentalement, Nix ne peut créer que des fonctions anonymes.

nix-repl> x: y: x + y
«lambda @ (string):1:1»

Donc, si vous voulez nommer la fonction, utilisez l'expression let

nix-repl> let
            add = x: y: x + y;
            add2 = add 2; #Partiellement applicable
          in
          add2 3 #Identique à ajouter 2 3
5

Attribute set

Un ensemble d'attributs est une paire de clé = valeur entre parenthèses sous la forme «{clé1 = valeur1; clé2 = valeur2;}». Un point-virgule est toujours requis à la fin de la paire clé = valeur;.

Vous pouvez accéder à la valeur sous la forme «x.key1».

nix-repl> let
            x = {     
              hoge = "hoge";
              fuga = "fuga";
            };
          in x.hoge
"hoge"
Une fonction qui prend un ensemble d'attributs comme argument

Les fonctions qui prennent un ensemble d'attributs comme argument peuvent généralement être définies sous la forme ʻarg: body`.

nix-repl> let
            f = x: x.hoge + x.fuga;
          in f { hoge = "hoge"; fuga = "fuga"; }
"hogefuga"

Cependant, il peut également être défini sous la forme «{key1, key2}: body» à la place. Sous cette forme, une erreur se produit si le nom de la clé d'argument ne correspond pas exactement. Vous pouvez éviter cette erreur en mettant ... dans l'argument, comme {key, key2, ...}: body.

nix-repl> f = { hoge, fuga }: hoge + fuga

nix-repl> let x = { hoge = "hoge"; fuga = "fuga"; }; in f x
"hogefuga"

nix-repl> let y = { hoge = 3; fuga = 4; piyo = true; }; in f y
error: anonymous function at (string):1:2 called with unexpected argument 'piyo', at (string):1:50

nix-repl> g = { hoge, ... }: "hello, " + hoge

nix-repl> let y = { hoge = "world"; fuga = 4; piyo = true; }; in g y
"hello, world"

Autre

Référence grammaticale Nix Expression

--Manuel officiel https://nixos.org/manual/nix/stable/#chap-writing-nix-expressions --Nix Pills (Blog officiel) https://nixos.org/guides/nix-pills/basics-of-language.html

Lire le fichier de configuration

Lisons à nouveau le fichier de configuration défini en premier.

nix:./config/nixpkgs/home.nix


{ pkgs, ... }:
{
    #C'est la maison-Entre automatiquement lorsque le gestionnaire est installé
    programs.home-manager.enable = true;
    home.username = "hnakano";
    home.stateVersion = "20.09";

    #Déclarez le package ici
    home.packages = [
        pkgs.git
        pkgs.hello
    ];
}

Tout d'abord, nous pouvons voir que cette expression est une fonction qui prend un ensemble d'attributs avec la clé pkgs. pkgs contient généralement <nixpkgs>, c'est-à-dire la collection de paquets Nix.

{key1.key2 = value;} est le sucre de syntaxe pour l'ensemble d'attributs imbriqués, qui signifie {key1 = {key2 = value;};}.

Sans sucre de syntaxe, ce fichier de configuration ressemblerait à ceci:

{ pkgs, ... }:
{
    programs = {
        home-manager = {
            enable = true;
        };
    };

    home = {
        username = "hnakano";
        stateVersion = "20.09";
        packages = [
            pkgs.git;
            pkgs.hello;
        ];
    };
}

Autrement dit, cette fonction prend un ensemble d'attributs de {pkgs = ..; ...} comme argument. C'est une fonction qui renvoie un ensemble d'attributs de {programmes = {...}; home = {...};}.

La commande home-manager évalue cette valeur de retour et reflète les paramètres de l'environnement utilisateur.

Autres éléments de réglage

J'essaierai divers paramètres en utilisant home-manager. Pour le contenu qui peut être défini dans home-manager, reportez-vous au Home-manager Manual.

nix:.config/nixpkgs/home.nix


{
  home.packages = with pkgs; [ nixfmt exa bat source-han-code-jp ];

  programs.git = {
    enable = true;
    userName = "hnakano863";
    userEmail = "[email protected]";
    extraConfig.pull.rebase = false;
  };

  fonts.fontconfig.enable = true;

  programs.bash = {
    enable = true;
    profileExtra = ''
      export XDG_DATA_DIRS=$HOME/.nix-profile/share''${XDG_DATA_DIRS:+:}$XDG_DATA_DIRS
      export LIBGL_ALWAYS_INDIRECT=1
      export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0
      if [ -e $HOME/.nix-profile/etc/profile.d/nix.sh ]; then
          . $HOME/.nix-profile/etc/profile.d/nix.sh;
      fi
    '';
    initExtra = ''
      if [ -z $IN_NIX_SHELL ]; then exec fish fi
    '';
    shellAliases = {
      ls = "exa";
      cat = "bat";
    };
  };

  programs.fish = {
    enable = true;
    interactiveShellInit = ''
      set -gx fish_user_paths $HOME/go/bin $HOME/.local/bin
    '';
  };
      
  programs.tmux = {
    enable = true;
    clock24 = true;
    keyMode = "vi";
    shortcut = "a";
    terminal = "screen-256color";
  };
}

Il y a des éléments grammaticaux que je n'ai pas expliqués, je vais donc les expliquer.

Premièrement, dans home.packages, il y a le formulaire avec pkgs; [...]. C'est une syntaxe pour éviter d'écrire pkgs. comme [pkgs.nixfmt pkgs.exa ...].

Vient ensuite la chaîne entre deux guillemets simples qui apparaît dans programmes.bash.profile Extra etc. Il s'agit d'une chaîne de type chaîne indentée.

Indenté est ignoré dans la chaîne indentée, ce qui est utile pour écrire des scripts shell. En fait, programmes.bash.profile Extra est reflété dans ~ / .profile.

Enfin, si vous avez programmes.bash.enable = true;, l'exécution de home-manager switch essaiera de remplacer ~ / .profile, ~ / .bashrc, et ainsi de suite. À ce stade, si un fichier de configuration existant tel que ~ / .bashrc existe déjà dans l'environnement utilisateur, la commande home-manager échouera avec une erreur disant" J'ai un fichier de configuration ". Pour éviter cela, enregistrez le fichier existant à l'avance avec mv ~ / .bashrc ~ / .bashrc.bk.

Recommended Posts

Gérez de manière déclarative l'environnement avec Nix et home-manager
Gérez les packages d'exécution Python et les packages d'environnement de développement avec Poetry
Gérez l'environnement python avec virtualenv
Gérez vos données avec AWS RDS
Créer un environnement avec pyenv et pyenv-virtualenv
Créez un environnement Python sur votre Mac avec Anaconda et PyCharm
Nettoyer l'environnement python avec Pythonz et virtualenv
Construction de l'environnement MacOS 10.11: Powerline avec Anaconda et Dein.vim
Construire un environnement python avec virtualenv et direnv
Django: enregistrez l'agent utilisateur et gérez-le avec l'administrateur
Gérez l'environnement de plusieurs versions de Python avec Pythonz, virtualenv
Gérez les transitions d'état et communiquez avec les compteurs intelligents
Créez un environnement virtuel avec pyenv et venv
Créez un environnement virtuel python avec virtualenv et virtualenvwrapper
Créez un environnement virtuel python avec virtualenv et virtualenvwrapper
Gérer la rétention des groupes de journaux Amazon CloudWatch avec AWS Lambda
Installez Ubuntu 20.04 avec GUI et préparez l'environnement de développement
Automatisez Chrome avec Python et Selenium sur votre Chromebook
Comment configurer et compiler l'environnement Cython
Construire un environnement de calcul numérique avec pyenv et miniconda3