2026-06-13
前回 、NixでCLIツールを管理できるようにしました。ワンコマンドで必要なツールが揃うのが快適だったので、せっかくNixを入れたなら、.zshrc や neovim などの設定ファイル(dotfiles)もNixで管理できないか試してみることにしました。
ただ、結論から言うと 設定ファイルはNixで管理せず、これまで通りシンボリックリンクで管理する ことに落ち着きました。
この記事は、実際にNix管理を試してみて、なぜ最終的にシンボリックリンクに戻したのか、という試行錯誤の記録です。
home-managerでは、設定ファイルも配置できます。やり方は大きく2つあって、挙動が違います。
| 書き方 | 挙動 |
|---|---|
source = ./somefile | ファイルをNixストアにコピーしてから配置する。編集するたびに switch が必要 |
source = mkOutOfStoreSymlink "..." | dotfilesの実体に直接シンボリックリンクを張る。編集したら即反映、switch 不要 |
設定ファイルは普段から直接編集するので、switch なしで編集が反映される mkOutOfStoreSymlink(out of store = ストアの外の実体を直接指す)を選びました。home.nix にはこう書きます。
xdg.configFile."nvim" … リンク先(~/.config/nvim)を指定するmkOutOfStoreSymlink "..." … リンク元(dotfilesの実体)を指定するこの時点では、これでNixでも ln と同じようにリンクが張れる、と思っていました。
いきなり全部移すのは不安だったので、まずは neovim の設定だけをNix管理に移してみました。
これまでは、セットアップスクリプトの中で ln コマンドを使って手動でリンクを張っていました。
これを前述の home.nix の書き方に置き換えて switch します。
ここで一つ注意点がありました。~/.config/nvim にはすでに手動で張ったシンボリックリンクが残っているため、このまま switch すると「home-managerが管理していないファイルがある」とエラーになります。なので、先に古いリンクを外してから switch する必要がありました(リンクを外しても、実体はdotfiles側に残るので消えません)。
switch 後、リンクのチェーンを readlink -f で辿ってみると、ちゃんと最終的にdotfilesリポジトリの実体に到達していました。lazy-lock.json(lazy.nvimが書き込むロックファイル)も書き込み可能で、mkOutOfStoreSymlink が狙い通り動いていることが確認できました。
neovimを起動しても設定の読み込みエラーは出ず、移行自体は問題なく完了しました。
……のですが、移行を進めるうちに「これ、わざわざNixでやる意味あるんだっけ?」と思い始めました。引っかかったのは、どちらも「パスの書き方」に関する2点でした。
dotfilesは複数のマシンで使い回したいのですが、マシンによってユーザー名(=ホームディレクトリのパス)が違います。Nixでこれを扱うには、flake.nix でユーザー名を変数として注入し、home.nix 側で ${config.home.homeDirectory} のように組み立てることになります。
設定ファイルを置きたいだけなのに、マシンごとの差分を吸収する仕組みをNix側に足すことになり、だんだん大げさに感じてきました。
mkOutOfStoreSymlink に渡すのは絶対パスです。なので前述の home.nix のように、let でリンク元のパスを最初から組み立てておく必要がありました。
一方、これまでの ln はこうでした。
$(pwd) も $HOME も実行時に解決されるので、絶対パスを自分でハードコードする意識がいりません。symlinkを張るときの「今いる場所から相対的に張る」感覚に近く、こっちの方が素直でした。
結局やりたかったのは「dotfilesの実体にリンクを張る」だけで、それなら ln 一行で済んでいたことを、Nixの記法に置き換えただけ。ユーザー名の注入と絶対パスの組み立てという手間が増えただけで、見合うものが得られていないと感じて、設定ファイルのNix管理はやめることにしました。
前述のユーザー名問題をきれいに解決できそうだったのが chezmoi です。テンプレートでマシンごとに設定の中身を変えられて、秘密情報も暗号化できる。ユーザー名も {{ .chezmoi.username }} という組み込み変数で実行環境から自動取得できるので、Nixのように flake.nix でユーザー名を注入する仕組みは要りません。
これは良さそうだと思ったのですが、結局 chezmoi も採用しませんでした。理由は、ファイルを編集しても即反映されないこと。
chezmoiはシンボリックリンクではなく、ソースから実ファイルを生成してコピーする方式です。
ソースと実ファイルが別物なので、反映には必ずコマンドを挟まないといけません。しかも両方向で手間がかかります。
| 編集する場所 | 反映に必要なコマンド |
|---|---|
| ソースを編集 | chezmoi apply(ホームへ書き出す) |
| ホーム側を直接編集 | chezmoi re-add(ソースへ取り込む) |
自分は ~/.config/nvim/ を直接編集するので、編集のたびに re-add を忘れず実行しないといけません(忘れると次の apply で上書きされて消える)。設定をいじってすぐ試せなくなる。これがどうしても合いませんでした。
シンボリックリンクなら実体は1つなので、編集はそのまま反映されます。username問題は解決できても、即反映されないという一点が大きく、chezmoiは見送りました。
いろいろ試した結果、こういう役割分担に落ち着きました。
ln)設定ファイルに関しては、mkOutOfStoreSymlink で絶対パスを宣言的に組み立てるより、$HOME を実行時に解決してくれる ln の方が素直でした。直接編集してすぐ反映される手軽さも、そのまま残ります。
試しにNix管理へ移した neovim の設定は元に戻し、home.nix の変更も取り消しました。遠回りでした。それでも、設定ファイルはNixに載せない、とはっきり決められたのは収穫です。設定を毎日直接いじるなら、迷わず ln でいい。Nixはツールの管理に集中させる。これが今の自分の結論です。