あけましておめでとうございます。 2023年気持ちも新たに、まずはdotfilesの見直しから開始しました。
これまでは、Emacs以外の fish
や git
などのconfigはpCloud経由で管理し、シンボリックリンク経由で利用していました。
またWSL環境やPC/Mac環境の再構築をする中で、config以外の exa
や fzf
といった普段利用しているパッケージのインストールも毎回必要なため、
homebrewやlinuxbrewを含めたインストール手順を実行していました。
これらを一元管理し、更に自動化したいなぁと思いつついつの間にやら数年経っていた^^;ところ、Nixを知りました。 当時NixOSというディストロがあるということは目にしていたのですが、クロスプラットフォーム(Win除く)なNixというパッケージ管理システムがあることは知らず、 今回これはよさそうだということで、重い腰を上げて移行してみることにしました。
Nixとは
Nixは純粋関数的パッケージマネージャです。公式ドキュメントによると、以下のように説明されています。
Nix is a purely functional package manager. This means that it treats packages like values in purely functional programming languages such as Haskell — they are built by functions that don’t have side-effects, and they never change after they have been built.
ちょっとわかりにくいですが、NixにはNix expressionという独自の言語があり、これによって各Nixのパッケージが記述されています。 これはビルド環境や手順、依存関係などを記述するものなのですが、これが関数的言語であり、同一の入力に対して同一の出力を保証しているということを言っていると思われます。
Nixpkgs
この記述されたNixのパッケージ群がNix Packages collection(Nixpkgs)で、いわゆるパッケージリポジトリに相当するものですが、コンセプトにある通りこの中身はNix expressionによる記述の集合です。 実際のパッケージはここから出力されたものが https://cache.nixos.org でcacheされており、可能であればそこから取得できるようになっています。
たとえばnodejsを例にすると、このコードにnodejs.orgからソースを取得して依存関係の解決とビルドする方法がNix expressionで記載されている様子がわかります。
Nix Profiles
NixマニュアルのProfilesに説明があるのですが、パッケージのインストール先は /nix/store
以下に集約され、直接/usr/binなどに展開されません。
更にNixではユーザー環境も同様にNix以下で管理され、version管理されています。各versionに含まれるパッケージの違いを管理することで、環境構成のアトミック性とロールバックの仕組みを担保しているようです。
パッケージの構成管理を記述するためにもNix expressionが利用できます。
~/.config/nixpkgs/config.nix:
にglobal configurationを配置することができ、そこでNixで解決するパッケージを記述できる旨がNixpkgsマニュアルのDeclarative Package Managementに紹介されています。
以前はNixのマニュアルにもconfigに関する記載があったらしいのですが、22.11の今日現在そのような記述はないようです。 Nixはドキュメントが結構散らかっている印象で、初学者には中々把握しずらい印象があります。 実際Hacker Newsなどでもそのようなコメントを見かけることもありましたので、どうもそういうもののようです。
新しいNixのドキュメントプロジェクト nix.dev
(2024/4/11追記)
上記のような学習コストの高さ、ドキュメントの複雑さを解消すべく新しい情報源の整備をするNix Bookというプロジェクトがありました。
ただ気がついたらここは閉鎖されていて、nix.devプロジェクトに統合されていました。
Nixパッケージマネージャのインストール
以下の home-manager
を利用するには、Nixパッケージマネージャをインストールする必要があります。
NixOS以外の各OSもしくはWSL2環境でのインストール方法があり、公式ページに詳細があります。 今回はMac OSに導入するので、以下を実行します。
|
|
これでNixパッケージマネージャを利用できるようになりました。(実際にはnix-shellなども使えるので純粋にパッケージマネージャだけでもない)
home-manager
home-managerは上記のNixパッケージマネージャを利用して、ローカルユーザー環境で利用するパッケージの管理とdotfilesを一元的に管理するための仕組みです。
単純に必要なパッケージを記述、管理できるだけでなく、例えば .config/fish/config.fish
ファイルや .config/git/config
ファイルなどもNix expressionの中に一緒に書き込んで管理できる特徴があります。
インストール
MacOSへのインストールでは、standalone installationに従ってインストールを行います。
NixのChannelとして、home-managerに必要なパッケージがまとめられていますので、それを追加します。 masterブランチをターゲットにすることもできますが、私は最新のリリースバージョンで固定して追加します。
|
|
マニュアルには以下の設定もした方がよいとあります。
NIX_PATH
はNixがパッケージが検索をするためのPATHのようで、どうもここに上記で設定したユーザーのChannel設定が通っている必要があるようです。
|
|
そして、home-mamagerをインストールします。
|
|
最後に、 hm-session-vars.sh
のソースをするように設定します。
これは、中身を見るとわかりますが、home-managerで設定したdotfilesの結果必要になった環境変数が書きこまれるファイルのようです。
つまりこれをシェルのconfigなどに記述しておかないとhome-managerの設定が一部反映されなくなるようなので注意が必要です。
home.nixの記述
home-managerのインストールが完了すると、 .config/nix/home.nix
が以下の雛形で生成されています。
|
|
ここに、自身で必要なパッケージとdotfilesの記述をしていきます。
パッケージ単体だけ
ripgrep
などのようにパッケージインストールだけでよいものは、以下のように記述を追加していくだけです。
|
|
何らかのconfigも一緒に記述したいもの
git
のようにconfigファイルやプラグイン、環境変数設定なども一緒に管理する必要があるものは programs
を利用します。
|
|
どのような programs
がどのようなconfigを持っているのかは、home-managerリポジトリのmodules/programsを直接参照するとわかります。
パッケージとdotfilesの反映
準備ができたら、アクティベーションを実行します。
|
|
このとき、もし既存のconfigなどがある場合はエラーしますので退避しておく必要があります。
生成されたconfigは /nix/store/0z7f1q...-home-manager-files/.config/git/config
のようにNixストアへのシンボリックリンクになっており、直接編集はできません。
あくまでも編集は home.nix
で実施し、それを反映させていく、という運用になります。
編集の履歴はNixの仕組みで管理されており、
|
|
とすると、それまでの生成されたconfigの履歴を確認することができます。 またNixの仕組みでロールバックすることもできるようになっています。
まとめ
Nix+home-managerによるパッケージとdotfilesの管理への移行についてまとめてみました。 基本的なシェル環境はこれですっきり包括的に管理できるようになった印象があります。
なお、Emacsはここに混ぜるとちょっと扱いにくそうだったので別管理のまま除外しています。 また、シェル環境以外の設定(.e.g AlfredのconfigやKalabinerのconfigなど)はこのスキームに乗せられないため引き続き別の手段が必要そうです。
2023年は継続利用して育てていきつつ、いずれPCの乗り換えなどでその効果を実感できるんじゃないかと期待しています。