Nix改良に向けたあれこれ

Nix駆動の開発環境整備の土台が出来たので、細かな気になるポイント解消を目指してあれこれやってみる。
環境は特段言及無ければWindows 11 + WSL2。一部サブPCのNixOS上の営みもあるかもなので、その場合は言及する。

nix
コマンド高速化
事象
-
nix flake check
等のコマンドを打つ機会は多いが、一定出来上がったプロジェクト宛に実行するとめちゃくちゃ遅い- Electron + Vite構成のプロジェクト宛に
time nix flake check
を試すと4分かかった
- Electron + Vite構成のプロジェクト宛に
real 3m59.841s
user 0m3.619s
sys 0m12.750s
理解
-
nix
コマンドを実行すると、依存関係管理のためのハッシュ生成の意図でプロジェクトリソースをNixサンドボックス環境にコピーする挙動が走ると認識している - この挙動のため、プロジェクトが膨らむと必然重くなる
対策
-
.nixignore
ファイルを作るとコピー対象のexclude定義が書ける -
node_modules
やビルド成果物はコピー対象から外してしまって良い気がするので除外してみると、ベンチマークが1分15秒程に短縮 - 何をignoreするかの整備はもうちょっと練る必要があるが、対処は分かった

どこまでNix管理するか
- 例えばPythonを利用する場合、
nix develop
でPythonを起動した時にpip
は同梱されていない - 上記はNixの想定として、
python3.withPackages(ps: with ps; [ XXX ])
の様な形でのインストールを考えている - ただ、上記はあまりにもNixに寄せた管理であり、下記の様な懸念・気になりポイントがある
- VSCodeのLSP側でNixでインストールしたライブラリを認識出来ない可能性
- Nixはあくまで開発環境として利用するだけで、デプロイ先はどこかのPaaSであれば
pip
の存在を前提にしたリソースを求められる。その場合に対応出来る? - ランタイム側のパッケージ管理は素直にランタイムに任せる方が素直なのでは
この場での結論
o3-miniとも討論して下記方針で進めようと思う。
- Nixはあくまでも
apt
yum
等の役目を埋める物として定義(システムレベルパッケージ) - ランタイムレベルのパッケージはランタイム側のルールに沿う
- Node.js ->
npm
- Python ->
pip
- Node.js ->
- 上記の分割は、元々行っていたDockerによる環境閉じ込めの単位とも一致するので運用上も違和感が無い

nixos-container
の用途
これはNixOSの話になる。
nixos-container
とは
NixOS上で systemd-nspawn
ベースで作られた隔離環境を指す。
これはOCI仕様に沿って作られたコンテナエコシステムであるDockerやPodmanとは明確に異なる。nixos-container
はVM的なイメージで認識するのが近い気がする。
Nixの宣言的な書き味でOCIコンテナ定義を書ける様な記載があるが、あくまでもコンテナエンジンとしてPodmanを利用しているだけに過ぎないと理解なため、nixos-container
の用途についてちゃんと考える様にする。
どこで利用するか
- 開発目線では無さそう
-
nix develop
で閉じた環境が作れるので、コンテナにする意味が無い
-
- 再現出来る範囲がOS相当と思うと、OS宛の何かしらの検証環境にする、みたいな使い方になるのでは
- でも、コンテナでやる必要性があるかは疑問。NixOSは
configuration.nix
で宣言的に定義を書けるので、切り戻しコスト自体相当低い

JPキーボード設定が再起動の度に解除される
NixOSの話。
事象
- マシンを再起動するとJPキーボード設定が解除されUSキーボードに戻されてしまう
- 無論GUI上から一度設定は切り替えている
-
services.xserver.xkb.layout
はjp
で定義している
理由
- Waylandセッション上はGNOME側のスキーマ定義に沿ってキーボード定義がされる
-
services.xserver.xkb.layout
はXorg向けの定義なため、Wayland側は無視する
対策
- dconf定義を作成しGNOMEスキーマ側を制御する
実装
下記を参考に configuration.nix
をアップデートする。
{
programs.dconf = {
enable = true;
profiles.user.databases = [{
# 上書き防止
lockAll = true;
# JPキーボードにセットする
settings = {
"org/gnome/desktop/input-sources" = {
sources = [(lib.gvariant.mkTuple ["xkb" "jp"])];
};
};
}];
};
}

