🐣

NixOS を WSL2 で使えるようにする

13 min read

設定ファイルをいじってシステムを粉砕する方々へ向けて。

はじめに

この記事は、

設定ファイルを触って気がついたらシステムが粉砕されていた

と言う方々が使うと幸せになる Linux Distribution である、

を Windows 10 2004 で使える様になった Windows Subsystem for Linux 2(WSL2)で取り扱えるようにしよう! と言う記事です。

※ なお NixOS についての解説も含むので、本題に入るまで結構長いです

そもそも NixOS って何?(NixOS についての解説)

NixOS は Nix package manager を核とした Linux Distribution で、その Nix package manager とは、

設定ファイルを 関数型言語(Nix Expression Language)で記述 する、
再現可能性に焦点を当てた package manager

です。

なおこの辺りは Puppet や Chef 、Itamae と Package manager が融合している と考えると理解しやすいと思います。

NixOS や Nix package manager の利点

この Nix package manager の利便性としては、

  1. Nix 経由でインストールされるパッケージを設定ファイル(.nix)として記述できる
  2. 色々なパッケージの複数バージョンを競合させる事なく共存させられる
  3. 不要になりファイルを削除したいパッケージをコマンド一発で一掃できる

と言う辺りがメジャーな利点だと私は考えています。

また Nix package manager 自体は、

  • Linux 系 Distribution
  • macOS (旧名 OSX)

でも利用する事が出来て、さらに NixOS に至っては Nix package manager の利点に加え、

  1. システムの状態を設定ファイル(/etc/nixos/configuration.nix)として記述できる
  2. システムの状態を bootloader から過去の状態にロールバックすることが出来る
  3. systemd などのサービスの状態も、同じ設定ファイル経由で設定できる

と言う特長すら持ちます。

そのため、/etc/nixos/ 以下のファイルを Git で管理すればシステム状態のリビジョン管理も出来てしまいますし、また NixOS を Linux Desktop として利用している際に、何らかの設定ファイルに記述ミスがあって Xorg が起動しない、と言う状態に落ち行ったとしても手軽に過去の Xorg が起動した状態へロールバックできます。

またそれ以外にも システム状態を設定ファイルとして定義できる と言う利点は、Ubuntu や Debian 、または Fedora や CentOS と言った Linux Distro でサーバを運営する際に、古くは Puppet や Chef 、イマドキだと Ansible や Itamae を使う、と言う場面においても、パッケージと設定ファイルの状態 を Nix package manager の設定ファイルとして記述できるため、そう言ったサーバ運用においても利便性があると私は考えています。

NixOS や Nix package manager の欠点

とは言え NixOS や Nix package manager に欠点が無いと言えばそれは否で、特に NixOS だと、

  1. システム状態を設定ファイルとして記述する関係上、融通が効かない場合もある
  2. システム状態をロールバックしても、システムが粉砕されたままな時がまれに存在する
  3. 過去のシステムを構成したパッケージは意図的に削除しない限り残るので容量が厳しい

と言った弱点もあります。

特に NixOS や Nix package manager はその配下にあるシステムファイルが不変であることを要求するので、VMware Workstation などに代表される、システムファイルが可変である事を要求するソフトウェア とかなり相性が悪く、そもそもの VMware Workstation に至っては相当に hacky な事をしない限りインストールすら出来ません

また NixOS や Nix package manager は結構クセが強く、色々な場面で NixOS の流儀に従う必要があったりするので、過去に私は経験した中では、

iBus の SKK Engine(ibus-skk)の 独自ビルドは成功した が、
何故か設定情報が保存できない(これは NixOS 特有の設定をする必要があった)

と言うめちゃめちゃ面倒なケースも存在しました。

よって何時何如なる状況でも NixOS や Nix package manager の利用が適している、とは言い難い面もあるのですが、システムの(パッケージの)状態を設定ファイルで記述できる と言う利点は色々とクセが強くとも他には代え難い利点なので、そう言った面で私はそこそこ前から NixOS を Linux 環境として利用しています。

NixOS を WSL2 で使う(ようやく本題)

さてその様な利点と欠点を持つ NixOS ですが、過去の WSL1 の時代には色々な Blocker
な要因があったため、WSL1 では NixOS を利用できませんでした

しかし今(2020年9月現在)、 WSL2 が Microsoft 製の Custom Kernel を採用した軽量 VM として動作する様になった結果、WSL2 の互換性が格段に上がりいくつかの hack を施せば systemd すら動く様になったため、NixOS は WSL2 上で動作します!

よってここから下記はその環境の実現方法と、 NixOS on WSL2 を運用する際の注意点などを記載して行きたいと思います。

