Nixでいい感じのdevShellを使うまで
devShell とは
NixにはdevShellという便利な機能があります。devShellはプロジェクトで定義した依存を読み込んだシェル環境(?)のことで、これを使うとプロジェクトの依存に基づいた、かつグローバルからは隔離され独立した環境を定義できます。
でも
便利そうだから使いたいな〜と思っていたものの、具体的にどうすればいいのかが私には全然わかりませんでした。 そもそもNixはまだ手探り状態だし、調べたら nix-shell とか nix develop とか色々出てくるし、いざnix develop してみたら bash しか立ち上がらないし...
devShellを実用するには、せめて普段使っているシェルの環境のままで使えるようにしたいですよね。 依然としてNixのことは全然わかっていませんが、devShellがいい感じに使える方法にたどり着いたのでその方法を記しておこうと思います。
Nixまわりはいろんな情報が散らばりまくっていてしんどいので、「こうしたほうがいいですよ〜」とか、「これ読むといいですよ〜」とかがあればぜひ教えてください。
こうすれば動く
次のようにやってみたらいい感じになりました。以下でそれぞれ説明していきます。
- direnv をインストールする
- プロジェクトに flake.nix を作り、依存・devShell を定義する
- devShell を立ち上げたいプロジェクトで
use flake
と記した.envrc
を用意する
direnv をインストールする
direnv は、環境ごとに読み込む環境変数などをいい感じにやってくれるツールです。 私はhome-managerでインストールしました:
{ programs.direnv = { enable = true; nix-direnv.enable = true; }; }
プロジェクトに flake.nix を作り、依存やdevShell を定義する
対象となるプロジェクトにてflake.nixを作り、依存を定義しておきます。
たとえばNode.jsを扱うプロジェクトだと、flake.nix
は次のようになります。
flake.nix
:
{ description = "..."; inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixos-23.11"; flake-utils.url = "github:numtide/flake-utils"; }; outputs = {nixpkgs, flake-utils, ...}: let utils = flake-utils; in utils.lib.eachDefaultSystem(system: let pkgs = nixpkgs.legacyPackages.${system}; in { formatter = pkgs.nixpkgs-fmt; devShell = pkgs.mkShell { nativeBuildInputs = with pkgs; [ nodejs-slim_20 corepack_20 yarn ]; }; } ); }
devShell を立ち上げたいプロジェクトでuse flake
と記した .envrc
を用意する
echo "use flake" > .envrc
すると
この設定ができると、cd でプロジェクトのディレクトリに入るだけでdevShellに定義した依存がactivateされ使えるようになり、シェルもzshのまま使えます。
番外編
devShellを用いた開発を運用するにあたり、次のような設定も行いました。
gitignore
グローバルで.direnv/
と.envrc
をignoreするようにしました。
{ programs.git = { # ... ignores = [ ".envrc" ".direnv/" ]; }; }
VSCode
ファイルエクスプローラ及びファイル検索において、.direnv
の内容を表示しないようにしました。
settings.json
:
{ "files.exclude": { "**/.direnv": true }, "search.exclude": { "**/.direnv": true } }
おわりに
Nixは情報がいろんな場所に散らばっていて大変だと思いました。アドバイス等あればぜひ教えてください!!!