Skip to main content
  1. Entry/

開発マシンの環境セットアップをAnsibleからNixに移行した

有給消化期間中に前から気になっていたNixを使い始めたはなし。

fastfetchの出力

Ansibleによるセットアップ #

以前はAnsibleを使ってMacbookをセットアップしていた。 正直特に不満はなく、足りない部分は自分でモジュールを書いたりして便利に使っていた1

不満点があるとすれば、Ansibleのplaybookを管理しているgitリポジトリをprivateにしていたこと。 ssh用の秘密鍵やGitHubのtokenなど、秘密情報はAnsible Vaultで暗号化して保存していた。 暗号化しているとはいえ秘密情報は秘密情報なので、publicにする気にはならなかった。 privateなので、当然playbookを直接共有することができず、不便を感じていた。 ただ、これは秘密情報をどう扱うかという構成に関する不満であって、Ansibleに対する不満ではないのはお察しの通り

Nixに移行した理由 #

秘密情報の管理については、以下の記事を参考に一昨年頃から1Passwordを参照する方法に置き換えていった。

この方法なら、git管理下のファイルには1Password上のIDのみを書けばよく、暗号化したものを含めて直接書く必要はなくなる。 つまりgitリポジトリを丸ごと公開しても問題がないということになる。

とはいえ、すでにAnsible Vaultとして暗号化したファイルのコミットログがあるリポジトリをそのまま公開するわけにはいかない。 どうせリポジトリを作り直すなら別の管理方法にしてみるかと思い立ったのが去年の秋頃2

当時自分の観測範囲内にちらほら登場するようになったNixが気になっていたのと、 ちょうど同じタイミングでNix meetup #1が開催されることを知り、これに参加したというのが決め手になった。

Nixへの移行 #

NixとNixOSの違いもわからない状態から始めたので、まともに使えるようになるまで時間がかかった。 リポジトリは以下にある。

Nixの設定にはnix langという言語を使う。 nix langは動的型付けな関数型言語(らしい)。 nixでインストールできるパッケージのインストール設定もすべてnix langで書かれており、再現性が高い(らしい)。

特に特徴的なのは、異なるバージョン(ソフトウェアのバージョンだけでなく、ビルドオプションなども含む)のパッケージはすべて異なるものとしてインストールされること。 /nix/store 以下に、パッケージ依存ツリーに含まれるパッケージのすべてのバージョンが保存されている。 例えば、手元の環境では openssl-3.3.2 だけで6種類のバージョンが存在する。

❯ ls /nix/store/ | rg 'openssl-3.3.2$'
1a4j0c5xn6xl53z77sifkncg3fing1qj-openssl-3.3.2
8ms7abrwg2nbqdjdcdf1aig4y7yha4v7-openssl-3.3.2
hfn95nq7wr6sidn5vridlk1a4drira0r-openssl-3.3.2
hx7ksp6xyw385k3wlvng15sd4s15vr0i-openssl-3.3.2
qm16x7kk34j7b6h90dfpj30fjazsswpv-openssl-3.3.2
rm2ss9qyvxad4q9iwdqanil25pj1rqwv-openssl-3.3.2

これにより、依存対象の非互換によりパッケージのインストール及び動作に支障が出ることがない、というのがウリらしい。

パッケージのインストールやファイル類の配置はhome-managerで、 Mac固有の設定はnix-darwinで行うのが一般的なようだ。 nix-darwinからはHomebrewのパッケージをインストールすることができるので、必要なものはほぼ間違いなく網羅できる。

もともとAnsibleで環境をセットアップしていたので、そこからmigrate的なことをする手もあるにはあったが、 今回は勉強のためにも一から少しずつセットアップしていった。

公式のドキュメント、および先人の記事に大変の世話になった。 以下に参考にさせていただいた資料のURLを挙げる:

Nixに移行してよかったこと #

移行してよかったことを挙げてみる。