NixOS を WSL2 で使う前に用意するもの

NixOS の WSL2 で使うには、当然のことながら、

  • Windows Subsystem for Linux 2 (WSL2)が使える Windows 環境

が必要になります。

また WSL2 で使うファイルシステムのイメージの元である rootfs.tar.gz を用意する際に Nix package manager を利用する必要があるため、

  • Nix package manager が利用できる Linux 環境

も用意しなければなりません。

そのため NixOS を WSL2 で使うためには、

  1. 既存の Linux に Nix package manager を導入した環境
  2. あるいは外部の NixOS のネイティブ環境か仮想環境などのインスタンス

が必要となるので、最低でもどこかのマシンでNix package manager が使える環境をこしらえる必要があります。

なお私の場合は NixOS on WSL2 を実現する前に Ubuntu 20.04 on WSL2 で Nix package manager を利用していたため、その環境を使って rootfs.tar.gz を生成しました。

また既存の(NixOS 以外の)Linux で Nix package manager を導入するためには、

を参考に、下記のコマンドで導入できます:

$ curl -L https://nixos.org/nix/install | sh

NixOS の rootfs.tar.gz を用意する

まず WSL2 も含め、Windows Subsystem for Linux で Microsoft Store 以外で提供される Linux Distro を利用したい場合、その Linux Distro の rootfs のデータが必要となるため、NixOS の場合でも一番最初にはこの rootfs を用意する必要があります。

また NixOS の場合、既に NixOS on WSL2 を実現した方が GitHub にその際に必要となったスクリプトや設定ファイルを公開しているため、今回はこれを利用します:

なお作業としては、上記リポジトリの中身を Git や zip ファイルからなどで取得して展開し、そのディレクトリ中で、下記のコマンドを発行します:

$ nix-build -A system -A config.system.build.tarball ./nixos.nix

そうするとディレクトリ内の下位ディレクトリのどこかに、 nixos-system-x86_64-linux.tar.gz に類するファイルが生成されるので、その生成されたファイルを適宜コピーして WSL2 を利用する Windows 上に配置します。

NixOS の軽量 VM を用意する

それでここまでの作業で rootfs.tar.gz に相当するファイルは取得できたので、次は rootfs.tar.gz を Windows Subsystem for Linux 2 用のファイルに変換して行きます。

まず先程の作業で生成した rootfs.tar.gz を適当なディレクトリに配置し、コマンドプロンプトか Powershell などの Windows 用の Console で次の様なコマンドを発行します:

> wsl --import NixOS %userprofile%/NixOS /path/to/rootfs.tar.gz --version 2

この際のポイントとしては:

  1. wsl--import コマンドを実行する際にインスタンス名に NixOS と付ける
  2. %userprofile%/NixOS/path/to/rootfs.tar.gz は各自の環境に応じで調整する
  3. --version 2 は必ず指定する。これが無いと WSL2 のインスタンスにならない

と言う辺りです。

ちなみに上記の例だと NixOS の rootfs の仮想ディスクイメージが、%userprofile%/NixOSC:\Users\<name>\NixOS)以下に生成されます。

NixOS を WSL2 上で自由に利用する前に最後の仕上げをする

さてこれで NixOS が WSL2 で自由に使える様になる……と思いきや実際はそうではなく、最後の仕上げとしてコマンドプロンプトか Powershell などの Windows 用の Console で、

> wsl -d NixOS

と言うコマンドで NixOS の WSL2 インスタンスを起動し、一番最初の起動時に下記のコマンドを実行しして一旦 WSL2 のシェルを終了させる必要があります:

$ /nix/var/nix/profiles/system/activate

それで何故このコマンド実行が必要になるかと言うと、このコマンドは本来 NixOS のインストール時に自動的に発行される類いのコマンドなのですが、NixOS on WSL2 用に生成された rootfs では自動的な実行が行なわれていないらしく、そのために初回の起動時にこのコマンドを実行する必要があるようです。

またこのコマンドを実行しないとどうなるか、についてですが、このコマンドを実行していないと基本的な Linux コマンドへの PATH や、その他の環境変数などが一切設定されず、

あれ、なんか何も出来ないぞい……?

と言う状態になります。

※ 私は一度やらかして最初から手順を見直すとかしてました。ナンテコッタイ

NixOS on WSL2 を使う際の注意点

さてここまでの作業が成功しているとするならば、晴れて NixOS on WSL2 が使える様になっていると思うのですが、この NixOS on WSL2 の環境は通常のインストール時の NixOS と使い勝手や一部制約が違い、/etc/nixos/configuration.nix などを編集して設定する際には色々と工夫する必要があるため、最後にその点を紹介してこの投稿を終えたいと思います。

