Open2

NixのTips

natsukiumnatsukium

nixpkgsにあるパッケージをバージョン指定したい

  1. 既存のパッケージの version, src などを override するような overlay を作成する
  2. 特定のバージョンがパッケージングされているnixpkgsのコミットハッシュを探してきて利用する

可能なら 1 を選択するべき

  • nixpkgsでは絶えずメンテナがパッケージを修正したりセキュリティパッチを当てたりしている
  • overlay を適用する方法だとローカルで特別な作業を必要とせずにそれらのアップデートを受けることができる
  • 一方 2 のように nixpkgs のバージョンを固定してしまうとアップデートは一切受けられなくなり、自分でメンテナンスをする必要がでてくる

overlay を作成する場合

メリット

デメリット

慣れるまで/パッケージによっては少し大変

やりかた

ベースにする nixpkgs のバージョンは最新の stable がいい

  • unstable はアップデートやリファクタリングに伴う derivation の変更が起こりやすく、容易に overlay が壊れうるため
  • stable リリースはそうした変更が少なく、セキュリティパッチなどの更新のみ受けられる

nixpkgsのコミットハッシュを固定する場合

メリット

デメリット

やりかた

2024-05-12 現在、 EOL となっている nodejs_16 を例としてあげる

  1. まず必要なバージョンのハッシュを以下のようなサイトから取得する
    今回の場合は nodejs などで検索するとこれまで nixpkgs に収録されてきたバージョンと nixpkgs のコミットハッシュが表示される
    https://lazamar.co.uk/nix-versions/
    https://www.nixhub.io/
    最後のリリース、16.20.2の nixpkgs におけるコミットハッシュは 9957cd48326fe8dbd52fdc50dd2502307f188b0d
    例えば以下のようなコマンドで nodejs_16 にパスが通ったシェルが起動する
    (insecure とマークされているため、 NIXPKGS_ALLOW_INSECURE=1 などの設定が必要)
nix-shell -p nodejs_16 -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/9957cd48326fe8dbd52fdc50dd2502307f188b0d.tar.gz
  1. shell.nix の引数や flake.nix の inputs に上記のハッシュを指定した nixpkgs のレポジトリを追加する
    shell.nix ベースで環境を作る場合
shell.nix
let
  pkgs = import <nixpkgs> { };
  pkgs-for-nodejs16 = import (builtins.fetchTarball {
    url = "https://github.com/NixOS/nixpkgs/archive/9957cd48326fe8dbd52fdc50dd2502307f188b0d.tar.gz";
  }) { config.permittedInsecurePackages = [ "nodejs-16.20.2" ]; };
in
pkgs.mkShell {
  buildInputs = [
    pkgs-for-nodejs16.nodejs-16_x
    pkgs.biome
  ];
}

このように nixpkgs のインスタンスはいくつあってもいいため、 nodejs 本体は 16.20.2 に固定しつつ他のツールは最新に追従するということも簡単にできる

flake ベースで環境を作る場合

flake.nix
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    nixpkgs-for-nodejs16.url = "github:NixOS/nixpkgs/9957cd48326fe8dbd52fdc50dd2502307f188b0d";
  };

  outputs =
    {
      self,
      nixpkgs,
      nixpkgs-for-nodejs16,
    }:
    {
      devShells.x86_64-linux.default =
        let
          system = "x86_64-linux";
          pkgs = import nixpkgs { inherit system; };
          pkgs-for-nodejs16 = import nixpkgs-for-nodejs16 {
            inherit system;
            config.permittedInsecurePackages = [ "nodejs-16.20.2" ];
          };
        in
        pkgs.mkShell {
          buildInputs = [
            pkgs-for-nodejs16.nodejs-16_x
            pkgs.biome
          ];
        };
    };
}
natsukiumnatsukium

{ a.b = 1; } と { a.c = 2; } をマージして { a = { b = 1; c = 2; }; } にしたい

単純に { a.b = 1; } // { a.c = 2; } を評価すると a が置き換えられて { a = { c = 2; }; } が得られる

こういうときは lib.attrsets.foldAttrs を使って以下のようにかける
https://github.com/NixOS/nixpkgs/blob/5fbeaf6d89ff1ff08a59a0f0b34d6eb33fb75307/lib/attrsets.nix#L782-L825

lib.foldAttrs (item: acc: item // acc) { } [ { a.b = 1; } { a.c = 2; } ]