設定対象範囲が広い #

まずはパッケージの種類が豊富なところ。 必要なものはたいていパッケージ化されている。 パッケージの総数、及びメンテナンスされているパッケージ数は、他のパッケージ管理ツールと比べて群を抜いて多いらしい。

https://repology.org/repositories/graphs より
パッケージマネージャごとの、パッケージ数(横軸)と更新されているパッケージ数(縦軸)のグラフ

Mac固有の設定を扱う nx-darwin は、defaultsの変更も宣言的に行うことができる。 たとえば、キーリピート速度の変更やDockの表示位置変更など、設定アプリから変更する内容はたいてい記述することができる3。 新しいMacをセットアップする際に、毎回ポチポチと設定変更していたものが nix-darwin switch コマンド一発で設定できるのは非常に楽。

Language Serverの対応 #

nix lang用のLanguage Serverが提供されているのも便利。 現在はnixdnilがよく使われているようだ。

VSCodeであればNix IDEを、 Zedならnix language supportを入れれば手軽に利用することができる。

syntax checkはもちろん、インストールされるパッケージのバージョンまで表示されるのが面白いところ。

inlay hintとしてパッケージのバージョンが表示される

依存解決 #

Nix特有の、パッケージの依存が壊れないというメリットももちろんあるが、壊れないということは何もおこらないということなので、直接的に恩恵を感じにくい。 もちろん、平和なのはいいことである。

Nixに移行するときに苦労したこと #

Nixにしてよかったことばかりではなく、不便に感じている点もある。 ただし、これらはまだNixとの付き合い方に慣れていないことから生じている可能性も大いにある。

気軽に設定ファイルを弄りにくい #

Nixで配置したファイルは、全て /nix/store 以下へのsymlinkとなる。

❯ ls -l ~/.config/git
total 0
lrwxr-xr-x@ 1 nagata-hiroaki  staff  81 Feb 11 08:01 config -> /nix/store/4ynh4s1g5c97as5n979lmi52n9xx56df-home-manager-files/.config/git/config
lrwxr-xr-x@ 1 nagata-hiroaki  staff  81 Feb 11 08:01 ignore -> /nix/store/4ynh4s1g5c97as5n979lmi52n9xx56df-home-manager-files/.config/git/ignore

また、 /nix/store 以下のファイルは全てreadonlyとなっている。

❯ ls -l /nix/store/ | head -5
total 456752
-r--r--r--@   2 root            nixbld      3206 Jan  1  1970 001gk5gmc1yyj4anm2cbndlw1l427kjj-requests-2.32.3.tar.gz.drv
-r--r--r--@   2 root            nixbld      3187 Jan  1  1970 0021g3y6nccaf9qm7sic3h3jq6i3scq7-lcms2-2.16.tar.gz.drv
-r--r--r--@   2 root            nixbld      3743 Jan  1  1970 003zs7gd0zaprnpvfdg2ix6m20fqi4x1-source.drv
-r--r--r--@   2 root            nixbld      5105 Jan  1  1970 004527k24fxsaillq3bfrij80m6qqgv9-python3.12-pytest-7.4.4.drv

不用意な変更が入らないので構成が壊れないという利点はあるのだが、 試行錯誤中の設定ファイルなどはこれでは不便。 ちょっと設定をいじるたびに毎回 nix-darwin switch するのは効率が悪い。

/nix/store にバージョンごとにコピーしてsymlink、というのはNixの基本方針でもあるので、これを回避するのは難しそう。 仕方がないので変更が多いファイルについてはNixでは配置せず、適宜リポジトリ管理下のファイルに内容をコピーすることにしている4

デスクトップアプリがアプリケーション一覧に表示されない #

これは昔からある問題のようだ。

例えば programs.vscode.enable = true; とするとVisual Studio Codeがインストールされるのだが、 これが /Applications あるいは ~/Applications にsymlinkされないのが原因のようだ。

