Wine を箱《コンテナ》のなかで愉しもう

概説

この記事のゴール

LXC/LXD による非特権の仮想化コンテナで Wine を動作させ,SSH の X11 Forwarding でウィンドウをホスト環境に引っ張ってきて利用します。

前提条件

Wine について

Wine とは何か

ブドウからつくられる醸造酒……ではなく,早稲田大学図書館の蔵書検索システム……でもなく,UNIX 系 OS 上で Windows 用バイナリを動作させる互換レイヤです。オーバーヘッドが低いことが特徴です。

なぜ Wine 環境を仮想化すべきか

最大の理由はセキュリティ上の問題への対応です。かつて Wine のセキュリティについては「原理的にはマルウェアも動作するが現実にはそこまでの互換性はない」と言われてきましたが,Wine の開発の進展に伴い,高度な API/ABI を使わないマルウェアであれば,かなり動作するようになってきています(世間を騒がしたランサムウェア WannaCrypt も Wine で動作したようです [ref]WineHQ – WannaCrypt[/ref]。Windows の SMB 実装に依存していたことを考えれば,興味深い事実です)。また,Wine には有効な権限管理機能がまだありません。コンテナ型仮想化は一般に厳密にはサンドボックスとしては利用できませんが,今回の用途においては実用上充分かと思います。

さらに,Wine では実質的に i386 のライブラリの導入が必須でパッケージ管理がごちゃごちゃしてしまうところ,環境を切り分けてホスト環境をクリーンに保てるというメリットもあります。

もちろん,環境をポータブルにできて問題が生じたときの対処もしやすいという仮想化一般のメリットも享受できます。

Wine 環境を仮想化することによる制限

デフォルトではハードウェアのグラフィックアクセラレーションを利用できず,ソフトウェア描画となります。少し設定すれば有効化することができますが,ポータビリティが損なわれますので,特に理由がなければそのままでいいと思います。(いずれ気が向いたら追記……)

また,グラフィックアクセラレーションを有効化しても,X 関連の環境変数や設定の関係で,一部のアプリケーションが正常に動作しません。試した範囲では,Linux 版の Slime Rancher や Wine で動くはずの洞窟物語が動作しませんでした。地道に調べて設定を修正していけば解決できそうですが,今回のところは試していません。

さらに,当然ですが,ホスト側のファイルに直接アクセスできないため,ファイルのやりとりは少し考える必要があります。

LXC/LXD について

LXC と LXD の違い

LXC は Linux Container の略で,カーネルの仮想化機能を利用するためのユーザスペースのインタフェース(ツール群)を指します [ref]Linux Containers – LXC – イントロダクション[/ref]。

LXD は,公式にはアナウンスされていませんが Linux Container Daemon の略とされ [ref]2014年11月7日号 LXD(“Linux Container Daemon”)・UWN#340:Ubuntu Weekly Topics|gihyo.jp … 技術評論社[/ref],追加の機能を提供したり,LXC のラッパーとして機能を統合したりすることで,仮想化環境としてより簡単に利用できるようにするものです。

現在はどちらも Canonical の支援のもと開発されています。

なぜコンテナ仮想化か

コンテナ仮想化ではカーネルの cgroups などのリソース隔離機能を使って――ホストと同じカーネルを使って――仮想化します。そのため,KVM や Virtualbox のような VM(ホスト)型仮想化と比べ,オーバーヘッドが非常に低いという特長があります。

原理上,同じカーネルを使える Linux ディストリビューション以外は利用できなかったり,サンドボックスとしての利用を前提としていないといった制約もありますが,少なくとも今回の用途では問題にならないでしょう。

なぜ Docker ではなく LXC/LXD か

気分です。あえて言うなら……

  • Docker はサービスをコンテナ化する思想が明確であるのに対し,LXC/LXD はどちらかといえばシステムをコンテナ化する思想……な気がする→デスクトップユースに親和的で,今回の用途にも合ってる
  • LXC は Debian のレポジトリにもあるので将来的に非互換性が出てもがんばれば対応できそう
  • だいたい Docker 界隈のシュッとした雰囲気がなんとなく場違いで落ち着かない

……まあなんというか,SSH でつなぐだけなのでどっちを使っても同じだと思います。

