2026-06-07

NixでCLIツールを管理する

やりたいこと

今回は、Nixを使ってCLIツールを管理できるようにしたいと思います。 今自分はdotfiles で設定を管理しているのですが、CLIツールのインストールは毎回コピペ->実行をしていてちゃんと管理できていません。 Nixを入れることで、ワンコマンドで必要なCLIツールをインストールできるようにしたいと思い、Nixを入れてみることにしました。

Nixを入れてみる

Nixのインストーラにはいくつか種類がありますが、今回はNixOS/nix-installer を選びました。 これはNixOSコミュニティ公式のインストーラで、インストール計画を立ててから実行する作りなので失敗しにくく、合わなければ /nix/nix-installer uninstall 一発で完全に撤去できる手軽さがあります。 加えて、一企業の配布物ではなく本家(upstream)のNixが入る点と、--enable-flakes を付けるだけで依存を固定して再現性を担保する flakes がすぐ使える点が決め手になりました。

インストールは以下のコマンドで行いました。

flake.nix と home.nix を書く

設定ファイルは一から書くこともできますが、home-manager init を使うとテンプレートを自動生成してくれます。

これで nix/ ディレクトリに flake.nixhome.nix の2つが生成されます。役割は以下の通りです。

  • flake.nix … 依存(nixpkgsやhome-manager本体)の取得元と、設定の枠組みを定義する。基本的に最初に書いたらほぼ触らない
  • home.nix … 実際にどんな環境にするか(どのツールを入れるか等)を書く本体。普段いじるのはこちら

init で生成される設定には、homeConfigurations."<ユーザー名>" のように、実行したPCのユーザー名が名前として付きます。ただしこの名前は「設定の識別名」で、自分で自由に変えられます(後述の switch でこの名前を指定します)。今回はユーザー名に依存しないよう、default という名前に変えておきました。

生成直後の home.nix は、使い方のサンプルがコメントで入っているだけで中身は空です。CLIツールを入れるには home.packages に追記します。今回は試しに以下のツールを入れてみました。

このリストに足すだけでツールを増やせるのがポイントです。

switch してみる

設定を書いたら、switch で実際に環境へ反映します。home.packages で宣言したツールがここでインストールされます。

--flake ./nix#default は「nix/ ディレクトリのflakeにある default という設定を使う」という意味です。defaultflake.nixhomeConfigurations.default で定義した名前に対応しています。

初回はnixpkgsなどのダウンロードが走るので少し時間がかかります。完了すると、依存のバージョンを固定した flake.lock が自動生成されます。これをコミットしておくことで、別のマシンでも同じバージョンの環境を再現できるようになります。

なお、flakeはgitに追跡されているファイルしか参照しないため、flake.nixhome.nix は事前に git add しておく必要がある点に注意です。

CLIツールのインストール・アンインストールの方法

home-managerでは、home.nixhome.packages が「インストールしたいツールの一覧」になっています。インストールもアンインストールも、このリストを編集して switch するだけです。

インストール

home.packagespkgs.<ツール名> を1行足します。

そして switch で反映します。

これで fzf~/.nix-profile/bin に入り、使えるようになります。

入れられるツールを探す

入れたいツールがNixで配布されているか(パッケージ名は何か)は、主に2つの方法で調べられます。

1つ目は NixOS Search です。ブラウザでキーワード検索するだけで、パッケージ名・説明・バージョンなどが確認できます。channelを unstable に合わせると、このflake(nixpkgs-unstable)に近い結果になります。眺めながら探すのに便利です。

2つ目は nix search コマンドで、ターミナルから直接 nixpkgs の中を検索できます。

アンインストール

逆に、リストから該当の行を消して switch するだけです。

switch 後、fzf は環境から取り除かれます。apt remove のような専用のアンインストールコマンドは不要です。

ポイント: 宣言的であること

aptやbrewでは「install する」「remove する」という操作を都度実行しますが、home-managerでは「最終的にこのツール一覧であってほしい」という状態home.packages に書き、switch が現実をその状態に合わせてくれます。

そのため、home.nix を見れば「今どのツールが入っているか」が一目で分かり、コミットしておけば「いつ・何を入れた/消した」も履歴として残ります。手作業でのインストールにありがちな「いつの間にか入っていて何だっけ、これ」が起きません。

このパッケージの追加のしやすさがNixを使う大きなメリットの一つだと感じました。

CLIツールのバージョンの更新方法

各ツールのバージョンは、flake.lock が固定している nixpkgs(パッケージの取得元)のバージョンで決まります。言い換えると、ツールは勝手にはバージョンが上がりません。上げたいときは flake.lock を更新します。

ここで重要なのは、Nixは「nixpkgs というスナップショット全体」を更新する点です。nix flake update を実行すると、home.packages のツールがまとめて新しい nixpkgs の時点のバージョンに揃います。aptやbrewのように「特定のツールだけ上げる」のとは考え方が違います。

更新したら flake.lock をコミットしておきます。これで「どのバージョンに上げたか」が記録され、もし更新で不具合が出ても flake.lock を元に戻して switch すれば、前のバージョンに戻せます。

普段はバージョンを固定して安定させ、上げたいときだけ意図的に flake update する。この「いつの間にかバージョンが変わっていた」を防げるコントロールのしやすさも、Nixを使う利点だと感じました。

複数の種類のPCでも同じ環境を作る

ここまでは1台(WSL)向けの default という設定でしたが、せっかくなのでMacでも同じCLI環境をすぐ作れるようにしてみます。まずマシンごとに何が違うのかを整理すると、大きく3つです。

違う点WSL (Linux)Mac
system(CPU + OS)x86_64-linuxaarch64-darwin
ホームディレクトリ/home/<user>/Users/<user>
OS固有パッケージxclip(X11用)不要(pbcopy 内蔵)

逆に、git や neovim などのCLIツールは両OSで共通です。なので「共通部分はそのまま、違う3点だけ切り替える」形にします。

まず flake.nix で、system を受け取って設定を作るヘルパー関数を用意し、マシンごとに名前を付けます。

次に home.nix で、OSによって変わる部分を自動で切り替えます。pkgs.stdenv.isDarwin / isLinux でOSを判定できます。

これで、共通のCLIは1箇所に書くだけで両方のマシンに入り、OS固有の差(ホームパス・xclip)は自動で切り替わります。

なお、ここで使った pkgs.stdenv.isLinux / isDarwin は、nixpkgs が提供する真偽値(bool)の属性です。関数ではないので、if や条件にそのまま置けます。

また ++リストどうしを連結する演算子です。lib.optionals 条件 [...](条件がtrueのときだけそのリストを返す関数)と組み合わせることで、共通のツール一覧に「Linuxのときだけ xclip を足す」という出し分けをしています(Macのときは空リストが連結されるだけなので何も足されません)。

Mac側でやることは2ステップだけです。

ここで効いてくるのが flake.lock です。依存のバージョンが固定されているので、Mac でも WSL と寸分違わぬバージョンのCLIが入ります。「別のPCでもコマンド一つで同じ環境」という当初の目的が、これで実現できました。

やってみてわかったこと

今回Nixを入れてみて、CLIツールの管理がとても楽になりました。特に、「最終的にこのツール一覧であってほしい」という状態を宣言するだけで、インストールもアンインストールもできるのが便利だと感じました。 これで気軽にCLIツールを試せるようになったので、今後はRust製のCLIツールなどを試したり、色々入れてみたいと思います。

参考

Thanks for the visit Nozo Blog