2026-06-07
今回は、Nixを使ってCLIツールを管理できるようにしたいと思います。 今自分はdotfiles で設定を管理しているのですが、CLIツールのインストールは毎回コピペ->実行をしていてちゃんと管理できていません。 Nixを入れることで、ワンコマンドで必要なCLIツールをインストールできるようにしたいと思い、Nixを入れてみることにしました。
Nixのインストーラにはいくつか種類がありますが、今回はNixOS/nix-installer を選びました。
これはNixOSコミュニティ公式のインストーラで、インストール計画を立ててから実行する作りなので失敗しにくく、合わなければ /nix/nix-installer uninstall 一発で完全に撤去できる手軽さがあります。
加えて、一企業の配布物ではなく本家(upstream)のNixが入る点と、--enable-flakes を付けるだけで依存を固定して再現性を担保する flakes がすぐ使える点が決め手になりました。
インストールは以下のコマンドで行いました。
設定ファイルは一から書くこともできますが、home-manager init を使うとテンプレートを自動生成してくれます。
これで nix/ ディレクトリに flake.nix と home.nix の2つが生成されます。役割は以下の通りです。
flake.nix … 依存(nixpkgsやhome-manager本体)の取得元と、設定の枠組みを定義する。基本的に最初に書いたらほぼ触らないhome.nix … 実際にどんな環境にするか(どのツールを入れるか等)を書く本体。普段いじるのはこちらinit で生成される設定には、homeConfigurations."<ユーザー名>" のように、実行したPCのユーザー名が名前として付きます。ただしこの名前は「設定の識別名」で、自分で自由に変えられます(後述の switch でこの名前を指定します)。今回はユーザー名に依存しないよう、default という名前に変えておきました。
生成直後の home.nix は、使い方のサンプルがコメントで入っているだけで中身は空です。CLIツールを入れるには home.packages に追記します。今回は試しに以下のツールを入れてみました。
このリストに足すだけでツールを増やせるのがポイントです。
設定を書いたら、switch で実際に環境へ反映します。home.packages で宣言したツールがここでインストールされます。
--flake ./nix#default は「nix/ ディレクトリのflakeにある default という設定を使う」という意味です。default は flake.nix の homeConfigurations.default で定義した名前に対応しています。
初回はnixpkgsなどのダウンロードが走るので少し時間がかかります。完了すると、依存のバージョンを固定した flake.lock が自動生成されます。これをコミットしておくことで、別のマシンでも同じバージョンの環境を再現できるようになります。
なお、flakeはgitに追跡されているファイルしか参照しないため、flake.nix や home.nix は事前に git add しておく必要がある点に注意です。
home-managerでは、home.nix の home.packages が「インストールしたいツールの一覧」になっています。インストールもアンインストールも、このリストを編集して switch するだけです。
home.packages に pkgs.<ツール名> を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を使う大きなメリットの一つだと感じました。
各ツールのバージョンは、flake.lock が固定している nixpkgs(パッケージの取得元)のバージョンで決まります。言い換えると、ツールは勝手にはバージョンが上がりません。上げたいときは flake.lock を更新します。
ここで重要なのは、Nixは「nixpkgs というスナップショット全体」を更新する点です。nix flake update を実行すると、home.packages のツールがまとめて新しい nixpkgs の時点のバージョンに揃います。aptやbrewのように「特定のツールだけ上げる」のとは考え方が違います。
更新したら flake.lock をコミットしておきます。これで「どのバージョンに上げたか」が記録され、もし更新で不具合が出ても flake.lock を元に戻して switch すれば、前のバージョンに戻せます。
普段はバージョンを固定して安定させ、上げたいときだけ意図的に flake update する。この「いつの間にかバージョンが変わっていた」を防げるコントロールのしやすさも、Nixを使う利点だと感じました。
ここまでは1台(WSL)向けの default という設定でしたが、せっかくなのでMacでも同じCLI環境をすぐ作れるようにしてみます。まずマシンごとに何が違うのかを整理すると、大きく3つです。
| 違う点 | WSL (Linux) | Mac |
|---|---|---|
| system(CPU + OS) | x86_64-linux | aarch64-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ツールなどを試したり、色々入れてみたいと思います。