いさぽん部屋(isapon.com)

ゲーム系プログラマによる特に方針のないブログ。技術系とカレー、ラーメンネタ多めだったはずが、最近はダイエットネタ多め。

headless & x11vncを自動起動にしてリモートPCにする

先日、プログラムのテストを行うための環境をEXSi上の仮想マシンに構築しました。どちらもGPUを使ったプログラムのテストをしたかったのでVNCで接続したいなー。でも毎回自分でVCNServerを起動するのは面倒だなーと思ったので、ヘッドレス化(モニタやきーぼどマウス無しで使うこと)してVNCServerを自動的に起動するようにしました。


セキュリティ的にはちょっと問題もあるのですが、閉じられた環境かつ使い捨ての環境なのでそこまで気にしなくてもよいので今回はとにかくお手軽に使えることを優先です。

headless化のための xorg.conf

まずはheadlessでXが起動できるように設定します。
ポイントはheadlessだと接続されているモニタが見つからないため、Xの初期化に失敗してしまうため「仮想スクリーンを使う」ということを指定してあげることです。

FreeBSDなら /usr/local/etx/X11/xorg.conf.d 、Linux なら /etc/X11/xorg.conf.d に自分が管理しやすい名前でファイルを作成し、以下の内容を記載してください。なお、ファイルの拡張子は .conf である必要があります(例 headless.conf など)。

# GPUを設定する。ここはPCによって異なるので注意
Section "Device"
        Identifier      "X11VncGgraphics0"
        # GPUの種類。nvidia, intel, amdgpu, radeon, modesetting などなど
        Driver          "nvidia"
        # GPUが接続されているPCIバス。
        # FreeBSDは pciconf -lv 
        # Linuxは lspci
        # で探すことができます。
        BusID           "PCI:3:0:0"        # search from pciconf(FreeBSD), lspci(Ubuntu)
EndSection

# ダミー用のモニタを定義する
Section "Monitor"
        Identifier "DummyMonitor0"
EndSection

# 使用するGPUとモニタを関連付けする
Section "Screen"
        Identifier      "Screen0"
        DefaultDepth    24
        Device          "X11VncGgraphics0"
        Monitor         "DummyMonitor0"
        SubSection      "Display"
                Depth           24
                # 仮想スクリーンサイズ。お好きな大きさに。
                Virtual         1280 720
        EndSubSection
EndSection

Section "Device" のGPU設定ですが、GPUの環境やドライバによっては Driver や BusID の項目はなくても大丈夫な時もありますし、使用している環境によって異なるので気を付けてください。FreeBSDなら pciconf -lv 、Linuxなら lspci で調べることができます。
また Identifier につける名前は管理しやすい名前で自由につけて構いません("Screen0" だけは固定のままにしておいたほうが良いです)。

これでモニタを接続しなくてもXが起動するようになります。

あとはlightdmなどのグラフィカルログインマネージャをインストールして自動起動するようにしておけばPC起動時に自動的にheadlessでXが起動するようになります。

x11vncを自動起動する

lightdmをインストールしているならlightdmのVNCServerの機能を使っても良いのですが、ここはx11vncを使ってVNCServerを起動してみます。違いについては下記のマトリックスを参考。

機能 切断時 メリット
lightdm vncserver連動 ログアウト 毎回ユーザーIDとパスワードを求められるので安全
x11vnc server自動起動 何もしない VNCを閉じても作業が中断されない

FreeBSD

Install

portsからインストールしても良いのですが時間短縮のためバイナリインストール。rootで作業します。

pkg install x11vnc

Startup script

次にスタートアップスクリプトを書きます。/usr/local/etc/rc.d/x11vnc というファイルを作成し、下記の内容を書いてください。また、chmod +x で実行権限も付け加えておくように。

#!/bin/sh

# $ FreeBSD $ 2019/12/30 Isaponsoft(Isao Shibuya)
#
# PROVIDE: x11vnc
# REQUIRE: LOGIN cleanvar moused syscons dbus lightdm
# KEYWORD: shutdown
#
. /etc/rc.subr

export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin
name="x11vnc"
rcvar=x11vnc_enable

load_rc_config $name
: ${x11vnc_enable:="NO"}
: ${x11vnc_logfile="/dev/null"}
: ${x11vnc_port="5900"}
: ${x11vnc_display=":0"}
: ${x11vnc_authfile="/usr/local/etc/x11vnc.passwd"}

command="/usr/local/bin/${name}"
command_args="-auth guess -display ${x11vnc_display} -rfbport ${x11vnc_port} -forever -loop -noxdamage -repeat -rfbauth ${x11vnc_authfile} > ${x11vnc_logfile} 2>&1 &"

run_rc_command "$1"

ちょっとしたポイントなのですが、6行目が以下のようになっていますが、最後に書いてある lightdm がポイントです。この行は「このサービスを開始するにあたりどのサービスに依存しているのか」というのを指定している行です。つまり、ここに lightdm が必要であることを書き加えると、lightdm が存在する場合は lightdm より後に起動するようにスケジューリングしてくれます。

REQUIRE: LOGIN cleanvar moused syscons dbus lightdm

Service の登録と開始

あとはVNCのパスワードを設定し、先ほどのスクリプトを起動するように指定します。/etc/rc.conf に x11_enable="YES" と書き加えれば良いのですが、serviceコマンドをを使うとこのあたりを簡単に行うことができます。

x11vnc -storepasswd /usr/local/etc/x11vnc.passwd
service x11vnc enable
service x11vnc start

Service の設定

さきに作ったStartupスクリプトはrc.conf(もちろんrc.conf.localもOK)に次のような設定を書くことでポート番号やログファイル、パスワードファイルを変更できます。

x11vnc_logfile="/mylogs/x11vnc.log"
x11vnc_port="5999"
x11vnc_display=":1"
x11vnc_authfile="/root/.vnc/passwd"

Ubuntu

Install

まずはインストール。

sudo apt install x11vnc

Startup script

StartupScript を /etc/systemd/system/x11vnc.service に追加します。ファイルを作成し、以下の内容を記載してください。7行のパスワードファイルの部分は自分で作成したパスワードファイルのパスを書いてください。

[Unit]
Description=x11vnc (Remote access)
After=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/x11vnc -auth guess -display :0 -rfbauth VNCパスワードファイル -rfbport 5900 -forever -loop -noxdamage -repeat -shared
ExecStop=/bin/kill -TERM $MAINPID
ExecReload=/bin/kill -HUP $MAINPID
KillMode=control-group
Restart=on-failure

[Install]
WantedBy=graphical.target

Service の登録と開始

パスワードファイルを作成し、x11vncをサービスとして登録&起動します。

sudo x11vnc -storepasswd VNCパスワードファイル
sudo systemctl daemon-reload
sudo systemctl enable x11vnc
sudo systemctl start x11vnc

ある意味究極のヘッドレス化

今回はあくまでも仮想スクリーンを使いましたが、下記のような仮想ディスプレイというハードウェアを使うのもありです。