Hyper-VでLinux環境(ArchLinux)を立ち上げてみる
特にArchLinuxに詳しいとかでは無いが、なんとなくやってみたくなったのでメモ。
方針・目標など
WindowsからHyper-V上のarchlinuxへの接続にはsshを使う。
Windows Terminalのプロファイルに登録しておくことで、WSLを起動するのと大きくは変わらない使用感(?)で楽に起動できるようにする。
ゆるふわ勢なのでインストールにはarchinstall
:
を使ってあまり頑張らずにやる。ManjaroにDesktop無しのサーバー版があればそれで良かったような、という気もする)
(ユーザーの作成やssh周りの設定などは、鍵の登録を自動化しやすかったりパッケージインストールなど諸々のセットアップができるのでcloud-init
を使って行う。
↓なお、他のディストリビューションでも知見を使い回しやすいのも大きい
検証環境
- Windows11 Pro
- バージョン23H2(OSビルド22631.3593)
- Hyper-V マネージャー バージョン: 10.0.22621.1
- 使ったarchlinuxのisoファイル:
手順
まず、Hyper-Vの有効化はまだであれば
などを参考に行っておく。
仮想マシンの作成
Hyper-Vマネージャーを開いて、画面右の「新規」→「仮想マシン」を開いて仮想マシンを作っていく。
仮想マシンの新規作成ウィザードが立ち上がるので、適当に入力していく:
名前は自分がわかりやすいものを適当につける。今回はarchlinux-example
にした。
世代は第2世代にしておく。
今回は"Default Switch"を選択する。
他の選択肢との比較については例えば
などを参照。
インストールオプションでarchlinuxをインストールするためのisoファイルを指定する。
(仮想マシンに仮想DVDがアタッチされた感じになる)
先述の通り今回は↑から取得した。
に他のミラーサイトもあるので適当なところから選んで最新版を取得する。
他の項目は適当に設定する。
(今回、触れてないところは全部デフォルトで設定した)
仮想マシンの新規作成ウィザードでの作業はここまでで終わりだが、
Linux仮想マシンを起動する際はトラップがあり、すぐに起動せずに一旦作成したマシンの「設定」を開く:
↑Linuxを起動する際は必ず「セキュアブート」をOFFにする
(デフォルトではONになっているが、OFFにしないと起動できない)
セキュアブートONだと起動時に↓のようなエラーになる:
仮想ハードディスクへのarchlinuxのインストール
仮想マシンの作成と設定を一通り行ったら仮想マシンを起動する。
正しく起動できると↓
みたいなのが出て、
少し待つとroot@archiso
にログインした状態になる↓:
本来的にはここから
などを参考にインストールしていく感じになるが、
冒頭で書いたようにもう少し楽にインストールする方法としてarchinstall
コマンド:
が使えるのでこれを使っていく。
先程のroot@archiso
にはarchinstall
コマンドへのパスが通っているため、
archinstall
と実行すれば以下のような画面が起動する:
十字キーでカーソル移動+適当に各項目を選択・入力すればOKで結構直感的に操作できる。
いくつかだけピックアップしてメモしておく:
Mirrorsでは、スラッシュ"/"を打ってから"Japan"と入力すればリポジトリに日本のミラーサイトを登録できるので、
好みで設定しておく。
キーボードレイアウトはデフォルトでUS配列となっているので、必要に応じて"Locales"から適宜変更する。
日本語配列は"jp106"なので"/jp"などと入力して検索・選択する。
"Disk configuration"は必須選択項目で、必ず設定が必要。
今回は"Use a best-effort default partition layout"を選択した。
作成した仮想ハードディスクの容量とほぼ同様になっている/dev/sda
を選択する。
ファイルシステムは"ext4"を選択した。
/home
を別パーティションに分けるかどうか。
好みや用途次第だが、今回は"no"を選択した。
"Profile"で、用途に合わせたものを選ぶと必要そうなものをある程度インストールしてくれる。
今回はホスト(Windows)側からssh接続したいのでTypeは"Server"の"sshd"を選択↑
"Network configuration"では、ホストからsshしやすくしたいのでデフォルトにはせず、
Use NetworkManager
を選択する。
これによって、ゲストにログインしてip a
を叩くなどしてIPアドレス(DHCPなので変わる可能性もあるらしい)をいちいち調べる必要がなくなり、<設定したホスト名>.mshome.net
を指定すれば良くなる。
(ex. ssh <username>@<設定したホスト名>.mshome.net
)
"Additional packages"について、インストールしたいパッケージ名を書くとはじめにインストールしてくれるようになる。
(リポジトリに存在しないものを入力するとメッセージを出した上で弾いてくれるため安心)
今回はcloud-init
を使うため、
-
cloud-init
- (後でプロビジョニングする用)
-
cloud-guest-utils
- growpart(後からディスクを拡張した際に、自動でパーティションサイズを調整してくれる)などを使えるようにしておく
は最低限入れておく。
また、x11を使いたいため、
x11に必要なもの+動作確認用のために
xorg-server
xorg-apps
-
xf86-video-fbdev
- GUIの表示に必要なビデオドライバー
-
xf86-video-vesa
でも良いかも(xf86-video-fbdev
→xf86-video-vesa
の順で使おうとするらしい) - (参考) https://wiki.archlinux.jp/index.php/Xorg
-
xorg-xeyes
- 動作確認用
なども入れておく。
(GUIやクリップボード共有機能が一切必要無ければ↑は不要)
また、デフォルトだと結構びっくりするくらい何も入っていない(less
コマンドも無いしエディタも入っていなかったり)ので、
必要そうなものがあれば入れておく。
あとは"Root password"を適当に設定する。
※一般ユーザーは後でcloud-init
で作るため今回は作成・設定しないことにする。rootでのログインは最終的には禁じた方が安心だが、最初はrootでログインする手段が残っている方がやりやすく、後から出来なくすれば良いというスタンスを取っている。
最終的に↓のような感じ:
(参考) 設定の保存
"Save configuration"を選択すると、
上記の手順で選択・入力した内容をjsonファイルとしてエクスポートできる。
によるとarchinstall
コマンド実行時に引数としてファイルの読み込みが可能なので、
今後同様の作業を行う可能性がある場合はここで保存しておくと良い。
"Save all"を選択し、適当なパスを指定するとそこにuser_configuration.json
およびuser_credentials.json
(※パスワードはハッシュ化などはされておらず平文で書き込まれているので注意)を保存できる。
インストール作業完了後、すぐにrebootせずに、例えば、
まずは仮想マシンのIPアドレスをip a
などで調べておき、
保存したファイルがあるディレクトリで
python -m http.server
を実行し、8000ポートで公開すると、
Windows側で"http://<先ほど調べたIPアドレス>:8000"にアクセスすると、
user_configuration.json
とuser_configuration.json
が見えるのでここでダウンロードしておく。
あとは"Install"を選択し、Enterを押すとインストールが開始される:
無事に一通り終わると以下のように聞かれる:
yesを選択するとインストールしたメディアにchroot
して必要な初期セットアップができる。
今回はcloud-init
のservice有効化をしたいのでyesを選択する。
cloud-initを有効化するため、
systemctl enable cloud-init
systemctl enable cloud-init-local
systemctl enable cloud-config
systemctl enable cloud-final
を順次実行する。
(他にも初期セットアップとしてやりたいことがあれば適宜やっておく)
exitで抜けると"Installation completed without any errors. You may now reboot."と出る。
先ほど(参考)と書いたところで説明したようにuser_configuration.json
とuser_credentials.json
を保存したい場合はすぐにrebootやshutdownをせずに、適宜これらのファイルを回収しておく。
ここまで一通り終わったら一旦shutdownする。
(今回、cloud-initで初期設定を行うために新規で仮想DVDドライブをアタッチするのでrebootはしない)
(補足)プロキシ環境下でのインストール
プロキシ環境下ではリポジトリへのアクセスが出来なかったり一部のサービスが死んでいたりするようで、
いくつか追加手順が必要。
具体的には、archinstall
コマンドを実行する前に、root@archiso
ユーザーで
# ↓環境に応じて適当に置き換える
proxy_url="http://username:password@X.X.X.X:80"
export http_proxy=$proxy_url
export https_proxy=$proxy_url
# 環境によっては `ftp_proxy=$proxy_url` なども要るかも
を実行しておく。これでパッケージインストール時にプロキシを突破できるようになる。
ただ、これだけでは不十分で、
のような問題が起こる。
すなわちreflector.service
なるものが正常に動作しなくなるようで、
このためにarchinstall
コマンドが途中で停止してしまう。
同issue中であるように、自身の環境では
# root@archiso
# `archinstall`コマンド実行前に↓を実施する
systemctl stop reflector.service
とすることで直った。
cloud-initによる初期セットアップ
meta-data, user-dataの記入とcloud-init用のメディア作成
やることとしては、cloud-initによる初期セットアップのために以下の2ファイル:
meta-data
user-data
を作成し、これらをisoファイルとして書き出す形になる。
なお、これはDatasourceをNoCloudとした場合(のMethod 1)に相当する:
ここで、
などを参考に、まずはmeta-data
ファイル:
local-hostname: <vm-hostname>
を作成する。(<vm-hostname>
部分は適当に変更する)
ちなみに今回の手順ではhyperv-archlinux
とした。
先述の通り、ここで設定した内容を使って(IPアドレスをいちいち調べずに)今回立てるarchlinuxのゲストOSにアクセスできる。
※archinstall
コマンドで同内容の設定項目(デフォルトではarchlinux
となっている)があり、後から変えないのであればそちらで設定してmeta-data
は無し、ということでも良いのかもしれない(未検証)
次にuser-data
を作っていく。
前準備として、ssh用の鍵を作る必要があるので、ssh-keygen
コマンド(WSLなどでやっても良いし、Windows上でもたぶんC:\Windows\System32\OpenSSH\ssh-keygen.exe
にある)を使って予め作っておく。
今回は例えば、
# archlinux_key_ed25519(秘密鍵), archlinux_key_ed25519.pub(公開鍵)が生成される
ssh-keygen -t ed25519 -f ./archlinux_key_ed25519
# パスフレーズ無しで良ければ↓ など(PowerShellではうまく動かなかった)
ssh-keygen -t ed25519 -f ./archlinux_key_ed25519 -N ""
のように作っている。
次にuser-dataの中身に関して、
や、その他諸々を参考にして設定していく。
今回は、大まかなところでいうと
- uid: 1000のユーザーを作成
- 今回、名前は
vm-user
としている(適宜好きに変える) - パスワード無しで
sudo
を使えるようにする - sshの公開鍵を設定しておく(password認証は禁止しておく)
- 今回、名前は
- sshにおける認証は公開鍵の使用を義務付け
- rootへのsshログインは禁止
- (ただし、Hyper-Vの「接続」からのログインは禁止されていないので注意。)
みたいな感じになる。
(他にも若干設定している)
具体的には例えば以下のような感じ:
#cloud-config
timezone: Asia/Tokyo
locale: en_US.utf8
ssh_pwauth: False
disable_root: True
users:
- name: vm-user
ssh_authorized_keys:
# ↓sshにおけるログインで使う公開鍵の内容(ここではed25519にしているが他のでも良い)
- ssh-ed25519 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX xxxxxxxx@XXXXXXXXX
shell: /usr/bin/bash
sudo: ALL=(ALL) NOPASSWD:ALL
groups: [wheel, users, sudo, adm]
uid: 1000
package_update: true
package_upgrade: true
# 追加でインストールしたいものを↓に列挙していく
packages:
- tmux
- xclip
- xsel
- neovim
- bash
- bash-completion
- zsh
- zsh-completions
- man-db
- man-pages
# ↓最後に以下で設定した内容が順次実行される
runcmd:
# ↓Portをデフォルトから変えたい場合はコメントアウトを解除して適当に変える
# - sed -i -e 's/^#Port 22/Port 2022/' /etc/ssh/sshd_config
- sed -i -e 's/^#PermitRootLogin prohibit-password/PermitRootLogin no/' /etc/ssh/sshd_config
- sed -i -e 's/^#X11Forwarding no/X11Forwarding yes/' /etc/ssh/sshd_config
- systemctl restart sshd
packageで書く部分は前の手順のarchinstall
部分でやってスキップでも良い。
が、手打ちで沢山書くのは大変だし、archinstall
のオプションにファイルを読み込ませるのが意外と面倒そう(isoイメージ側にうまくファイルを渡すか、入力しやすいURLでファイルをネット上に公開するか...)だったので、ごく最低限のものとデバッグに必要なもの以外はcloud-initで入れるのもアリだと考えている。
一通り記入したら、これらをディスクイメージに書き出す。
例えばWSL(Ubuntu)などを使う場合、
# WSLのUbuntu
# genisoimageのインストール
sudo apt install genisoimage
# イメージ作成
mkisofs -output arch-seed.iso -volid cidata -joliet -rock user-data meta-data
のような感じでできる。(参考)
cloud-initによる初期セットアップの実行
仮想マシンにアタッチされているインストールメディア(isoファイル)を除去し、
代わりに先ほどgenisoimage
を使って作成したisoファイルをアタッチする。
この状態で仮想マシンを起動すれば、自動でcloud-initが走ってmeta-data
およびuser-data
で記述した内容が設定される。
仮想マシンの「接続」を開いておくと(※ログインはしない)、↑のような感じで実行状況が表示される。
(実行状況はrootなどでログインして/var/log/cloud-init.log
などを見て確認することもできる)
(あとどうでも良いが、前の手順でxf86-video-fbdevを入れ忘れていたのでここで入れている)
無事に終わってそうであれば一度shutdownして再起動すると確実かも?しれない
(設定内容次第ではしなくても良いのかも)
うまくいってなさそうなら、/var/log/cloud-init.log
の内容を参照しつつuser-data
とisoファイルを作り直し、
再実行していく。
cloud-initの再実行は
などを参考
一通り終わったら、仮想マシンにアタッチされているcloud-init用のisoファイルを外しておく。
ホスト(Windows)からゲスト(archlinux)へのログイン
仮想マシンを起動しておけば、自動でsshdサーバーが起動しているためホスト(Windows)側からssh接続することができる。
Windowsにもおそらくデフォルトでsshは入っている(C:\Windows\System32\OpenSSH\ssh.exe
など)ので、それを使ってログインする。
# 秘密鍵はuser-dataに記入した公開鍵と対になっているものを指定
# `vm-user`部分はuser-dataで作成したユーザー名に、
# `hyper-v-archlinux`はmeta-dataで指定したホスト名にそれぞれ置き換える
ssh.exe -i <作成した秘密鍵のパス> vm-user@hyperv-archlinux.mshome.net
↑のように無事、PowerShellなどからsshログインできる。
(※archinstall
時にNetworkManagerを設定しなかった場合、<ホスト名>.mshome.net
を指定してsshすることは出来ず、別途IPアドレスを調べる必要がある)
なお、Hyper-VのDefault SwitchとWSLのネットワークは通常つながっていないため、
WSLからHyper-Vのゲストにsshにすることは出来ない。(設定を頑張れば出来るらしいが今回はやらない)
X11の動作確認(VcXsrv)
個人的にはCUIベースの操作が多くてもclipboardの共有などのためX11(X Window System)を使えるようにしたいことがある。
先述の通り、WSLからではなく素の(?)Windowsからsshしているため、そのままではX11は使えないので、別途入れる。
無償で使えるものとしてはVcXsrv
:
などがあるのでこの辺を使う。
なお、wingetが使える状況であれば、
winget install vcxsrv
などとしてインストールできる。
インストールしたらWindowsキーを押して"xlaunch"などと入力して検索すると"XLaunch"が起動する。
こだわりが無ければひたすらEnterを押しまくれば良い。
するとWindowsから見てlocalhost:0.0
にXクライアントを起動出来る。
(今回はやらないが、都度X Launchを起動するのが面倒であれば自動起動する方法もあるので、「VcXsrv 自動起動」や「x launch 自動起動」などでググる)
sshするときに上記を環境変数DISPLAYとしてセットすると、リモート側(ゲストOSのarchlinux)のGUIアプリをWindows側で実行できる。
# PowerShellでは、環境変数は $env:<環境変数名> = <設定内容>で設定できる
# GUIを使う場合、X11の自動転送を有効化するためsshのオプションに`-XY`を追加する
$env:DISPLAY = "localhost:0.0"; ssh.exe -XY -i .\archlinux_key_ed25519 vm-user@hyperv-archlinux.mshome.net
↑ちゃんとxeyesが動いており、Windows側で操作できる。
※Warning: No xauth data; using fake authentication data for X11 forwarding. が出るが、個人的に使う範囲で実害はたぶん無いのでここでは放置する。
※リモート側の/etc/ssh/sshd_config
ファイルなどでX11Forwarding yes
が設定されている必要があるので、うまく動かない場合はその辺も確認すること
ssh_configの設定
秘密鍵の指定やX11の転送設定、更にはホスト名もmshome.net
まで入れると結構長くて都度打つのは疲れてくる。
(設定次第では当然もっとオプションは増えてくる。ポート番号など)
これだと大変なので、ssh_configを作成する。
Windows(C:\Windows\System32\OpenSSH\ssh.exe
)ではC:\Users\<ユーザー名>\.ssh\config
(あるいは、同じ意味だが%USERPROFILE%\.ssh\config
)を作成・編集すれば良い。
記載例:
# ↓必要に応じて全プロファイル共通の設定
ServerAliveInterval 60
ServerAliveCountMax 5
# ↓Hostは自分な好きな名前を適当につける
Host archlinux
HostName hyperv-archlinux.mshome.net
User vm-user
# デフォルト(22)なら記述不要だが、ポート番号を変えている場合は書いておく
# Port 22
# 秘密鍵のパスを記述しておく。(Windowsでも書き方はUnix系の書き方になる)今回は%USERPROFILE%\.sshに秘密鍵も置くことにしている
IdentityFile ~/.ssh/archlinux_key_ed25519
# ↓X11の転送設定。それぞれ順にX, Yオプションに相当
ForwardX11 yes
ForwardX11Trusted yes
# (その他適宜オプションを追加)
上記のような設定を書いておくと、↓のようにsshできる。
# sshの引数にはssh_configで設定したHost名を指定できる
$env:DISPLAY = "localhost:0.0"; ssh.exe archlinux
また、Windows側とリモート側でファイルのやり取りをする際にscp
コマンドを便利に使えるようになる:
↑scp
コマンドでもリモートマシンの指定にssh_configで記述したHost名を指定できるので、ssh同様長いオプションなどを省略できる。
Windows TerminalでのProfile設定
X11転送をしてGUIを使う場合、環境変数の設定はまだ直打ちになっており不便である。
また、それがなかったとしてもWindows TerminalでWSLのディストリビューションを選ぶのと同じ感覚でリモートマシンに入れるとより便利である。
↑の"+ 新しい空のプロファイル"から作成・追加する。
名前はわかりやすいものをつけておく(ここでは"ArchLinux(Hyper-V)"とした)。
後はコマンドラインでsshする部分を設定してあげる必要がある。
DIAPLAY環境変数を永続的に設定したくない場合は前の手順のように都度ワンライナー的に設定する形になり、sshする部分と合わせて最低2コマンド分をProfileに設定しないといけないので少し大変になる。
などを参考に、ここでは
%SystemRoot%\System32\cmd.exe /k "set DISPLAY=localhost:0.0&& C:\Windows\System32\OpenSSH\ssh.exe archlinux"
のように設定している。
後は好みでアイコンやフォントなど適当に設定する。
設定したプロファイルをWindows Terminalで選択して開くと:
のようにsshコマンドを打たなくてもはじめからリモートにログインした状態になる。
スクショの通り、X11転送もしっかりできている。
事前に仮想マシンおよびXLaunchの起動をやっておく必要はあるものの、これでかなり手軽に起動できるようになった。
まとめ、雑感
WSL2は便利で大好きなのだが、稀にWSL特有の制約事項で困るケースが稀にある(稀だが...)ので、
どうしても本物のLinuxを使いたかったりするときや、
あるいはセキュリティ的にホストとの隔離度を強くしたい場合には使えそう、
みたいなモチベーションでやってみた。
あと、意外とHyper-V特有の話は少なく、本質的には仮想マシンで立てたsshサーバーにホストからなるべく楽にsshできるようにする、という話でしかない。
なので、例えばLinuxのデスクトップを母艦にしてkvmで作業環境を作る(Gnome Terminalにプロファイル設定する)、といった場合にもほとんど同様の手順でできる。
(サードパーティのX11を使う手順が無くなるのでむしろ楽)
どちらかというと、そういう応用が効くような気がしたのでやってみたというモチベーションが大きかったりする。
Discussion