NixOSデスクトップ環境改善
これもNixOSの話。GNOMEベースにあれこれ改造する。
拡張機能インストール
例に漏れずこちらも configuration.nix
で完結する。
{
# GNOME有効化。ここはデフォルトでいずれもtrue設定されているはず
services.xserver.displayManager.gdm.enable = true;
services.xserver.desktopManager.gnome.enable = true;
environment.systemPackages = with pkgs; [
# gnome関連のパッケージたち
gnome-tweaks
gnome-shell-extensions
gnomeExtensions.dash-to-dock
gnomeExtensions.burn-my-windows
gnomeExtensions.arcmenu
];
}
ここまで出来れば gnome-extensions-app
コマンドでGNOME Shell拡張の設定GUIが立ち上がるため、ここで必要な有効化や設定等を行えばOK。

sudo
パスワード有効時間を長くしたい
NixOSの話。例えば sudo
でファイルオープンすると結構な頻度でパスワードを求められるので、流石にもうちょっと長く出来ないかと調査。
security.sudo
を使う
{
security.sudo = {
enable = true;
extraConfig = ''
Defaults timestamp_timeout=15
'';
};
}
ドキュメントの通りだが、extraConfig
の内容が sudoers
に統合されるらしい。

Ulauncherがアプリとして登録されない
NixOSの話。ランチャーとしてUlauncherをインストールしたが、アプリとして登録されない事象が発生。
事象としては下記と一緒。
対応
-
ulauncher
コマンドを打つと挙動することを確認したので、起動ショートカットを登録することにした。今はctrl
+L
で立ち上がる様にしている

ipykernel
インストール手順
Nix上でPython環境を構築の上、Zedで使えるREPL機能を有効化するべく ipykernel
をインストールしようとしたが、どうやらNixがコードコンパイル系のライブラリ依存を追えない様でインストールに失敗したので、一工夫必要だった。
venv
を利用する前提で下記記載。
手順
flake.nix
用意
{
description = "Python REPL";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; };
in {
devShells.${system}.default = pkgs.mkShell {
buildInputs = with pkgs; [
(python313.withPackages (ps: [ps.pip]))
];
# activate venv if exists
shellHook = ''
if [ -d ./repl ]; then
source repl/bin/activate
fi
'';
};
};
}
venv
準備
後述する fix-python
がパッケージパッチ時にシンボリックリンクを辿らない様なので、--copies
を渡してあげる。
$ python -m venv repl --copies
fix-python
でコンパイルに必要なパッケージインストール
事象自体はある程度既知らしく、NixOS wikiでも記載があるが、あれこれ設定することも本筋で無いので venv
環境に必要パッケージをパッチしてくれる fix-python
と言うCLIを使うことにする。
// 初回だけなので一時的にCLI有効化
$ nix shell github:GuillaumeDesforges/fix-python
$ fix-python --venv repl --libs libs.nix
fix-python
がパッチしてくれるライブラリは gcc.cc
glibc
zlib
だけなので、それ以外で必要な物は libs.nix
に書く。今回は libstdc++
も必要だったので libs.nix
はこんな感じ。
let pkgs = import (builtins.getFlake "nixpkgs") { };
in [
pkgs.stdenv.cc.cc.lib
]
ipykernel
インストール
下記に沿って本丸の準備。
$ source repl/bin/activate
$ pip install ipykernel
$ python -m ipykernel install --user --name repl --display-name "Python REPL"
補足
fix-python
や pip
等の行為は初回限定なので、一度環境が出来た後は shellHook
で記載の様に venv
を自動で起動することだけ自動化した。この上で zed
なりでエディタ起動すればREPLまでスムーズに行ける。