Open7

[chezmoi / Nix / aracritty / zellij / fish / neovim] dotfiles v2025

RentalCatRentalCat

環境を一新したい。ヤクの毛刈りは大変だが頑張ってく。

要件

  • マルチプラットフォーム対応 (x86_64-linux, aarch64-linux, aarch64-darwin に対応)
  • 仕事用・個人用PCの管理を一元化
  • gitにてバージョン管理が行える

開発環境

  • Apple M3 Pro | Sequoia 15.3

使うツール類の選定理由とか

  • chezmoi: 上記プラットフォーム、{仕事用 | 個人用} の設定を書き分けれるように
    • パスワードの管理などは 1Password を使う
  • Nix : オーバーヘッドの少ない 再現性・冪等性を維持した環境構築を担保
  • aracritty: 軽量・高速なターミナル。設定がファイルにて完結するのが ◎
  • zellij: ターミナルマルチプレクサ。普段利用している tmux を使い続けるか悩んだが、新しい風にふれてみたかったので採用。
  • fish: シェル。普段愛用している zsh を使い続けるか悩んだが、新しい風に(ry
  • neovim: 体の一部

参考になった記事の皆様 (感謝)

https://zenn.dev/airrnot1106/scraps/20e6a33574229f
同じく Nix + chezmoi で dotfiles を整えようとした先人様。ぜひこの記事も読んで。
https://zenn.dev/kawarimidoll/articles/0a4ec8bab8a8ba
https://zenn.dev/kawarimidoll/articles/9c44ce8b60726f
https://zenn.dev/kawarimidoll/articles/271c339c5392ce
上の記事でも紹介にあった Nix での dotfiles 管理を体系立てて解説してくれる素晴らしい方。これも読んで。

RentalCatRentalCat

基礎知識のお勉強 (個人的に新規技術なのでよく分かってない)

chezmoi って何よ。

  • dotfiles を Git 管理しつつ、安全かつ効率的に管理・同期するためのオープンソースツール
  • 以下が特徴だそうな
    • 安全性:リポジトリに機密情報を含めないように設計
    • 柔軟性:テンプレート機能を使って、環境に応じた設定が可能
    • 簡単な導入:シンプルなコマンドでセットアップ可能
    • クロスプラットフォーム:Windows、macOS、Linuxで動作
  • stowyadm とは異なり、秘密情報の管理 (1Password 連携) やリモート適用 (chezmoi apply) が可能
  • シンボリックリンクではなく、ファイルを直接適用する方式
    • ~/.config 等にファイルをデプロイする。個人的には「修正したのに反映されない」みたいな現象を招くのでシンボリックリンクのほうが好みだったりする。ちょっと不安要素。
  • 学習コストは他類似技術と比べ高めなので頑張る。

Nix って?

  • 宣言型のパッケージ管理システムで、環境の再現性と依存関係の分離を実現
  • aptbrew とは異なり、複数バージョンのソフトウェアを共存可能
  • 各設定バージョン毎に設定ディレクトリを用意することで冪等性やらスクラップビルドに対応しているっぽい
    • 今まで docker を使って開発環境を整えてたが、仮想環境なためオーバーヘッドが目立っていた。Nixではそれが軽減できそう
  • 名前の似ている NixOS は OS 全体を Nix で管理するOS。Mac や他 Linux では nix 単体で使用する
  • 学習コストは他類似技術と比べ バリクソ高めなのでめっちゃ頑張る。

Zellij ?ゼリー…の一種?

  • tmux の代替として設計されたターミナルマルチプレクサで、モダンな UI とプラグインシステムを搭載
  • 読み方は「ゼリージュ」だったり「ゼリッジ」だったり。言語の由来は「タイルを組み合わせた幾何学模様」のことらしい。
  • tmux に比べ、デフォルトの操作性が直感的で設定ファイルがシンプル (kdl フォーマット)
    • ...って言うが、本当だろうか…。独自フォーマットに良い経験がないので懐疑的。
  • wezterm の multiplexer 機能と比較すると、より拡張性が高く CLI で完結可能
    -まだ tmux ほどの安定性はないが、面白そうなので触ってみたい (重要)

fish とは?

  • bashzsh に比べ、構文がシンプルで、補完やシンタックスハイライトが標準装備
  • zsh のようなプラグイン管理 (oh-my-zsh) が不要で、デフォルトの機能が充実
  • POSIX 非互換のため、一部のスクリプト (sh, bash 用) がそのまま動かない点がデメリット
    • このあたり問題ないかは気になる。ただ、社内で使ってる人が散見するあたり問題ない気がする (楽観)
  • xonshnushell もモダンなシェルなので対抗馬
    • xonsh: コンシュ? python 上で shell を実行する。面白そうだけど普段使いできるレベルまで枯れているのかは不明なので見送り。
    • nushell: Rust 製shell で初期から ls がきれいに整形されていたりQueryライクの絞り込みがつおい。ただ、他人への共有や他環境 (サーバー内) で使えないのでちょっと微妙か。今回は一旦見送り、落ち着いたら使ってみたい。
RentalCatRentalCat

ChatGPTは偉大だ。適当に要件を書くとそれらしい解決策を出してくれる。
とはいえ人ならざる者の言の葉なので鵜呑みにせず真偽を確認しながら見ていくのが良き。

以下ChatGPT君が出してくれたセットアップ方法。

1. dotfiles リポジトリ作成

Github/GitLab 等で適当なリポジトリを用意しておく (中身は空っぽでOK)

2. chezmoi セットアップ

(1) install

ref: https://www.chezmoi.io/install/

sh -c "$(curl -fsLS get.chezmoi.io)" -- -b $HOME/.local/bin
# パスが通ってないので一時的に通しておく (恒久的には後ほど設定予定)
PATH=$HOME/.local/bin:$PATH

(2) 初期化

# chezmoi を先ほど用意した dotfiles リポジトリと紐づけて初期化
chezmoi init git@github.com:yourusername/dotfiles.git

# chezmoi を環境に反映 (この時点では対象となる設定ファイルが存在しないので何も起きない)
chezmoi apply

これで dotiles リポジトリが $HOME/.local/shere/chezmoi/ 以下に配置される
このディレクトリには chezmoi cd で移動できる。
(個人的にまだ chezmoi コマンドに不慣れなので $HOME 直下にシンボリックリンクを追加してる。慣れたら消す予定)


このあと、config 関係のファイルを dotfiles/.chezmoi に詰め込んでいくが、先にアプリケーションを追加していきたいので Nix の設定を行う。

RentalCatRentalCat

3. Nix を使った環境構築

(1) Nix のインストール

ref: https://zero-to-nix.com/start/install/

curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
RentalCatRentalCat

(2) flake.nix の作成

flake.nix (古いよ)
{
  description = "My dotfiles managed with Nix and chezmoi";

  # inputs: 依存する外部 Flake の定義
  inputs = {
    # Nix パッケージコレクションを取得
    #   最新パッケージやApple Silicon (aarch64-darwin) の互換性を確保するため
    #   https://search.nixos.org/packages の unstable 版を見に行く
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };
  # outputs: この Flake が提供する成果物を記述
  outputs = { self, nixpkgs, ... }: 
    let
      system = "aarch64-darwin";  # 現在の実行しているOSシステム (後日自動化したい)
      pkgs = import nixpkgs { inherit system; };  # ↑に対応しているパッケージ
    in {
      packages.${system}.my-packages = pkgs.buildEnv {
        name = "global-package-list";
        paths = with pkgs; [
          chezmoi
          git
          neovim
          zsh
          tmux
          alacritty
          nerdfonts
        ];
      };
    };
}

トラブルシューティング error: path '/nix/store/...-source/flake.nix does not exist`

上記 flake.nix を動かそうと nix profile install .#my-packages を叩いてもエラーが出てしまい動かない…
どうやら git 管理下のディレクトリ内だと git add しておかないと読み込んでくれないらしい。なーるほど
https://qiita.com/suin/items/e265f74c4aa6498b2115
沼って nix を reinstall したりで2時間ほど無駄にした。あるある。

現状の flake.nix ファイルの課題

  • system が直書き
    • builtins.currentSystem を使って自動取得する
    • builtins.currentSystem はNixが純粋評価モードでは利用できないとのこと。まぁ確かに外部状態に影響されると純粋とは言えないし。
    • forAllSystems パターンで全 system 分の定義を行うのが良さそう
  • 更新する際のコマンドが2つになる
    • nix flake update && nix profile upgrade my-packages
    • apps.${system}.app-name を定義して nix run .#app-name で起動できるようにする
  • alacritty などのGUIアプリが $HOME/.nix-profile/bin 配下になってしまう
    • /Applications 配下ではないので起動に不便。
    • nix-darwin を使ってインストールする
RentalCatRentalCat

↑のスクリプトをちょっと修正 (半日かかった)

やったこと

  • 管理方式を nix flake から Home Manager + nix-darwin に変更
    • nix flake だと設定ファイルの内容をインストールはしてくれるが、項目を消しても削除はしてくれない
    • Home Manager + nix-darwin は「環境を switch する」という考え方なのでこっちのほうがスクラップビルドしやすい。
  • nix formatter 追加
  • 更新コマンドを整備
    • nix run (.#default) に更新コマンドをまとめた。今後これ1つでOK
    • 他、よく使うコマンドを nix run にまとめたが、どちらかと言うと備忘録代わり。なくても良い
  • Home Manager 設定都合 $USER 環境変数が欲しかったが 、ここでも Nix の純粋評価モードがネックに
    • 可能ならこのまま純粋評価を維持したかったが実装に難があるので泣く泣く --impure オプション付与
    • (…--impure つけたら↑で諦めた system の自動取得できるのでは?後で試してみる)
成果物 (diffはすごいことになってたので省略)
./flake.nix
{
  description = "My dotfiles managed with Nix and chezmoi";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    nix-darwin = {
      url = "github:LnL7/nix-darwin";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
      home-manager,
      nix-darwin,
      ...
    }@inputs:
    let
      system = "aarch64-darwin";
      pkgs = import nixpkgs { inherit system; };
      config_name = "my-config";
    in
    {
      # nix file formatter
      formatter.${system} = pkgs.nixfmt-rfc-style;

      # nix custom scripts
      apps.${system} = {
        # nix run (.#default) : run update script
        default = {
          type = "app";
          program = toString (
            pkgs.writeShellScript "update-script" ''
              set -e
              echo "❄️ Updating flake..."
              nix flake update
              echo "❄️ Switch: Home Manager..."
              nix run nixpkgs#home-manager -- switch --flake .#${config_name} --impure
              echo "❄️ Switch: nix-darwin..."
              nix run nix-darwin -- switch --flake .#${config_name} --impure
              echo "❄️ Update complete!"
            ''
          );
        };
        # nix run .#fmt : format all nix script
        fmt = {
          type = "app";
          program = toString (
            pkgs.writeShellScript "format-script" ''
              set -e
              echo "❄️ Formatting nix files..."
              nix fmt ./**/*.nix
              echo "❄️ done."
            ''
          );
        };
        # nix run .#gc : garbage collect nix store
        gc = {
          type = "app";
          program = toString (
            pkgs.writeShellScript "gc-script" ''
              set -e
              echo "❄️ Garbage collectting nix store..."
              nix store gc
              echo "❄️ done."
            ''
          );
        };
      };

      homeConfigurations."${config_name}" = home-manager.lib.homeManagerConfiguration {
        inherit pkgs;
        extraSpecialArgs = {
          inherit inputs;
        };
        modules = [ ./home ];
      };

      darwinConfigurations."${config_name}" = nix-darwin.lib.darwinSystem {
        inherit system;
        modules = [ ./nix-darwin ];
      };
    };
}
./home/default.nix
{ pkgs, ... }:
let
  inherit (import ../environment.nix) username;
in
{
  nixpkgs = {
    config = {
      allowUnfree = true;
    };
  };

  home = {
    username = username;
    homeDirectory = "/Users/${username}";

    packages = with pkgs; [
      git
      neovim
      fish
      tmux
    ];

    # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
    stateVersion = "24.11";
  };

  programs.home-manager.enable = true;
}
./nix-darwin/default.nix
{ ... }:
{
  system.stateVersion = 6;
  nix.enable = false;

  # homebrew
  homebrew = {
    enable = true;
    onActivation = {
      autoUpdate = true;
      cleanup = "uninstall";
    };
    casks = [
      "alacritty"
    ];
  };
}

気になったこと

nix-darwin で nix 自体の管理をしようとしたら怒られた。

error: Determinate detected, aborting activation
Determinate uses its own daemon to manage the Nix installation that
conflicts with nix-darwin’s native Nix management.

To turn off nix-darwin’s management of the Nix installation, set:

    nix.enable = false;

This will allow you to use nix-darwin with Determinate. Some nix-darwin
functionality that relies on managing the Nix installation, like the
`nix.*` options to adjust Nix settings or configure a Linux builder,
will be unavailable.

どうやら Determinate Nix との管理が競合してるらしい。
一旦エラー文通り nix.enable = false; にして管理から除外した。
今後どちら側に寄せるかを調整していきたい。

RentalCatRentalCat

ここから作業を alacritty に寄せたいので優先的に config 整備

alacritty設定

既存の alacritty 設定ファイルをchezmoi 管理下に追加

chezmoi add ~/.config/alacritty

.chezmoiignore 用意

chezmoi managed で簡易一覧を確認できる…が、このままだと dotofile リポジトリ配下 ($HOME/.local/share/chezmoi/nix) すべてのファイルが出てくるので、.chezmoiignore ファイルを作成

.chezmoiignore
# Repository Documents
LICENSE
README.md
doc

# nix setting
environment.nix
flake.lock
flake.nix
home
nix-darwin
$ chezmoi managed
.config
.config/alacritty
.config/alacritty/alacritty.toml
.config/alacritty/font.toml
.config/alacritty/themes
.config/alacritty/themes/iceberg.toml
ちなみに、現在の alacritty 関連の設定ファイル
alacritty/alacritty.toml
# setting of Alacritty
# ref: https://alacritty.org/config-alacritty.html

[general]
import = [
  "./font.toml",
  "./themes/iceberg.toml",  # ref: https://github.com/seahal/iceberg_theme_for_alacritty/blob/master/iceberg.yml
]
live_config_reload = true

[window]
decorations = "Buttonless" 
startup_mode = "Maximized"
opacity = 0.80
blur = true

[scrolling]
history = 0  # using tmux's history

[cursor]
style = { shape = "Beam", blinking = "off"}

[keyboard]
bindings = [
  { key = "¥", chars = "\\" },
]
alacritty/font.toml
[font]
# default font size
size = 18

normal = { family = "MesloLGM NErd Font Mono", style = "Regular" }

フォント周り対応

フォントがないぞとエラーが出てきたので対応

./nix-darwin/default.toml
-{ ... }:
+{ pkgs, ... }:
 {
    ...
+  # fonts
+  fonts = {
+    packages = with pkgs; [
+      nerd-fonts.meslo-lg
+    ];
+  };
 }