Open13

NixOS 全然分からない

karnokarno

WSL2 に NixOS を入れて遊びたいんだ。

今の WSL 環境 (Ubuntu 20.04) がさまざまな要因で壊れつつあり、dotfiles も全壊しつつあるので NixOS にして心の平穏を得たい。

とりあえず https://github.com/nix-community/NixOS-WSL を入れた状態。

karnokarno

設定の違い

NixOS で知ってるのは configuration.nix なんだが、どうやら Nix Flakes や home-manager などいろいろあるらしい。どれがどれだ?

karnokarno

ざっと調べて「こんな感じ?」という内容をまとめたもの:

configuration.nix

システムの設定を管理する。弄るのに sudo が要るようなやつ。

nix flakes

構成を再現性高く管理する。npm みたいなもの。

home-manager

ユーザーごとの設定を管理する。ホームディレクトリとかユーザ権限でインストールするアプリケーションとか。

karnokarno

Docker を有効化する with configuration.nix

現状、少なくとも 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 コマンドが通るようになりました。めでたし。

karnokarno

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 が起動するのであった。すごいね。

karnokarno

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 して終わり。

karnokarno

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 で使うには以下が参考になりそう。
https://nixos.wiki/wiki/Flakes#Using_nix_flakes_with_NixOS

karnokarno

Home Manager を入れるぞ

Home Manager のリポジトリを見ると、しっかり warning が書かれている:

https://github.com/nix-community/home-manager#words-of-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系統があるようです。

  1. スタンドアロン。
  2. system configuration (たぶん configuration.nix) 経由。nixos-rebuild で設定できるようになる。

nixos-rebuild が必要なのはかったるいのでスタンドアロンで入れます

  1. nix-channel に home-manager を追加する
  2. nix-shell でインストールする

という感じになりそうです。それぞれ初出なので真面目に確認します。

karnokarno

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 なので特に出力はありませんでした。

karnokarno

改めて 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:

karnokarno

Nix Flakes でインストールしてみる

nix-channels の次世代版が Nix Flakes だよという風評を聞いたので、 Nix Flakes でインストールを試みます。

https://nix-community.github.io/home-manager/index.html#ch-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'
karnokarno

インストール方法おさらい

というわけで、上記では home-manager を Nix Flakes でインストールしましたが、あくまで ユーザ権限 で成されています。
Nix Flakes を使うかどうか と、システム権限でインストールするかどうか は独立しており、要するに以下の構造です。

システム権限 ユーザ権限
nix-channel これ これ、↑で試みて失敗したやつ
Nix Flakes これ これ今回のインストール方法

システム権限で Nix Flakes を使ってインストールすることももちろん可能です。今回これを選ばなかった理由はユーザの設定を編集するたびに nixos-rebuild が必要になって面倒だからです。

karnokarno

とりあえず設定を編集できるようにする

ひとまずログインシェルを 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 だからか?