NixOS 全然分からない
WSL2 に NixOS を入れて遊びたいんだ。
今の WSL 環境 (Ubuntu 20.04) がさまざまな要因で壊れつつあり、dotfiles も全壊しつつあるので NixOS にして心の平穏を得たい。
とりあえず https://github.com/nix-community/NixOS-WSL を入れた状態。
設定の違い
NixOS で知ってるのは configuration.nix
なんだが、どうやら Nix Flakes や home-manager などいろいろあるらしい。どれがどれだ?
ざっと調べて「こんな感じ?」という内容をまとめたもの:
configuration.nix
システムの設定を管理する。弄るのに sudo
が要るようなやつ。
nix flakes
構成を再現性高く管理する。npm
みたいなもの。
home-manager
ユーザーごとの設定を管理する。ホームディレクトリとかユーザ権限でインストールするアプリケーションとか。
configuration.nix
Docker を有効化する with 現状、少なくとも Docker と離れては生きられない状況なので Docker を active にしておく。
こういった類いの設定は configuration.nix
に書かれるようであり、実際 WSL 向け NixOS には既にコメントアウトされた状態で準備されている。
{ lib, pkgs, config, modulesPath, ... }:
with lib;
let
nixos-wsl = import ./nixos-wsl;
in
{
imports = [
"${modulesPath}/profiles/minimal.nix"
nixos-wsl.nixosModules.wsl
];
wsl = {
enable = true;
automountPath = "/mnt";
defaultUser = "nixos";
startMenuLaunchers = true;
# Enable native Docker support
- # docker-native.enable = true;
+ docker-native.enable = true;
# Enable integration with Docker Desktop (needs to be installed)
# docker-desktop.enable = true;
};
# Enable nix flakes
nix.package = pkgs.nixFlakes;
nix.extraOptions = ''
experimental-features = nix-command flakes
'';
system.stateVersion = "22.05";
}
設定の変更ができたら NixOS マニュアル にある通り、nixos-rebuild
を実施する。nixos-rebuild test
で test できるが、現状失うものがなく気持ちが強いのでいきなり nixos-rebuild switch
した。
$ sudo nixos-rebuild switch
building Nix...
building the system configuration...
stopping the following units: systemd-sysctl.service
activating the configuration...
Copying /usr/share/applications
Copying /usr/share/icons
setting up /etc...
setting up /bin...
reloading user units for nixos...
setting up tmpfiles
fchmod() of /tmp/.X11-unix failed: Read-only file system
reloading the following units: dbus.service
starting the following units: systemd-sysctl.service
the following new units were started: docker.service, docker.socket, var-lib-docker.mount
warning: error(s) occurred while switching to the new configuration
/tmp/.X11-unix
がなんかダメそうですが、WSL だからだと思います (そんな感じの issue もあるので)。
いったん WSL をシャットダウンしてブートし直すと、docker コマンドが通るようになりました。めでたし。
configuration.nix
を編集する with nix run
上記の通り /etc/nixos/configuration.nix
を編集するのであるが、素の状態ではエディタの類いが何も入っておらず vim
emacs
はおろか vi
ですら存在しない。
[nixos@claudel:~]$ vim
bash: vim: command not found
[nixos@claudel:~]$ emacs
bash: emacs: command not found
[nixos@claudel:~]$ vi
bash: vi: command not found
そういうわけでまずはパッケージマネージャから適当な vim
を入れる必要がある。ところで Nix にはパッケージをインストールしなくてもその場で使えるようにするスーパー機能があり、その名も nix run
である。
$ nix run nixpkgs#vim
そういうわけで、上記のように configuration.nix
に手を入れたいのであれば
$ sudo nix run nixpkgs#vim /etc/nixos/configuration.nix
すると、しばらくゴニョゴニョした後に vim が起動するのであった。すごいね。
vim
を入れる with configuration.nix
とはいえ vim
を叩くためだけに毎回 nix run
をするのはかったるいので、さすがにインストールしておく。
https://nixos.wiki/wiki/Vim によると
- システムパッケージとしてインストールする方法
- home-manager からインストールする方法
の二種類があるようであり、ひとまずシステムパッケージとしての導入を試してみる。
これは単純で、configuration.nix
の最後の }
の前に以下を足すだけ。
environment.systemPackages = with pkgs; [ vim ];
ちょっと自信がないので nixos-rebuild test
してみる。
$ sudo nixos-rebuild test
...(snip)...
$ vim
立ち上がる。よさそうなので nixos-rebuild switch
して終わり。
Nix Flakes 再訪
configuration.nix
について分かってきたので、次は Nix Flakes。
Nix Flakes は、特定のフォーマットを持つ git repo を clone してきて使える環境を用意してくれる機能っぽい感じがあり、例えば https://github.com/NixOS/nixpkgs の hello を使えるようにする例:
[karno@claudel:~]$ hello
bash: hello: command not found
[karno@claudel:~]$ nix shell github:nixos/nixpkgs#hello
[karno@claudel:~]$ which hello
/nix/store/7syg3lif5ik17dsrwgk3s00s116q87by-hello-2.12.1/bin/hello
[karno@claudel:~]$ hello
Hello, world!
[karno@claudel:~]$ exit
exit
[karno@claudel:~]$ hello
bash: hello: command not found
さて、実は github:nixos/nixpkgs
は単に nixpkgs
として記述できます。そういうわけで、さっきの nix run nixpkgs#vim
も Nix Flakes を使っているのであり、同様に:
[karno@claudel:~]$ which vim
/run/current-system/sw/bin/vim
[karno@claudel:~]$ nix shell nixpkgs#vim
[karno@claudel:~]$ which vim
/nix/store/12jh1klrixvqilis5ywqsgqr6nkvrbh1-vim-9.0.1441/bin/vim
みたいな感じになるのでした。
NixOS Flakes を configuration.nix
で使うには以下が参考になりそう。
Home Manager を入れるぞ
Home Manager のリポジトリを見ると、しっかり warning が書かれている:
If you are not very familiar with Nix but still want to use Home Manager then you are strongly encouraged to start with a small and very simple configuration and gradually make it more elaborate as you learn.
ということなので、小さく始めることでなんとかします。
ちなみに warning で触れられている Nix Pills は ← これ。
インストール
インストール方法は、NixOS においては以下の2系統があるようです。
- スタンドアロン。
- system configuration (たぶん
configuration.nix
) 経由。nixos-rebuild
で設定できるようになる。
nixos-rebuild
が必要なのはかったるいのでスタンドアロンで入れます。
-
nix-channel
に home-manager を追加する -
nix-shell
でインストールする
という感じになりそうです。それぞれ初出なので真面目に確認します。
Nix パッケージマネージャの基礎の基礎
上記の通り、Nix を理解するためによいドキュメントとして Nix Pills が挙げられています。
Section 2. を見ると概念が、Section 3. を見ると概ねの操作が分かってきます。
主要な概念
- profile: 複数のパスに分散されたコンポーネント群の集合からなる、ある環境を示すやつ。
- profile には generation の概念があり、バージョン管理される。ロールバックしたり特定の世代に飛んだりできる。
- nixpkgs:
Nix 式 (Nix expression)
によって、パッケージの説明 (とビルド方法) が記述されたパッケージ。 - channnels: ダウンロード可能な nixpkgs と Nix 式のセット。リポジトリ的なもの?
主要な操作
パッケージの操作は以下の通り。
# install package
nix-env -i hello
# uninstall package
nix-env -e hello
# rollback
nix-env --rollback
# print installed packages
nix-env -q
ところで、上記の通り入れたり消したりしたパッケージはすべて store
と呼ばれる空間に保存され、nix-store
を使って管理できます。
# dependencies of hello
nix-store -q --references `which hello`
# reverse-dependencies of hello
nix-store -q --referrers `which hello`
# print all dependent packages
nix-store -qR `which hello`
# ... as tree
nix-store -q --tree `which hello`
そして、nix-env -i [package_name]
したときに package_name
をどこから取得してくるかが channels で解決され、これを制御するのが nix-channel
です。
nix-channel --list
今はまだまっさらな NixOS なので特に出力はありませんでした。
改めて Home Manager を入れる
そういうわけで、インストール手順に従います。
nix-channel
への追加
nix-channel
にまずは手を入れます。
[karno@claudel:~]$ nix-channel --add https://github.com/nix-community/home-manager/archive/master.tar.gz home-manager
[karno@claudel:~]$ nix-channel --update
this derivation will be built:
/nix/store/ag006jrz816lm8zkgx50f8y6s55nxx5z-home-manager.drv
building '/nix/store/ag006jrz816lm8zkgx50f8y6s55nxx5z-home-manager.drv'...
unpacking channels...
[karno@claudel:~]$ nix-channel --list
home-manager https://github.com/nix-community/home-manager/archive/master.tar.gz
nix-channel --add
すると、さっきまでまっさらだった nix-channel --list
に home-manager が出現します。
nix-shell
でインストール
下記を実行するように言われます。
$ nix-shell '<home-manager>' -A install
果たしてまた知らんやつが出てきたのですが、どうやら nix-shell
は Nix expression を実行するやつっぽいです。<>
は nixpkgs (すなわち、さっき登録した channel から見つけてほしい home-manager
) を指し、-A install
は評価されるべきトップレベルの Nix expression を指定するやつらしいです。
なんとなく分かったので実行してみます。
[karno@claudel:~]$ nix-shell '<home-manager>' -A install
error: file 'home-manager' was not found in the Nix search path (add it using $NIX_PATH or -I)
なんか調子が悪そうなのでいったんログアウトしてまた立ち上げます。
[karno@claudel:~]$ nix-shell '<home-manager>' -A install
this derivation will be built:
/nix/store/0xy6rkj8rdr9mplinrr70wm7nq100h33-home-manager.drv
these 8 paths will be fetched (2.41 MiB download, 10.94 MiB unpacked):
/nix/store/4bmi4bagsz62nhf4vjy987a0n11lp3a5-bash-interactive-5.1-p16-info
/nix/store/4r83g1mj2qg6n6pf3ihwizksna7wl6d0-nix-2.3.16
...(snip)...
Creating /home/karno/.config/home-manager/home.nix...
Creating initial Home Manager generation...
error: attribute 'numbers' missing
at /nix/store/ld9xjfsmvz2gqkk06sx3mfcw420jsj5p-home-manager/home-manager/modules/services/picom.nix:144:14:
143| activeOpacity = mkOption {
144| type = types.numbers.between 0 1;
| ^
145| default = 1.0;
(use '--show-trace' to show detailed location information)
Uh oh, the installation failed! Please create an issue at
https://github.com/nix-community/home-manager/issues
if the error seems to be the fault of Home Manager.
ダメでした。
さらっと調べてみるとチャンネルの不一致という話が出てきており、どうやら unstable と stable が・・・という話っぽいです。そういえば、インストールの説明で 「もし 22.11 channel 使ってるなら以下を参照してくれよな」という説明があった気がします。
[karno@claudel:~]$ nix-channel --add https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz home-manager
[karno@claudel:~]$ nix-channel --list
home-manager https://github.com/nix-community/home-manager/archive/release-22.11.tar.gz
[karno@claudel:~]$ nix-channel --update
this derivation will be built:
/nix/store/546bfda2z1aj4l7pci48l6nmygz0lbbh-home-manager-22.11.tar.gz.drv
building '/nix/store/546bfda2z1aj4l7pci48l6nmygz0lbbh-home-manager-22.11.tar.gz.drv'...
unpacking channels...
[karno@claudel:~]$ exit
exit
PS C:\Users\karno> wsl -d NixOS
[karno@claudel:~]$ nix-shell '<home-manager>' -A install
this derivation will be built:
/nix/store/ps716hvyrybrxian4753sdv15pbjlhyl-home-manager.drv
this path will be fetched (0.06 MiB download, 0.38 MiB unpacked):
/nix/store/8w1g7af686l4l1ih67znq7p4sp9hgrj0-ncurses-6.3-p20220507-dev
copying path '/nix/store/8w1g7af686l4l1ih67znq7p4sp9hgrj0-ncurses-6.3-p20220507-dev' from 'https://cache.nixos.org'...
building '/nix/store/ps716hvyrybrxian4753sdv15pbjlhyl-home-manager.drv'...
install: creating directory '/nix/store/qf3cbhsagda9nf8v1wjwpj6d6za6a0x9-home-manager'
install: creating directory '/nix/store/qf3cbhsagda9nf8v1wjwpj6d6za6a0x9-home-manager/bin'
'/nix/store/dlc5qzrvm301jlsibx37npswfns6b22c-home-manager' -> '/nix/store/qf3cbhsagda9nf8v1wjwpj6d6za6a0x9-home-manager/bin/home-manager'
Creating initial Home Manager configuration...
Creating initial Home Manager generation...
error: attribute 'numbers' missing
at /nix/store/071dd34mmwqpkw26vk6ymc1g8pi72ppk-home-manager-22.11.tar.gz/home-manager/modules/services/picom.nix:144:14:
143| activeOpacity = mkOption {
144| type = types.numbers.between 0 1;
| ^
145| default = 1.0;
(use '--show-trace' to show detailed location information)
Uh oh, the installation failed! Please create an issue at
https://github.com/nix-community/home-manager/issues
if the error seems to be the fault of Home Manager.
ダメやないですか! :very_sad:
Nix Flakes でインストールしてみる
nix-channels
の次世代版が Nix Flakes
だよという風評を聞いたので、 Nix Flakes
でインストールを試みます。
[karno@claudel:~]$ nix run home-manager/master -- init --switch
The file /home/karno/.config/home-manager/home.nix already exists, leaving it unchanged...
Creating /home/karno/.config/home-manager/flake.nix...
Creating initial Home Manager generation...
warning: creating lock file '/home/karno/.config/home-manager/flake.lock'
Starting Home Manager activation
Activating checkFilesChanged
Activating checkLinkTargets
Activating writeBoundary
Activating installPackages
installing 'home-manager-path'
building '/nix/store/vdpmdimhrz9aqhiqylqyadjhddj168dl-user-environment.drv'...
Activating linkGeneration
Creating profile generation 1
Creating home file links in /home/karno
Activating onFilesChange
Activating reloadSystemd
All done! The home-manager tool should now be installed and you can edit
/home/karno/.config/home-manager/home.nix
to configure Home Manager. Run 'man home-configuration.nix' to
see all available options.
サクッと通りました。さすが。
用済みの nix-channel
は消しておきます。
[karno@claudel:~]$ nix-channel --remove home-manager
uninstalling 'home-manager-22.11.tar.gz'
インストール方法おさらい
というわけで、上記では home-manager
を Nix Flakes でインストールしましたが、あくまで ユーザ権限 で成されています。
Nix Flakes を使うかどうか と、システム権限でインストールするかどうか は独立しており、要するに以下の構造です。
システム権限 | ユーザ権限 | |
---|---|---|
nix-channel | これ | これ、↑で試みて失敗したやつ |
Nix Flakes | これ | これ、今回のインストール方法 |
システム権限で Nix Flakes を使ってインストールすることももちろん可能です。今回これを選ばなかった理由はユーザの設定を編集するたびに nixos-rebuild が必要になって面倒だからです。
とりあえず設定を編集できるようにする
zsh
に
ひとまずログインシェルを こういった system-wide な設定は configuration.nix
らしい。
(chsh ってユーザ権限で動く気がしていたが、しょうがないのか)
+ # user-specific configuration
+ users.users.karno = {
+ isNormalUser = true;
+ extraGroups = [ "wheel" ];
+ shell = pkgs.zsh;
+ };
+ programs.zsh.enable = true;
+ programs.zsh.enableCompletion = true;
Home Manager について知る
こんな記事を見つけた: https://ghedam.at/24353/tutorial-getting-started-with-home-manager-for-nix
設定ファイルは ~/.config/nixpkgs/
ではなく ~/.config/home-manager/
になっていた。Nix Flakes だからか?