なお,Wine が導入されたサードパーティの Docker コンテナも公開されているので,抵抗がない方であれば,そういったものを使わせてもらうという選択肢もあります(手間はそれほど変わりませんが)。

Wine を箱詰めする

Snappy での LXD 導入

前置きが長くなってしまいました。どんどん行きましょう。

ホストマシンの OS は Debian 10 で hostname は "host",コンテナの hostname は "wine",ユーザ名はどちらでも "hoge" とします。

先述の通り LXC は Debian のレポジトリにありますが,いろいろと面倒が多いので Snappy を使って LXD をインストールします。

Snappy は "snapd" としてレポジトリにありますので,簡単かつ安全に導入できます("snap" は別のパッケージなのでご注意ください)。

root@host:~# apt install snapd
root@host:~# snap install core
root@host:~# snap install lxd
root@host:~# /snap/bin/lxd init

Debian 10 では必須のパッケージ "core" がなぜか導入されず,パッケージをインストールしようとすると失敗するため,事前に明示的に導入する必要があるようです。

lxd init では初期設定についていろいろ聞かれます。全てデフォルトで大丈夫かと思いますが,loop device の大きさは使い方によって調節するといいかもしれません。なお,–auto ですべてデフォルトにすることもできます。

パスを通す

希望する場合,

export PATH=$PATH:/snap/bin

~/.bashrc 等お使いの設定ファイルに追加することでパスを通すことができます。

ホスト環境で使用するユーザを lxd グループに加えます。

root@host:~# gpasswd -a hoge lxd
hoge@host:~# newgrp lxd

newgrp はシェルごとに実行する必要がありますが忘れがちなので、いろいろと作業する予定の場合は一回ログアウトしてログインし直すとよいでしょう。

コンテナ構築

コンテナの準備

hoge@host:~$ /snap/bin/lxc launch images:debian/10/amd64 wine

あれこれダウンロードするので少し待つ必要がありますが,たったこれだけコンテナの作成は完了です。非常に簡単ですね。

ホストのユーザ権限で実行していることに注意してください(非特権コンテナ)。

ここではホストと同じ Debian 10 を選択しましたが,他のディストリビューションをインストールすることもできます。

なお,ファイアウォールを導入している場合,この先に進む前に LXD が用意してくれるブリッジである lxdbr0 を介しての通信を許可します。以下は ufw での例です。

root@host:~# ufw allow in on lxdbr0
root@host:~# ufw route allow in on lxdbr0

以下ではコンテナにログインし,環境のセットアップを進めていきます。

hoge@host:~$ /snap/bin/lxc exec wine bash

コンテナ内のシェルであることをよく確認してください。

必要なソフトウェアのインストール

root@wine:~# apt install wine ssh wget fonts-vlgothic sudo bash-completion sakura
root@wine:~# dpkg --add-architecture i386 && apt update && apt install wine32

とりあえず必要なものをぶち込みます。

普通の感覚で言えばターミナルエミュレータ (sakura) 自体を ssh -X で持ってくるのはどうかしていますが,今回はローカル完結・X11 forwarding 前提という特殊なケースなので,これも現実的な(そして便利な)方法です。容量を気にしないのであれば,Thunar のようなファイラや Gedit か Mousepad のような GUI テキストエディタも入れておけばなお良いでしょう。Wine Explorer や Wine Notepad が Wine にバンドルされていますが,使い勝手はいまいちです。

ロケール・タイムゾーン設定

root@wine:~# sed -i -e 's/# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/g' /etc/locale.gen && locale-gen && update-locale LANG=ja_JP.UTF-8 && timedatectl set-timezone Asia/Tokyo

unattended-upgrades をぶちかます

unattended-upgrades をぶちかまします。

root@wine:~# apt install unattended-upgrades && dpkg-reconfigure unattended-upgrades

TUI の設定画面が立ち上がるので,有効化します。

アップデート履歴の報告を受ける

アップデート履歴をローカルメールで受け取るには,以下のようにオプションのコメントアウトを外したうえで “root” 等を指定します。

root@wine:~# vi /etc/apt/apt.conf.d/50unattended-upgrades
Unattended-Upgrade::Mail "root";