systemd を起動するための hack script は常に必要

まず rootfs を作る際に紹介したリポジトリである、

には、

  • syschdemd.nix
  • syschdemd.sh

の二つのファイルが含まれています。そしてこの両者は /etc/nixos/configuration.nix でシステム設定を変更する際には 必ず要求されます

と言うのもこの両者のファイルは、syschdemd.sh が NixOS on WSL2 での bootloader に相当する hack を行うスクリプトであり、syschdemd.nix がそのスクリプトをシステムにインストールするためのパッケージ定義ファイルとなっているため、この両者はシステム定義の更新の際には常に必要とされます。

また仮にこの両者に相当するスクリプトと定義ファイルを用意すればこれらのファイルは不要となるのですが、その辺りを不用意に触ると NixOS on WSL2 の環境が起動しなくなると考えられるため、カスタムスクリプトを用いた NixOS on WSL2 が動作する確証が無いのであれば、この辺りのファイルは基本的に触らないでおく方が無難だと私は考えています。

最大の利点である bootloader でのロールバックが出来ない

そして更に注意が必要なのが NixOS on WSL2 では通常の Hardware に NixOS をインストールした場合と違って、bootloader によって systemd が linux の PID 1 になっているのではなく、 WSL2 の起動時に root shell で nsenter を使って systemd を擬似的に PID 1 にしている と言う構造で systemdの PID 1 と言う動作を実現しているため、NixOS 最大の利点である bootloader でのシステムのロールバックが出来ません

そしてこの点が通常の NixOS と NixOS on WSL2 の最大の違いだと私は考えていますが、NixOS on WSL2 ではシステム定義の更新の際に、 常に新しい wsl console を使って NixOS on WSL2 が起動するかどうか を確認する必要があると思っています。

と言うのもこれを怠った結果として NixOS on WSL2 の起動プロセスが壊れた際に、NixOS on WSL2 の復旧は困難なのではないか? と考えられるからです。

また仮に起動トラブルも強い NixOS だとしても、WSL2 上で利用する際には他の Linux Distribution と同じく、起動プロセス周りの設定は慎重に扱う必要があると思います。

NixOS on WSL2 でも NixOS の基礎知識が必要

最後に当たり前と言えば当たり前なのですが、今回解説した NixOS on WSL2 を実現する方法は、NixOS を WSL2 で取り扱う方法であるため NixOS を扱う際の基本的な知識は必要になります。

そしてさらに言えば NixOS on WSL2 と言う実行環境は NixOS と言う独特な Linux Distribution を、これまた特殊な Windows Subsystem for Linux 2 と言う環境で取り扱う話であるため、これを使いこなすには NixOS と WSL2 の両方の知識が求められます。

そのため今回紹介した手法は どう考えても NixOS や WSL2 の初学者には向いていないのではないか? と私も思うのですが、今回の記事で NixOS に興味を持った方や、NixOS on WSL2 って出来るの? と思われている方の参考になれば幸いです。

と言う事で今回の話は以上となります

ちなみに今回の投稿内容ですが、この内容は実は以前に私のブログで書いた、

と言う話の焼き直しに過ぎません。が、上記リンク先の元記事は あまりにも雑 だったと自分でも思ったため、今回は NixOS とは何か? と言う話から、NixOS on WSL2 の実現の仕方、あと NixOS on WSL2 特有の注意点などを丁寧に書くことを意識して Zenn.dev への投稿として書き直しました。

そのためこの投稿の本文が自分の中での長文ブログ記事(だいたい3,000~4,000字)二枚分ぐらいの分量となった……のですが、今回の内容、コードの分量よりもテキスト情報の方がはるかに多い ためここまで読み切るのには結構時間が掛かるんじゃないかと思ってます。良いか? あとで読むにつっこんで放置するんじゃないぞ!

まぁでも NixOS や NixOS を WSL2 で使ってみるのは結構楽しいし実用的ではあるので、NixOS と Windows 10 環境と統一したい! と思ってる方にはこの記事は参考になるんじゃないかな、と個人的には思ってます。(いやそれお前だけじゃね? とは思うんだけども)

あと NixOS や Nix package manager についての利点・欠点も結構まじめに記載したので、そう言った面からも読み応えがあるんじゃないかなーと思ってます。(とは言え十分に話が長過ぎるんですが)

と言う事で Zenn.dev への最初の投稿記事はそんな感じでした。はい。

いやどう考えて話が長いんじゃが、是非も無いよネ!