みなさんメタバース盛り上がってますか!インフラエンジニアの nobuh です。
前回の記事 Mozilla Hubs を VirtualBox でホストしてみた に続いて、PC 上の VirtualBox を使い、今回は 真っ黒ではない自作シーンのルーム に入るところまでを動作確認出来ましたので、その方法を共有したいと思います!
Mozilla Hubs って?
詳しくは前回の記事 Mozilla Hubs を VirtualBox でホストしてみた でも解説していますが、Mozilla Hubs は Mozilla 社が提供している VR のサービスで、オープンソースでも公開されていて、それを PC 上の VirtualBox で運用してみよう! というのが今回の Mozilla Hubs 挑戦シリーズの趣旨になります。
VirtualBox でのサーバー準備
OS 廻りの基本的なところは前回の記事と同じですが、再び概要を列挙いたします。
VirtualBox 設定
- OS : 64 bit Linux
- ネットワークアダプタ: ブリッジネットワーク を使います
- CPU : 2個以上
- メモリ :最少 5G 、推奨 8G 以上
- 仮想ディスク: 30G 以上
Debian 11 インストール
- インストーラー CD : Debian 11.2 bullseye netinst iso
- 国: Asia, Japan
- ロケール : en_US.UTF-8 (メッセージ調査が簡単になるので US にしてます)
- hostname : hubs
- domain : local
- 追加 user : ops2 としましたが何でも可
- パッケージ : ssh, standard utilities のみチェックを付けます。使わない Desktop とかはチェックを外します
- IP アドレス:DHCP で取得した IP をそのまま使っています。お好みで static ip に変更してもかまいません
言語ランタイムは後述する asdf で用意していますので Debian に限らず最近の Ubuntu であればどのバージョンでも問題ないと思われます
OS まわりセットアップ
root でログインし使うパッケージをインストールします。
apt-get update apt install libssl-dev automake autoconf libncurses5-dev make unzip g++ apt install inotify-tools curl git dirmngr gpg gawk sudo apt install ca-certificates gnupg lsb-release
sysctl で fs.innotify.max_user_watches の数を表示し
root@hubs:~# sysctl fs.inotify.max_user_watches fs.inotify.max_user_watches = 50000
5万以下であった場合は /etc/sysctl.conf に fs.inotify.max_user_watches = 50000 を追記して
sysctl --system
で反映してください
DNS 代わりの /etc/hosts 編集
今回は独自ドメインではなくデフォルトの hubs.local と hubs-proxy.local を使う前提で設定を進めていきます。
VirtualBox のサーバー上の /etc/hosts は以下に設定します。
127.0.0.1 localhost hubs hubs.local hubs-proxy.local
ブラウザを動かすクライアントPC自体の /etc/hosts は以下に設定します。(VirtualBox のサーバーの IP が 192.168.0.7 の例)
192.168.0.7 hubs.local hubs-proxy.local
ユーザーと作業ディレクトリ作成
ユーザー ops2 に sudo 権限を付与します。
adduser ops2 usermod -aG sudo ops2
言語ランタイムのキャッシュや設定はユーザーの $HOME 直下の .cache などに蓄積されますので、Mozilla Hubs のインストールをやり直す場合は今回のようにユーザーから新規に作り直すのがお薦めです。
以上で root を一度ログアウトし、sudo 付与済みの ops2 で作業を行っていきます。
ops2 のホーム下に作業用に mozilla ディレクトリを作成しておきます
cd && mkdir mozilla && cd mozilla
Docker と PostgreSQL 11 セットアップ
指定されている Postgres が 11 とやや古いため docker を使ってセットアップします。
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io
一度ログアウト後 docker-compose をインストールします。
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
docker-compose.yml ファイルを以下の内容で作成します。
version: '3' services: db: image: postgres:11 environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres volumes: - ./tmp/db:/var/lib/postgresql/data ports: - "127.0.0.1:5432:5432"
起動します
sudo docker-compose up -d
asdf で node.js v12 セットアップ
node.js や elixir といった各言語のランタイムは asdf を使って特定バージョンを使えるようにします。
まずは asdf をインストール
git clone https://github.com/asdf-vm/asdf.git ~/.asdf echo '. $HOME/.asdf/asdf.sh' >> ~/.bashrc echo '. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc exec $SHELL -l
最初に node.js v12 (erbium) をインストールします。
asdf plugin add nodejs asdf install nodejs lts-erbium asdf global nodejs lts-erbium
自己署名証明書作成
今回は Mozilla Hubs 指定のデフォルトの hubs.local と hubs-proxy.local を使っていますが、それでもデフォルトで自動生成される自己署名証明書の多くは鍵長が足りていない、Subject Alt Name (SAN) が無いなどのエラーを起こしましたので、自分で新規に作成します。
mkdir ~/certs && cd ~/certs echo subjectAltName = DNS:hubs.local,DNS:hubs-proxy.local > san.txt openssl genrsa -out server.key 2048 openssl req -out server.csr -key server.key -new
組織名など聞かれますが何でもかまいません。Common Name (CN) だけは hubs.local で入力してください。(例)
Country Name (2 letter code) [AU]:JP State or Province Name (full name) [Some-State]:Hokkaido Locality Name (eg, city) []:Sapporo Organization Name (eg, company) [Internet Widgits Pty Ltd]:infiniteloop Co,Ltd Organizational Unit Name (eg, section) []:NOBUH Common Name (e.g. server FQDN or YOUR name) []:hubs.local
csr が出来たら san.txt と合わせて自分で署名して証明書を生成します
openssl x509 -req -days 3650 -signkey server.key -in server.csr -out server.crt -extfile san.txt
Hubs セットアップ
GitHub の Hubs リポジトリを clone しますが、変更が激しいためこの記事で確認出来ている特定 commit 4fe2529a9 まで戻します。
cd ~/mozilla git clone https://github.com/mozilla/hubs.git cd hubs git reset --hard 4fe2529a9
certs ディレクトリを作成、最初に作っておいた証明書をシンボリックリンクで配置します。ファイル名は cert.pem と key.pem 固定です。
mkdir certs ln -s ~/certs/server.crt certs/cert.pem ln -s ~/certs/server.key certs/key.pem
他のコンフィグはそのまま修正不要です。local モードで起動します。
npm ci npm run local
ブラウザで https://hubs.local:8080/ にアクセスします。オレオレ証明書のため各社のブラウザで警告が出ますが、無視してアクセスする操作を行います。なんらかのページが表示されていれば OK です。以下 Chrome の例
Admin セットアップ
Hubs のターミナルはそのまま。別のターミナルを開き ops2 でログインします。
次に同じ hubs リポに格納されている admin サーバーをセットアップします。
ここでも作成しておいた証明書を使います。ファイル名も固定です。
cd ~/mozilla/hubs/admin mkdir certs ln -s ~/certs/server.crt certs/cert.pem ln -s ~/certs/server.key certs/key.pem
起動します。(時間がかかります)
npm ci npm run local
https://hubs.local:8989/ にアクセスして Hubs と同じように証明書を例外承認します。
admin サーバーは稼動させたまま。別のターミナルを開きます。
Spoke セットアップ
シーンエディタの Spoke サーバーをセットアップします。こちらも把握出来ている commit まで戻してください。
cd ~/mozilla git clone https://github.com/mozilla/Spoke cd Spoke git reset --hard 9669ef73
yarn と corss-env を npm でインストールします。
npm install -g yarn npm install -g cross-env
必要なパッケージをインストールし
yarn install
ここでも証明書を配置します。
mkdir certs ln -s ~/certs/server.crt certs/cert.pem ln -s ~/certs/server.key certs/key.pem
Spoke サーバーを起動します。
./scripts/run-local-reticulum.sh
https://hubs.local:9090/ にアクセスし、例外承認をして何がしかのトップ画面が表示されていれば問題ないです。
Reticulum セットアップ
Hubs, Admin, Spoke の3つのサーバーが起動されている状態になりましたら、いよいよ中心的なサーバーになる Reticulum サーバーのセットアップに入ります。
Erlang 22 と Elixir 1.8 のインストール
前回の記事では Erlang 23 と Elixir 1.12 を使っていましたが、今回は Erlang 22 と Elixir 1.8 を使いますので注意してください。
asdf plugin add erlang asdf install erlang 22.3.4.24 asdf global erlang 22.3.4.24 asdf plugin add elixir asdf install elixir 1.8.2-otp-22 asdf global elixir 1.8.2-otp-22
次に Reticulum のソースを clone し、把握しているコミットまで戻します。
cd ~/mozilla git clone https://github.com/mozilla/reticulum.git cd reticulum git reset --hard fc80a577
elixir のツール mix や phoenix フレームワークでのビルドを進めます。
mix local.hex --force mix deps.get mix local.rebar --force mix ecto.create mkdir -p storage/dev
証明書を配置します。
ln -s ~/certs/server.key priv/server.key ln -s ~/certs/server.crt priv/server.crt
Dialog 音声サーバーとの通信用の 1024 ビット RSA 秘密鍵 perms.priv.pem と公開鍵 perms.pub.pem を用意します。
cd priv openssl genrsa 1024 > perms.priv.pem openssl rsa -pubout < perms.priv.pem > perms.pub.pem
さらに秘密鍵の値の改行を素の2文字 ‘\n’ に変換したファイル perms.priv.pem.line を sed で作成します。
sed -z 's/\n/\\n/g' perms.priv.pem |sed -E 's/\\n$/\n/g' > perms.priv.pem.line
config/dev.exs ファイルの中の以下の4点を修正します。
- dev_janus_host を hubs.local にする
- keyfile/certfile のパスを自分が置いた server.key, server.crt に
- perms_key の文字列の値として perms.priv.pem.line の内容を貼り付ける
- janus_port を 443 から 4443 に
dev_janus_host = "dev-janus.reticulum.io" ↓ dev_janus_host = "hubs.local" keyfile: "#{File.cwd!()}/priv/dev-ssl.key", certfile: "#{File.cwd!()}/priv/dev-ssl.cert" ↓ keyfile: "#{File.cwd!()}/priv/server.key", certfile: "#{File.cwd!()}/priv/server.crt" config :ret, Ret.PermsToken, perms_key: (System.get_env("PERMS_KEY") || "") |> String.replace("\\n", "\n") ↓ config :ret, Ret.PermsToken, perms_key: "ここに perms.priv.pem.line の内容を貼り付けます" config :ret, Ret.JanusLoadStatus, default_janus_host: dev_janus_host, janus_port: 443 ↓ config :ret, Ret.JanusLoadStatus, default_janus_host: dev_janus_host, janus_port: 4443
ここで一度 dev モードの Reticulum を起動します。
cd ~/mozilla/reticulum iex -S mix phx.server
https://hubs.local:4000/health にアクセスして ok と表示されているか確認します。
次に Reticulum のサーバーで skipadmin オプション付きでトップページが表示されるのを確認します https://hubs.local:4000/?skipadmin
さらにトップページの Sign In/Sign up ボタンを押すとメールアドレスを入れるダイアログが出ます。今回の設定ではまだメール機能は使えてませんので、適当なアドレスを入力します。(例)nobuh@hubs.local
Next を押しますが、メールは届きません。代わりに Reticulum を起動したコンソールで、リンクを送信した旨のログ(黄色の線)を見つけます。
同じブラウザでリンクを貼り付けて実行すると Verification Complete の表示が出て、右上の自分のアカウントでログイン済みの表示になります。
次にシーンエディタ Spoke のページ https://hubs.local:4000/spoke を開いて、右上が Logout のメニューになっていれば OK です。
ログイン状態が確認できましたら、今ログインしたユーザーに管理権限をつけます。Reticulum の iex プロンプトで1行コマンド
Ret.Account |> Ret.Repo.all() |> Enum.at(0) |> Ecto.Changeset.change(is_admin: true) |> Ret.Repo.update!()
を実行します
Coturn と Dialog のセットアップ
Reticulum のユーザー管理が無事動いてることが確認出来ましたら、次に音声サーバーのセットアップを行います。
まずは UDP の通信で必要になる STUN/TURN サーバーの coturn をインストールします。
sudo apt install coturn
/etc/turnserver.conf の psql-userdb の行のコメントを外し以下に変更します。
#psql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> connect_timeout=30" ↓ psql-userdb="host=127.0.0.1 dbname=ret_dev user=postgres password=postgres options='-c search_path=coturn' connect_timeout=30"
設定を反映するため再起動します。
sudo systemctl restart coturn
最後に WebRTC Mediasoup の Dialog サーバーをインストールします。
cd ~/mozilla git clone https://github.com/mozilla/dialog.git cd dialog git reset --hard 4edefad npm install
certs ディレクトリを作成し、証明書をファイル名 fullchain.pem, privkey.pem で配置します。また、reticulum で作成した通信用公開鍵もここに配置します。
mkdir certs && cd certs ln -s ~/certs/server.crt fullchain.pem ln -s ~/certs/server.key privkey.pem ln -s ~/mozilla/reticulum/priv/perms.pub.pem . cd ..
自分のサーバーの IP (例 192.168.0.7)を指定して起動します。
MEDIASOUP_LISTEN_IP=0.0.0.0 MEDIASOUP_ANNOUNCED_IP=192.168.0.7 npm start
トップ画面 https://hubs.local:4000/ から「部屋を作る」で前回の記事と同様な真っ暗な部屋に入れれば音声サーバー設定は無事完了です。
自己署名証明書を使っている際によく発生すること
事前に以下の 4 URL を踏んで証明書の例外承認をしたブラウザから最後に Reticulum にアクセスする必要がありますが、つい忘れがちですのでまとめて再掲いたします。
- Hubs https://hubs.local:8080/
- Admin https://hubs.local:8989/
- Spoke https://hubs.local:9090/
- Dialog https://hubs.local:4443/
- 最後に Reticulum https://hubs.local:4000/
オリジナルなシーン作成
長い準備でしたがサーバーがようやく完成しました。ここからが本記事の本題です!
https://hubs.local:4000/spoke にアクセスし New Project ボタンを押します。
自作の Reticulum サーバーにはプロジェクトが何もありませんので流用できるプロジェクトが何もありません。New Empty Project を押します。
Blender のようなモデルツールの画面になりますが、早速エラーが表示されます。
これはデフォルトで用意しようとするアセット、黄色で囲んだ Terrain_Crater1.glb が自分のサーバーには無いためエラーになったものです。無くて正しいので ok を押してダイアログを消したあと、Terrain_Crater1.glb を選択して削除しておきます。
Elemets メニューにあるオブジェクトはサーバーが空の状態でも使えますので、Ground Plane と Water その他を置いてみました。この状態で右上の Publish Scene を押します。(Ground Plane などの静的物体となるオブジェクトが1個もないと publish 時に collection is undefined エラー表示で失敗しますので何か一つは物体を足してください)
一度も save していないとまず save するよう促されますので save します。
次に Publish の条件を聞かれます。
- Allow Remix と
- Allow Promotion
の2つを聞かれますのでどちらもチェックを付けます。
進めると、パフォーマンスの確認画面になります。重すぎるモデルなどはここで気がつけます。
publish が完了すると open scene のボタンが現れます。この open scene を押すと作成したシーンを使って新しい部屋を生成することが出来ます。
部屋に招待する
- 部屋にいるときの URL (例 https://hubs.local:4000/BAGfh7d/lustrous-capital-tract )
- またはハッシュ値までの短いリンク (例 https://hubs.local:4000/BAGfh7d)
を招待リンクとして使えます。(自分と他2名入った様子)
本家 hubs.mozilla.com のモデルの Remix
一から全部モデリングしてルームを作るのは大変ですので、本家 hubs.mozilla.com で公開されているフリーなルームを活用してみます。
https://hubs.mozilla.com/spoke にアクセスし、ユーザー登録をしてください。
Project メニューに利用可能なシーンが沢山ありますので、そのうちの一つ Art Gallery を開いてみます。
File メニューに Export as binary glTF がありますのでエクスポートを実行します。必須ではないですが、メッシュの結合などは利用した方がよいと思います。
ダウンロードすれば本家のサイトでの作業は完了です。
次に https://hubs.local:4000/spoke で自分のサーバーにアクセスします。メニューに Logout が表示された ログイン済み状態であることを忘れず確認してください。
自作シーンのときと同じく New Empty Project を作成し、エラーになっている glb を削除します。Asset メニューの My Assets を選ぶと Upload ボタンがありますので、ダウンロードしておいた glb ファイルをアップロードします。
アップロードすると My Assets の1個のオブジェクトとして登録されるので、選択して自分のシーンに配置します。(このモデルはドアが無い閉じた箱状の空間になっていますので、人が入ってくる Spawn Point が箱の中になるように配置の際は気を付けてください。)
あとは Publish して Open Scene すれば使えます!
以上長文になりましたが、自分の PC 上の VirtualBox のサーバーで Mozilla Hubs のルーム作成機能を使うことが出来ました!!
独自ドメインでの運用や、自作アバターの使用、本物のメールでのユーザー登録など、Mozilla Hubs のホスティングではまだまだ解決すべきところも多々ありますので今後も研究を続けていきたいと思います!
弊社ではメタバースに興味のある xR エンジニアやプログラマ、インフラエンジニアなどを積極募集しておりますので、ご興味ある方はぜひご応募くださいー ⇒ 採用情報