固定 IP に

初期設定では DHCP になっているので,固定 IP にします。mDNS を使う方法もありますが,今回の用途ではあまりメリットはないかと思います。

root@wine:~# vi /etc/network/interfaces
auto eth0
iface eth0 inet dhcp

とあるのを

auto eth0
iface eth0 inet static
   address 10.125.230.30
   netmask 255.255.255.0
   gateway 10.125.230.1
   dns-nameservers 10.125.230.1 1.1.1.1

などと書き換えてください。構成されるレンジはインストールごとに異なりますので,ip addr して lxdbr0 についての情報を確認してください。

X11 Forwarding で IME 入力に対応させる

いつもの儀式をこなします。まずはサーバ側であるコンテナから。

root@wine:~# vi /etc/ssh/sshd_config

以下を追加。

AcceptEnv XMODIFIERS

ところで Debian の公式イメージと異なり nano は入っておらず素の vi ではなく vim が最初から入っているようです。なんで?

次にクライアント側であるホスト。sshd_config ではなく ssh_config を開くことに注意。

root@host:~# vi /etc/ssh/ssh_config

以下を追加。

SendEnv XMODIFIERS

もし SendEnv LC_* がない場合,それも追加してください。

そしてホスト環境のお使いのユーザの .bashrc に以下を追加します(UIM の場合)。

hoge@host:~$ vi .bashrc
export GTK_IM_MODULE=uim
export QT_IM_MODULE=uim
export XMODIFIERS=@im=uim

ユーザ環境構築

ユーザ作成

root@wine:~# adduser hoge
root@wine:~# gpasswd -a hoge sudo

そういえば root にはデフォルトではパスワードが設定されていない(ログインできないようになっている)ようです。これまでしてきたように lxc exec からコンソールに入れるのでそのままでいいかと思いますが,必要な方はついでにパスワードを設定しましょう。

公開鍵の設定

パスフレーズ不要の公開鍵認証を設定しておきます。このあたりはお好みで。

まだない場合は,ホスト環境で鍵を生成します。

hoge@host:~$ ssh-keygen -t rsa -b 2048 -C "Local"
hoge@host:~$ cat .ssh/id_rsa.pub
RSA v. ECDSA

面倒なので LAN の外と中は単に鍵の種類で使い分けるという運用をしているゆえ,ここでは RSA 2048bit を使っていますが,外向けサーバについて言えば RSA 暗号の使用はもう時代遅れで,ECDSA 521bit を使うのが今どきの標準です。為念。

hoge@host:~$ ssh-keygen -t ecdsa -b 521 -C "A much better key"

そして,先程作成したコンテナユーザでログインし,公開鍵の設定をします。

root@wine:~$ su - hoge
hoge@wine:~$ mkdir .ssh
hoge@wine:~$ vi .ssh/authorized_keys

あとは先程 cat で表示した公開鍵を適当にコピペしましょう。

基本的には,これで完了です。あとは ssh の X11 Forwading でお好きなアプリを起動しましょう。

hoge@host:~$ ssh 10.125.230.30 -X wine '~/bin/windozeblob.exe'

ショートカットを作成すればダブルクリックで起動でき,ホスト環境に直接 Wine を導入するのと変わらない使用感です。ショートカットにしてもいいですし,.ssh/config に登録しておいても便利です。ホストを再起動してもコンテナは自動で立ち上がります。

ホストの Thunar からコンテナのファイルシステムにアクセスできるようにする

Thunar は sftp に対応しているため,ついでにコンテナのファイルシステムにアクセスできるようにしておきます。

root@host:~# apt install gvfs-backends

Buster ではなぜか gvfs-backends だけ入っていないので,入れます。

既に公開鍵認証の設定は済んでいるため,あとは Thunar のアドレスに

sftp://10.125.230.30/home/hoge/

と入れて Enter を押せば,アクセスできます。サイドパネルに追加しておくとすぐアクセスできて便利です。

めでたしめでたし。

2021-01-28 ネットワーク関連について加筆修正

コメントを残す

投稿にあたり,完全な IP アドレスが保存されます(公開されません)。

コメントはスパムフィルタで処理され,承認後に公開されます。