NixでURLからインポートする
原文は Michael Lynch により に公開されました。 このブログを購読する
私はまだNix初心者ですが、最近まで分からなかったことの一つが、configuration.nixファイルの一部をどうやってソース管理すればよいのかということでした。
目標
Nixの設定ファイルをモジュール化して再利用可能にしたいと思っています。そうすれば、システムやflakeごとに必要な設定ファイルだけを取り込めるようになります。すべてのNix設定ファイルをソース管理下に置きたいのは、システムごとに各ファイルの異なるバージョンに依存できるようにするためです。そうすれば、すべてのシステムで各設定ファイルを同時に最新バージョンにアップグレードする必要がなくなります。
ローカルファイルで再利用可能なbashエイリアスを作る
再利用したいNix設定の一つが、bashのエイリアスです。既存のシステムでは、.bashrcに次のような行を記述しています。
alias gc='git commit --message'
alias gs='git status'
alias td='pushd $(mktemp -d)'bashで同等のことを実現するために、NixOSシステム上に次の内容のファイルを作成できます。shell.nixという名前にしていますが、名前は何でも構いません。
{
programs.bash.shellAliases = {
gc = "git commit --message";
gs = "git status";
td = "pushd $(mktemp -d)";
};
}このファイルを/tmp/shell.nixとして保存すれば、importsにパスを追加することで、/etc/nixos/configuration.nixにインポートできます。
{
imports = [
"/tmp/shell.nix"
];
}sudo nixos-rebuild switchを実行してからシェルを再起動すると、bashエイリアスが有効になっていることが確認できます。
$ td
/tmp/tmp.awb7PW7aus ~
[/tmp/tmp.awb7PW7aus]$ pwd
/tmp/tmp.awb7PW7ausNixファイルをURLに移す
上記の方法でも動作しますが、Nixを使っている各システムに同じファイルをコピーする必要があります。
むしろ、ファイルを公開されたURLでホストし、標準的なconfiguration.nixファイルからそのURLを参照する形にしたいと思います。
リモートURLから私のshell.nixファイルを取り込むために、configuration.nixを次のように修正します。
let
shellAliases = builtins.fetchurl {
url = "https://mtlynch.io/notes/nix-import-from-url/shell.nix";
};
in {
imports = [
shellAliases
];
}今回も、これらの変更をconfiguration.nixに保存し、sudo nixos-rebuild switchを実行してシェルを再起動すれば、NixがURLからbashエイリアスをインポートしてくれます。
fetchGitを使う(オプション)
リモートのNixファイルを取得する別の方法として、ファイルを公開Gitリポジトリに置き、fetchGitで取得する方法があります。
公開GitHubリポジトリからshell.nixを取得するconfiguration.nixファイルの例を次に示します。
let
repo = builtins.fetchGit {
url = "https://github.com/mtlynch/nix-files";
rev = "f98500a995cb5838e40be139a8327867faaff2d5";
};
in {
imports = [
"${repo}/shell.nix"
];
}urlはGitHubリポジトリの公開URLで、revはインポートしたいファイルのバージョンのGitコミットハッシュです。
configuration.nixにこれらの変更を加えた後、再度sudo nixos-rebuild switchを実行すれば、NixがGitHubリポジトリからshell.nixファイルをインポートします。
より高度なシェル設定
私のbashエイリアスの大半はシンプルなワンライナーですが、中にはもう少し複雑なものもあります。そういったものについてはbash関数を定義し、その関数に対して短いエイリアスを作成しています。
一例がgcbmというbashエイリアスです。gcbm some-branchのように使い、次のような処理を行います。
- mainブランチをチェックアウトする。
- リモートリポジトリから最新の変更をプルする。
some-branchという名前の新しいブランチをチェックアウトする。
エイリアスの主要な処理はgit_sync_and_branchというbash関数に実装しています。これをshell.nixでは次のように実装しています。
{
programs.bash = {
shellInit = ''
function git_sync_and_branch {
local readonly TARGET_BRANCH="''${1}"
local readonly MAIN_BRANCH='master'
git checkout "''${MAIN_BRANCH}" && \
git pull origin "''${MAIN_BRANCH}" && \
if [[ -n "''${TARGET_BRANCH}" ]]; then
git checkout -b "''${TARGET_BRANCH}"
fi
}
'';
shellAliases = {
gc = "git commit --message";
gcbm = "git_sync_and_branch";
gs = "git status";
td = "pushd $(mktemp -d)";
};
};
}注意点:ドル記号のエスケープ
bash関数をNixに移そうとしたときにハマった落とし穴の一つが、${というシーケンスをエスケープする必要があるということです。そうしないと、Nixがそれをローカル変数として展開しようとしますが、それらはNixの変数ではなくbashの変数だからです。
git_sync_and_branchのbash関数の中で、最初に次のように書こうとしました。
git checkout "${MAIN_BRANCH}"Nixは次のエラーで失敗しました。
error: undefined variable 'MAIN_BRANCH'${は次のように2つのシングルクォート('')を前に付けて${をエスケープする必要があります。
git checkout "''${MAIN_BRANCH}"なぜHome Managerを使わないのか?
Nix設定をモジュール化するより一般的な方法は、Home Managerを使うことだと思います。
ただ正直なところ、私はまだHome Managerの目的がよく分かっていません。プロジェクトのREADMEによると、
このプロジェクトは、NixパッケージマネージャーとNixpkgsにあるNixライブラリを併用して、ユーザー環境を管理するための基本的なシステムを提供します。ユーザー固有の(グローバルではない)パッケージやdotfilesを宣言的に設定できます。
これは私には混乱を招きます。なぜなら、Nixがすでにやっていることのように聞こえるからです。
Home Managerを何度か覗いてみましたが、そのたびに、この新しいツールを学ぶために多くの労力をかける必要があるのに、得られるメリットが自分にははっきりしないと感じます。
いつかHome ManagerでNix設定を管理する利点に気づくときが来るかもしれませんが、今のところ、標準のNixでリモートのNixファイルを管理するかなりシンプルな方法を見つけました。
記事をランダムに読む
コメント
ログインしてコメントする