Windows Subsystem for Linuxでディストリビューションを複数展開する

## 追記

下記は Debian12 として 作業していますが、/etc/issueを確認すると Debian11でした。
AppXのパッケージ名…。

## はじめに

Windows Subsystem for Linuxで、あるディストロを複数展開しようと思うと export/import するやり方が一般的かと思います。

WSL上で色々作業をしていて、クリーンなイメージが欲しいなと思ったので そのやり方とかの記録です。

::: note warn
この記事は私個人、独自の調査に基づいて行っています。
正しいオペレーション手順かどうかはわかりません。
:::

## 1. WSLで利用するイメージの取得

WSL上で展開するイメージを取得します。

### 1-1. 元になるAppxBundleのダウンロード

[Microsoft Learning - ディストリビューションのダウンロード](https://learn.microsoft.com/ja-jp/windows/wsl/install-manual#downloading-distributions)

ここで AppxBundleファイルが入手できます。

### 1-2. install.tar.gz の取り出し

AppxBundleを Zipとして解凍すると、例えば Debianであれば、以下のファイルが手に入ります。

```text
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2022-03-28 08:44:20 .....     86334776     86334776  DistroLauncher-Appx_1.12.2.0_ARM64.appx
2022-03-28 08:44:22 .....        49121        49121  DistroLauncher-Appx_1.12.2.0_scale-100.appx
2022-03-28 08:44:22 .....        60609        60609  DistroLauncher-Appx_1.12.2.0_scale-125.appx
2022-03-28 08:44:24 .....        73249        73249  DistroLauncher-Appx_1.12.2.0_scale-150.appx
2022-03-28 08:44:26 .....       230687       230687  DistroLauncher-Appx_1.12.2.0_scale-400.appx
2022-03-28 08:44:36 .....     88224853     88224853  DistroLauncher-Appx_1.12.2.0_x64.appx
2022-03-28 08:44:36 .....         2861          632  AppxMetadata\AppxBundleManifest.xml
2022-03-28 08:44:36 .....          338          272  AppxBlockMap.xml
2022-03-28 08:44:36 .....          469          246  [Content_Types].xml
2022-03-28 08:44:40 .....        11967         8259  AppxSignature.p7x
------------------- ----- ------------ ------------  ------------------------
2022-03-28 08:44:40          174988930    174982704  10 files
```

今回は x64 の Windowsなので、DistroLauncher-Appx_1.12.2.0_x64.appxを解凍して取り出します。

この Appx を更に Zipとして解凍します。

```text
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2022-03-28 08:43:26 .....        21259        21259  Assets\LargeTile.scale-200.png
...省略...
2022-03-28 08:43:26 .....        15336        15336  Assets\Wide310x150Logo.scale-200.png
2022-03-28 08:43:26 .....       305152       124494  debian.exe
2022-03-28 08:43:26 .....     87858067     87858067  install.tar.gz
2022-03-28 08:43:26 .....         4376         1132  resources.pri
2022-03-28 08:43:26 .....         3706         1366  AppxManifest.xml
2022-03-28 08:43:26 .....        84978        47880  AppxBlockMap.xml
2022-03-28 08:43:26 .....          744          317  [Content_Types].xml
2022-03-28 08:43:26 .....        12058         8250  AppxMetadata\CodeIntegrity.cat
2022-03-28 08:44:36 .....        12006         8294  AppxSignature.p7x
------------------- ----- ------------ ------------  ------------------------
2022-03-28 08:44:36           88450782     88219495  30 files
```

この中にある install.tar.gz が Debianのファイルシステムに含まれるファイルのアーカイブです。
これを取り出します。

## 2. WSLのイメージとしてimportする。

取り出した install.tar.gz を使って import すれば終わりです。

importするファイル名がわかりにくいので、Debian_12.2.0_WSL.tar.gzに名前を変えておきます。

また、WSLのvhdxを格納するフォルダが必要です。
ユーザプロファイルのドキュメントフォルダにWSLというフォルダを作って格納するようにします。

ここでつける名前（以下では Debian12 としています）を色々変えれば同じディストリビューションを複数展開できます。

```cmd
mkdir "%USERPROFILE%\Documents\WSL"
wsl --import Debian12 "%USERPROFILE%\Documents\WSL\Debian12" Debian_12.2.0_WSL.tar.gz
```

実行するとこんな結果になります。

```console
C:\Users\xxxxx\Documents>wsl --import Debian12 "%USERPROFILE%\Documents\WSL\Debian12" Debian_12.2.0_WSL.tar.gz
インポート中です。この処理には数分かかることがあります。
この操作を正しく終了しました。
```

## 3. シェルの起動

```cmd
wsl -d Debian12
```

このコマンドで起動するとrootユーザでログインされます。

## 4. 一般ユーザの追加とデフォルトユーザの切り替え

wslを起動した後に user を追加します。Debianだとこんな感じ。

```bash
# Linux上での操作
adduser ユーザ名
usermod -a -G sudo ユーザ名
```

ここで作成したユーザのUIDが1000だとして、デフォルトログインユーザを変更します。

### Registryの検索

ディストリビューションの情報が格納されているRegistryキーを検索します。

```cmd
reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss /s /d /f ディストロ名
```

出力はこんな感じです。

```console
C:\>reg query HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss /s /d /f Debian12

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
    DistributionName    REG_SZ    Debian12
    BasePath    REG_SZ    \\?\C:\Users\xxxxx\Documents\WSL\Debian12
```

これで `HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}` に記録されていることがわかります。

### デフォルトログインユーザの変更

Registryの DefaultUid(REG_DWORD) を 作成したユーザのUIDに変更します。

```cmd
reg add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} /v DefaultUid /t REG_DWORD /d 1000
```

実行するとこんな感じです。

```text
C:\>reg add HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} /v DefaultUid /t REG_DWORD /d 1000
値 DefaultUid は存在します。上書きしますか? (Yes/No) yes
この操作を正しく終了しました。
```

念のため確認。

```text
C:\>reg query HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Lxss\{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
    State    REG_DWORD    0x1
    DistributionName    REG_SZ    Debian12
    Version    REG_DWORD    0x2
    BasePath    REG_SZ    \\?\C:\Users\xxxxx\Documents\WSL\Debian12
    Flags    REG_DWORD    0xf
    DefaultUid    REG_DWORD    0x3e8

C:\>wsl -d Debian12 --cd ~
xxxxx@hostname:~$
```

## 5. 使い始め

パッケージ類をアップデートして使う。
本当にミニマルなので、必要なパッケージ類も追加する。

### Debianの AppxBundleについて

他のパッケージはわかりませんが、Debianのパッケージについては MSサイトからダウンロードしたイメージを使うと(install.tar.gzを取り出してimportしていなくても)、少し変なところがあるようです。

以下は私が気が付いた限りですが、気になる方は Storeにあるものを使うようにしたほうが良いかもしれません。

1. /etc/mtabが無い
2. トップレベルの /bin, /lib, /lib64, /sbinの扱いが本家を普通にInstallしたときと違う

1は appImageを使ったとき unmountされない事象に悩まされます。

2は Debianのbuster以降、`/lib` や `/lib64`等は、`/usr/lib`、`/usr/lib64`等へのシンボリックリンクになっています。この install.tar.gz の中身ではそのようになっていません。

追記： Bullseyeを最後に /usr への移動が行われたようです[^usrmerge] [^bullseye-release-notes]。

[^usrmerge]: https://wiki.debian.org/UsrMerge
[^bullseye-release-notes]: https://www.debian.org/releases/bullseye/i386/release-notes/ch-information.ja.html 5.3.2. bullseye で非推奨となったコンポーネント

以下は、これらの修正用のscriptです。--importした直後にrootで実行しています。

```bash
{
  # create mtab.
  ln -s /proc/self/mounts /etc/mtab

  apt update
  apt install usrmerge
  apt upgrade
}
```

## 6. 削除

以下で登録したWSLを削除可能です。
ただし、WSLの格納フォルダは削除されないので手動で削除する必要があります。

```cmd
wsl --unregister Debian12
rmdir "%USERPROFILE%\Documents\WSL\Debian12"
```

## おわりに

まだ、それほど使い込んでいませんが、こんな感じでWSLのクリーンなインスタンスを作る事ができるようになりました。