chezmoiでdotfilesを管理する
- 投稿した日
- 更新した日
- 書いたひと
- ひらたけ
.zshrc
や .bashrc
など、ホームディレクトリに存在している ドットから始まるファイル群を管理するリポジトリ として「dotfiles」というものがあります。毎日使うターミナルの設定などを記述したファイルをぶち込んで GitHub 等に置いておくことで パソコンを買い替えたり増やしたりしたときに自分用にカスタマイズした環境を素早く構築できる ようにするものです。
世界中のエンジニアが様々な dotfiles を公開しており、それらを参考にしながら、また時代の変化や自分自身の興味関心、そして成長などに合わせて 世界にひとつだけの自分専用オリジナル dotfiles を育てていきます。そんな dotfiles を管理するためのツールとして chezmoi というもの があり、こちらを利用して dotfiles を作ったので、備忘録的な感じで書いていこうと思います。
作ったもの
macOS と Windows Subsystem for Linux(以下 WSL)で利用できる dotfiles を作りました。
README に記載しているインストール用コマンドを実行すると、.zshrc
や .bashrc
などのドットから始まるファイル群がホームディレクトリに配置されます。また、Volta 経由で普段のフロントエンド開発などで使用する Node.js をインストールしたり、macOS の場合は Lima で Docker を使えるように環境をいい感じにしたりと、ファイルを配置するだけでなく必要なツールのインストールやセットアップもやります。
dotfiles を作る
さっそく chezmoi を使って dotfiles を作っていきます。
chezmoi をインストールする
ドキュメント に記載されているコマンドを実行して chezmoi をインストールします。Windows なら winget や scoop、macOS なら brew コマンドでもインストールが可能ですが、今回は「One-line binary install」にあるコマンドを実行してインストールしました。
sh -c "$(curl -fsLS get.chezmoi.io)"
インストール後、chezmoi --version
コマンド等を実行して、コマンドが動作するかを確認します。
dotfiles リポジトリを作成する
まずは chezmoi で管理する dotfiles リポジトリを作成します。以下コマンドを実行して、新しい Git リポジトリを作成します。
chezmoi init
コマンドを実行すると、~/.local/share/chezmoi
にリポジトリ(以下「dotfiles リポジトリ」)が作成されます。このディレクトリに .zshrc
や .bashrc
といった複数のマシンで共有したいファイルを追加 していきます。
ファイルを追加する
dotfiles リポジトリへファイルを追加する方法は 2 種類あります。ひとつは既にマシン上に存在する .zshrc
や .bashrc
などのファイルを dotfiles リポジトリ へ追加するコマンドを実行する方法。もうひとつは、直接 dotfiles リポジトリを編集する方法です。
まずは前者について。たとえば、現在使っているマシンにある ~/.zshrc
ファイルをそのまま他のマシンでも使用できるようにしたい場合は、以下のコマンドを実行すると ~/.zshrc
が dotfiles リポジトリにコピーされます。
chezmoi add ~/.zshrc
ドットから始まるファイルを追加した場合は自動的に .
が dot_
へと置き換えられ、.zshrc
の場合はファイル名が dot_zshrc
となります。追加したファイルを編集する場合は以下コマンドを実行します。
chezmoi edit ~/.zshrc
続いて後者の直接 dotfiles リポジトリを編集する方法。~/.local/share/chezmoi
にある dotfiles リポジトリを VSCode などのエディタで直接開いてファイルを追加したり編集したりします。今回は基本的にはこちらの方法で編集を行います。
リポジトリを開き、複数のマシンで共有したいファイルを追加していきます。新しいファイルやディレクトリを作成する際、コマンドでのファイル追加でコピーされるファイルと同様に、ドットから始まるファイルやディレクトリの場合は 先頭の .
を dot_
に置き換えて作成 する必要があります。
作成するファイルやその内容については、人それぞれ内容が異なるので割愛。作成する際に利用できる便利な機能について、以下にいくつか紹介します。
ルートディレクトリを変更する
dotfiles リポジトリを GitHub 上で公開する場合、dotfiles リポジトリのルートに README.md
ファイルを作成するなどしたくなります。他にも、エディタの設定ファイルなどを置くことがあるかもしれません。
そのまま置いてしまうと、他のマシンで chezmoi を使って dotfiles を展開した際に、そのマシンのホームディレクトリに README.md
ファイルなども一緒にコピーされてしまうことになります。邪魔です。
その場合、dotfiles リポジトリのルートに .chezmoiroot
と home/
ディレクトリ(名前は任意)を新たに作成し、.chezmoiroot
に home
と書いておくことでルートディレクトリを変更することができます。
home
上記の例の場合、これまでは ~/.local/share/chezmoi/dot_zshrc
が ~/.zshrc
に相当するファイルでしたが、これが ~/.local/share/chezmoi/home/dot_zshrc
に変更されます。dotfiles リポジトリのルートにファイルがズラズラと並んでいるのが見づらくて嫌だという場合にも便利です。
テンプレートを使う
chezmoi にはテンプレート機能というものが用意されており、これを利用することで マシンの OS に応じて設定内容を出し分けるなどの条件分岐が可能 になります。
テンプレートの機能を利用するには ファイルの拡張子を .tmpl
へと変更 します。たとえば dot_zshrc
なら dot_zshrc.tmpl
へと変更する、といった感じです。これでファイル内でテンプレートの機能が利用可能となります。
テンプレートは機能が豊富すぎて私も全容を把握できていないのですが、たとえば OS が macOS か Linux かで内容を変えたい場合には以下のように記述することで実現が可能です。
{{ if eq .chezmoi.os "darwin" }}
# macOS
{{ else if eq .chezmoi.os "linux" }}
# Linux
{{ else }}
# Other
{{ end }}
.chezmoi.os
は chezmoi が用意している 変数 で、OS の情報が代入されています。他にも様々な情報を取得することができる変数や、便利な関数などが用意されているのでドキュメントを参照してください。
インタラクティブな入力をする
たとえば、自宅のパソコンと職場のパソコンで同じ dotfiles を使いたいとします。dotfiles リポジトリに Git の設定を記述した .dot_config/git/config
ファイルを作成し、dotfiles を展開した際に ~/.config/git/config
に配置されるように設定すると、たしかに Git の設定を異なるマシンの間で揃えることができるのですが、困ることがあります。
そのままだと、Git の設定にある user.email
や user.name
が同じ値になってしまい、SNS で使っているハンドルネームが職場に大公開されてしまう…なんてことが起きてしまうかもしれません。
chezmoi では dotfiles を適用するときに「ユーザ名を入力してください」のように入力を要求 し、それをファイルへ出力することも可能です。これを使えば、自宅のパソコンで使用するときには Git の user.name
にハンドルネームを、職場のパソコンでは本名を指定する、といったことが実現できます。
まずは dotfiles リポジトリのルート(もしくは .chezmoiroot
で指定した場所)に .chezmoi.yaml.tmpl
ファイルを作成します。今回は YAML 形式で作成しましたが、JSON 形式や TOML 形式でも記述が可能です。
このファイルの使い方としては 全体で共通して使用する変数を定義 したり、今回のように ユーザに入力を要求して入力された値を変数として呼び出せるようにする のに使用できます。以下のように記述すると、.tmpl
ファイル内で入力されたメールアドレスを .email
という変数で使用することができるようになります。
{{ $email := promptStringOnce . "email" "What is your email address" -}}
data:
email: {{ $email | quote }}
$hoge
のように変数を定義し、最後の data
に含めたものが他のファイルで変数として呼び出せるような感じです。これを利用して、.dot_config/git/config.tmpl
に以下のように書いておけば、マシンごとに異なるメールアドレスと名前で Git のコミットができるようになります。
[user]
# Specify the email address of the author/committer.
email = "{{ .email }}"
# Specify the username of the author/committer.
name = "{{ .name }}"
スクリプトを書く
.zshrc
や .bashrc
などの必要なファイルが作成できたら、dotfiles のリポジトリとしてはほぼ完成となります。GitHub などに push して、他のマシンから呼び出せば、同じ .zshrc
や .bashrc
がホームディレクトリに作成されます。
必要なファイルを新しい環境に素早く用意できるだけでも非常に便利なのですが、楽をしたがる生き物であるエンジニアは「どうせなら開発環境の構築もまとめてやってしまいたい」「Node.js のインストールや Docker 環境の構築なんかもコマンドひとつで終わらせたい」みたいなことになりがち。そんなときに便利なのが スクリプトの機能 です。
簡単に説明すると、chezmoi でファイルを展開する際に 任意のスクリプトを実行できる というもの。dotfiles リポジトリ内に run_
や run_once_
といった名前から始まるスクリプトを置いておくと、自動的に実行してくれます。
run_
は dotfiles を適用する度に実行され、run_once_
は初回の実行かスクリプトの内容を変更した場合に実行されます。複数のファイルを置いた場合には、ファイルの名前順で実行されます。また、run_before_
のように before_
を付けた場合には各 dot_
ファイルがホームディレクトリに配置される前、after_
を付けた場合にはホームディレクトリに配置された後に実行されます。
dotfiles リポジトリ内の他のファイルと同じ階層に配置しても良いのですが、.chezmoiscripts/
というディレクトリを作成してまとめることも可能なので、今回はこちらの方式を採用しました。
macOS で Homebrew をインストールする
スクリプトの例として、macOS で dotfiles を展開した際に Homebrew をインストールするスクリプトを用意してみます。.chezmoiscripts/
内に run_after_darwin.sh.tmpl
というファイルを作成してシェルスクリプトを記述します。
このファイルは run_
なので、初回に限らず dotfiles を適用する度に実行され、after_
なのでホームディレクトリには既に .zshrc
や .bashrc
などのファイルが存在している状態です。
#!/bin/bash
# macOS の場合のみ実行する
# {{- if eq .chezmoi.os "darwin" }}
if command -v brew >/dev/null 2>&1; then
printf -- "%sHomebrew already installed, skipping.%s\n"
else
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# {{- if eq .chezmoi.arch "arm64" }}
eval "$(/opt/homebrew/bin/brew shellenv)"
# {{- else }}
eval "$(/usr/local/bin/brew shellenv)"
# {{- end }}
fi
# {{- end }}
上記のスクリプトでは、{{- if eq .chezmoi.os "darwin" }}
と {{- end }}
で囲むことで、macOS の場合のみスクリプトが実行されるようにしています。
ファイル名が run_
から始まる場合は dotfiles の適用の度に毎回実行されることになるので、brew
コマンドが存在しなければ Homebrew のインストールを実行、既にコマンドがあればスキップしています。この部分は好みに応じてファイル名を run_once_
にするなどの検討をしても良いでしょう。
Homebrew では、Apple Silicon CPU か Intel CPU かによってインストール後に必要なコマンドが微妙に異なります。なので、.chezmoi.arch
から CPU のアーキテクチャを取得して分岐させています。
dotfiles を使用する
作成した dotfiles を使用する場合は、以下のようなコマンドを実行します。Hiratake
となっている箇所にはリポジトリを作成した GitHub のユーザ名を指定します。
sh -c "$(curl -fsSL get.chezmoi.io)" -- init --apply Hiratake
実行すると、ホームディレクトリにドットから始まるファイル群が配置され、各種ツールのインストールやセットアップのコマンドが実行され、あっという間に自分だけのターミナル環境が整います🎉
chezmoi のおかげで、いい感じの dotfiles を整備できて良かったです。使用する OS によって実行する内容を分けたり、ファイル内の記述を出し分けたりするのは、シェルスクリプトなんもわからんな私には難しいので、そういった部分をやってくれるのは非常に助かります。
dotfiles は一度作ったらそれでおしまい、というものではありません。時代の変化によって使うツールが別のものになったり、新たなプログラミング言語が登場してその環境を整備することになったり、エンジニアとして成長して過去の自分が書いた dotfiles のコードよりも良いコードを書けるようになったり。
そんな様々な変化に応じて、育てていく。そういうものだと思うので、私も世界にひとつだけの dotfiles を育て続けていきたいと思います。