NixOS で .local/bin ディレクトリを生成して自作スクリプトを保存する方法

概要

前置き

NixOS の home-manager でユーザー環境を管理していますが、設定を編集する都度 cd .dotfiles && home-manager switch flake . && cd と長いコマンドを実行する必要があるのが少し面倒でした。

そうしたとき、Taskfile(taskコマンド)のfish補完定義を改善してグローバルタスクに対応した | Atusy's blog という記事を読んで、専用のコマンドが簡単に作れることが分かりましたので、これを NixOS の機能を活用しながら応用することにしました。

設定内容は大したものではないですが、NixOS の Tips になるかと思いましたので、備忘録代わりにまとめます。

環境

OS: NixOS on WSL2 (Windows on ARM)

 1> nix-shell -p nix-info --run "nix-info -m"
 2 - system: `"aarch64-linux"`
 3 - host os: `Linux 5.15.167.4-microsoft-standard-WSL2, NixOS, 24.11 (Vicuna), 24.11.717196.9684b53175fc`
 4 - multi-user?: `yes`
 5 - sandbox: `yes`
 6 - version: `nix-env (Nix) 2.24.14`
 7 - channels(root): `"nixos-24.11, nixos-wsl"`
 8 - nixpkgs: `/nix/var/nix/profiles/per-user/root/channels/nixos`
 9
10> home-manager --version
1125.05-pre

シェルスクリプトの作成

NixOS でシェルスクリプトを作成する場合、1つ注意点があります。NixOS は独自のファイル構造を採用して Filesystem Hierarchy Standard - Wikipedia に準拠していないため、冒頭の shebang を #!/bin/bash と書いても実行時にエラーになります1

ではどうするかと言いますと、shebang を #!/usr/bin/env bash とします。これにより、env コマンド経由で bash が起動しますので、シェルスクリプトのコードが無事に実行されます2

実際に作成したシェルスクリプト(~/.dotfiles/home-update)は次のとおりです。

1#!/usr/bin/env bash
2
3cd ~/.dotfiles
4git add .
5home-manager switch --flake .
6cd ~/

スクリプトを作成したら、chmod +x .dotfiles/home-update コマンドで実行権限を付与します。

設定内容

ここから .dotfiles/home-update スクリプトのシンボリックリンクを .local/bin に作成して home-update コマンドで実行できるよう設定します。

まず、configuration.nixenvironment.localBinInPath = true を追加して .local/bin がパスに追加されるようにします。

それから、home.nix に以下のコードを追加してシンボリックリンクを作成しています。

1home.file.".local/bin/home-update" = {
2  source = config.lib.file.mkOutOfStoreSymlink "${builtins.toString config.home.homeDirectory}/.dotfiles/home-update";
3};
  • home.file.".local/bin/home-udate" = {} は、シンボリックリンクとして作成する .local/bin/home-update の各種設定を宣言する部分です。シンボリックリンクの場所の指定はホームディレクトリからの相対参照にします。
  • source = config.lib.file.mkOutOfStoreSymlink "${builtins.toString config.home.homeDirectory}/.dotfiles/home-update"; の内容は次のとおりです。
    • lib.file.mkOutOfStoreSymlink 関数を使うことで、Nix ストア(/nix/stor)以外の場所にシンボリックリンクを作成できるようにします。
    • lib.file.mkOutOfStoreSymlink の引数としてリンク元のパスを渡しますが、パスの直打ちを避けたかったので、${builtins.toString config.home.homeDirectory} でホームディレクトリのパスを文字列として取得し、そこに .dotfiles/home-update を繋げることでリンク元のフルパスを作成して関数に渡しています。
    • 上記の設定を source に渡すことで、.local/bin/home-manager のリンク元を ~/.dotfiles/home-manager に設定しています。

ここまで設定したら cd .dotfiles && git add . && home-manager switch --flake . && cd コマンドを実行して設定を反映させます。すると、コマンド実行前に .local/bin ディレクトリが作成されていなかったとしても、ディレクトリが自動的に作成されてシンボリックリンクが配置されます。

これで home-update コマンドを実行できるようになりました。

参考情報


  1. bash の保存場所が /run/current-system/sw/bin/bash になっているためです。 ↩︎

  2. env bash を実行すると bash が起動します。 ↩︎