❯ ls -l /nix/store/mdlr8182am37p84y5nf57wgrn18wgqja-vscode-1.94.2/Applications/
total 0
dr-xr-xr-x@ 3 root  wheel  96 Jan  1  1970 Visual Studio Code.app

アプリケーション一覧に表示されないということは、Alfredからのアプリケーション起動もできないということなので困ってしまう5

上記のissueではあれやこれやして Applications ディレクトリにsymlinkする方法が議論されているが、 面倒なのでデスクトップアプリは nix-darwin 経由の Homebrew インストールしてしまっている。 Homebrew によるインストールであれば /Applications にsymlinkされるので、アプリケーション一覧にも問題なく表示される。

/nix/store 以下が肥大化する #

Nixでインストールしたパッケージは、依存関係にあるものはバージョン違いのものも全て /nix/store に保存される。 これにより依存に関する問題を回避しているわけだが、複数バージョンのパッケージが同時にインストールされている状態になるため、当然 /nix/store 以下が肥大化する。

手元の環境では /nix/store が 13GB になっていた。

❯ du -sh /nix/store
 13G	/nix/store

ちなみに、数年使っているHomebrew管理の /opt/homebrew は 12G だった。

❯ du -sh /opt/homebrew
 12G	/opt/homebrew

適当なタイミングで nix store gc することで不要になったパッケージを削除することはできる。

これから #

先日、転職に伴う支給PCのセットアップがあり、その際に今回整備したNixによる環境セットアップをまっさらなMacbook上で実施する機会6があった。 一発ではうまくいかなかったものの、それを受けての修正もできたので、十分実用できる段階に持ってこれていると思う。

できればCodespacesのセットアップもNixで行いたいところだが、 現職ではCodespacesの出番がないのでモチベーションが低い・・・。

CPUのアーキテクチャとか、ホームディレクトリのパスとか、 マシンごとに固有の設定をしたい場合にどうやるのかがまだわかっていないので、そのあたりは改善の余地がある。

NixOSを触ってみたい気持ちもあるのが、触ってみる以外の用途があるかというと、あるかなぁ。

おわりに #

環境セットアップの手段をAnsibleからNixに移行して、今のところは満足している。 固めの設定ができていることを実感できるし、何より新しいツールを触るのは楽しい7

Nix meetup #2もあるようなので、都合をつけて参加したいところだが・・・行けるかな?


  1. ghqでリポジトリをcloneしてくるモジュールや、 homebrew-gomodするモジュールなど。 簡単なPythonのコードを書けばいいだけなので、気軽に追加できる。 ↩︎

  2. 1Password管理にしてから1年ほど経っているわけだが、その間新しいPCをセットアップする機会がなく、やる気が出なかったのである。 M1 Macbookが快適すぎるのがいけない。 ↩︎

  3. 例えばこのあたり https://github.com/handlename/dotfiles/blob/d57731a1bd4aa9e13ab865d77c4dccaa3bc00205/darwin.nix#L17-L48 ↩︎

  4. 現状ではZedの設定ファイルがそれにあたる。 リポジトリ管理下にはあるが、moduleをimportする部分はコメントアウトしている。 ↩︎

  5. 実際にはエディタやブラウザなど、常用するアプリケーションの起動・切り替えにはBetter Touch Toolによるキーバインドを設定しているので、 それらを使う分には問題はなかったりする。 とはいえそうではないアプリケーションもインストールしたいので、アプリケーション一覧に表示されないのはやはり困る。 ↩︎

  6. 実はPC納品タイミングの関係で、最初の1週間は仮の支給PCを使っていた。 つまり1週間で2回、まっさらなMacbookをセットアップする羽目になったのだが、おかげで十分にテストをすることができた。 ↩︎

  7. Ansibleを触り始めたのも、当時仕事で使っていたChefではないものを使いたかったというのが理由。 ↩︎