暇殺シ

忙しくはない

ValheimのサーバーをVPSでたてる

目次

いま話題のValheimを24時間遊べるサーバーをたてて友達と一緒に楽しもうって主旨です。
store.steampowered.com

こんな人向け

  • サーバーを借りていつでも友達とValheimを遊べるようにしたい
  • 自宅サーバーは嫌
  • ラグが多いのは嫌(サーバーは国内に設置したい)
  • お金はあまりかけたくない(~1600円/月)
  • コマンドラインの操作ができる

サーバー(VPS)選び

サーバーに必要なスペックは高くない。現状は以下を満たせば十分。*1

私は自分でVPSを借りるのが今回初めてだが仮想サーバーで十分だろうということで適合するVPSサービスを比較サイトから選んだ。
採用したのはKagoyaのサービス。3コア/3GB/30GBの仮想サーバー(KVM)を選択した。(1540円/月)
本当はWeb Arena Indigoの2コア/4GB/80GB(1399円/月)を借りたかったけど空きが無いと断られてしまったので妥協した。
有名どころのAmazon Web Service EC2Google Compute EngineMicrosoft Azureさくらインターネットを選んでもよかったが無料で使えるサーバーではスペック不足だったりそれ以外だと比較的高価なので却下。GPortal等のゲーム専門のレンタルサーバーはサーバーの設定とかラクちんそうだが微妙に高かったりラグがひどいみたいな評判が目についたのでこちらも却下。ここは好みで。

サーバー(インスタンス)の作成・起動

ツールの準備

サーバーはリモートから操作するので最初にSSHクライアントを用意する。好きなものを使えばよい。
マニュアル - KAGOYA CLOUD VPS サポートサイト - SSH接続の設定
私はWindows Terminalを使っている。
Windows Terminalの設定は次の記事が参考になる。後で出てくる秘密鍵をあわせて設定しておけばサーバーへの接続が多少楽になる。
astherier.com

インスタンスの作成

※ここはKagoyaのVPSを借りる場合の手順になります。他サービスで借りた場合はそちらのマニュアル等を参照してください。
マニュアルに従ってやればよい。

  1. SSHアクセスするための鍵作成
    マニュアル - KAGOYA CLOUD VPS サポートサイト - ログイン用認証キー作成
  2. ファイアウォールの設定
    マニュアル - KAGOYA CLOUD VPS サポートサイト - セキュリティグループの設定
    開けるポートは次の通り。
    f:id:Idios:20210216115842p:plain
    セキュリティグループ設定例
    • TCP 22番 → SSHクライアント接続用
    • TCP/UDP 2456-2458番 → Valheimサーバーの接続用
  3. インスタンス作成
    マニュアル - KAGOYA CLOUD VPS サポートサイト - インスタンス作成(Linux OS)
    選択は基本デフォルトでOK。以下のものは設定する。
    • スペック → 3コア/3GB/30GB
    • パッケージ → Ubuntu 16.04 64bit
    • ログイン用認証キー → 鍵作成で作ったものを指定する。
    • セキュリティグループ → ファイアウォールの設定で作ったグループを指定する。

なお、KadoyaのVPSにはeth0にグローバルIPアドレスとプライベートIPアドレス(10.150.11.1)の二つが付与してある。この状態だとValheimサーバーがゲームクライアントに送るべきパケットをプライベートIPアドレスの方で送ることがありその場合はゲームに入れなくなる。これはtcpdumpで調べた。
このプライベートIPが邪魔だがこれはVPSに追加でアドレス設定する時に使うものとありそんなことする予定は無いのでここではアドレスを削除する。疎いので他にいい方法あれば教えて欲しい。

ip addr del 10.150.11.1 dev eth0

インスタンスの起動

インスタンスの作成時に勝手に起動すると思うが起動してなかったら手動で起動する。
マニュアル - KAGOYA CLOUD VPS サポートサイト - 起動

Valheimサーバーの設定

サーバーにSSHで繋いで設定操作をおこなう。
本稿ではValheimサーバーの設定・運用にはLinux Game Server Managers(LinuxGSM)を使うものとする。最初の設定が楽だし運用のための機能もついてるので。
linuxgsm.com

LinuxGSMのインストール

前提パッケージをインストールする。

sudo dpkg --add-architecture i386; sudo apt update; sudo apt install curl wget file tar bzip2 gzip unzip bsdmainutils python util-linux ca-certificates binutils bc jq tmux netcat lib32gcc1 lib32stdc++6 steamcmd

サーバーの状態確認に便利なのでGamedig(LinuxGSMの推奨ツール)も入れておく。

sudo apt remove --purge nodejs npm
sudo apt clean
sudo apt autoclean
sudo apt install -f
sudo apt autoremove
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt update && sudo apt install -y nodejs
npm install gamedig -g

Valheimサーバー用のユーザーを作る。

adduser vhserver
passwd vhserver
※好きなパスワードを設定する

自身をサーバー用ユーザーに変更する。

su - vhserver

LinuxGSMをダウンロードする。

wget -O linuxgsm.sh https://linuxgsm.sh && chmod +x linuxgsm.sh && bash linuxgsm.sh vhserver

LinuxGSMをインストールする。

./vhserver install

ゲームサーバーを起動してみる。

./vhserver start

無事起動したら設定を進めるためゲームサーバーを止める。

./vhserver stop

ゲームサーバーの設定

※サーバーにはSSHで繋ぎゲームサーバー用ユーザーとなって操作すること。
次のパスに設定ファイルがあるのでエディタ(vi/nano)で開く。

lgsm/config-lgsm/vhserver/vhserver.cfg

設定ファイルには次の内容を記載する。

servername="サーバー選択画面で表示するサーバーの名前"
# Minimum password length is 5.
serverpassword="サーバーに入るためのパスワード"
port="2456"
gameworld="ゲームワールドを生成するための文字列(半角英数字ならなんでもよいはず)"
public="1"

サーバーの起動・停止

※サーバーにはSSHで繋ぎゲームサーバー用ユーザーとなって操作すること。
起動は次のコマンドを実行する。

./vhserver start

停止は次のコマンドを実行する。

./vhserver stop

ゲームからサーバーに接続

次の手順でサーバーを探して接続する。お友達にはサーバー名とパスワードを教えておく。

  1. Valheimを起動
    f:id:Idios:20210216130911p:plain
    メニュー画面
  2. Start Game
  3. キャラクター未作成なら作る
    f:id:Idios:20210216131133p:plain
    キャラクター選択
  4. Start→Join Game
    f:id:Idios:20210216131356p:plain
    サーバー選択
  5. [Filter]欄にサーバー名を入れる
  6. サーバーを選択
  7. Connect
  8. パスワードを入力する
    f:id:Idios:20210216132003p:plain
    パスワード入力
  9. I HAVE ARRIVED!!
    f:id:Idios:20210216132138p:plain
    ログイン成功

もしもサーバーが見つからなかったり、パスワードが違ったら設定を見直してください。
steamアプリのお気に入りから入る手順が出回ってるけど自分の環境では結局↑の手順を踏まないとサーバーには入れなかった。

アップデートとバックアップ

※サーバーにはSSHで繋ぎゲームサーバー用ユーザーとなって操作すること。
ゲームにアップデートが入るとサーバーも更新するまで遊べなくなってしまうので1時間に一回アップデートをかける。また、障害やバグでデータ壊れた時に巻き戻せるように1日に一回バックアップをとるようにする。
処理はcronに対して次のように設定する。なお、更新が無い場合はアップデート処理が走ってもサーバーの再起動などは起きない。

crontab -e
↓エディタで以下を記入。
0 * * * * /home/vhserver/vhserver update > /dev/null 2>&1 # 毎時0分にアップデート
0 7 * * * /home/vhserver/vhserver backup > /dev/null 2>&1 # 毎日7:00にバックアップ

バックアップの個数や最大保持日数はLinuxGSMの設定で変更できる。デフォルトは4回×30日。

*1:今後のエンハンスでこのスペックでは足りなくなる可能がある。

*2:私はUbuntu 16.04 LTSを採用した。

スマートフォンを失った

ここ数年はiPhoneを使っている。
日曜日の朝、いつも通りそのiPhoneを手にとって一日を始めようかと思ったが電源がついていない。
電源ボタン押しても反応しない。

ご愁傷さまです。

近所のアップルストアで直してもらえないかなーと思ったけど予約できない。
なんだあれ、全然予約空いてないじゃん。
端末売りっぱなしで壊れても知らんってやる気ねーのかよって思いながら街の修理屋さんに持ち込む。
翌日受け取りに行ったら部品をいくつか交換して起動を試みたけど「リンゴループ」と呼ばれる現象が起きていてうちではお手上げですと無事死亡宣告。
ワンターレンかよ。ふざけんな。

そんなわけで今週から携帯電話を持ち歩かない生活を始めています。
twitterも二段階認証でSMS受け取れないとログインできないのでいまこうしてブログを書いて昔連携設定したツテでtwitterに投稿しようとしているんです。

そんなわけでわたしは元気です。
ほなまたね。

P.S. その1 今月末くらいに結婚する予定です。
P.S. その2 twitterとの連携設定が死んでいて投稿には失敗しました。

状態遷移の実装(Java編)

他の人が状態機械Javaでどうやって実装してるのかな~っと調べてみたら条件分岐の嵐だった。オブジェクト指向とはなんだったのか。
そこで私がいつも使っている方法を紹介します。ただ、あらゆるケースに使えるわけではありません。

  • Enum(Java5以降)が使えること。
  • マルチプロセス環境では使えない。

制約はこんなところです。

結論としては、状態をEnum値、状態遷移をメソッドで定義する。それだけです。
まずは簡単な例から。
f:id:Idios:20120707230317p:plain
これは初期状態と受容状態だけを定義した簡単な状態機械図です。
これをクラスに変換すると下記のようになります。状態はEnum値、状態遷移はメソッドで定義しています。

/**
 * Every values defines Machine state and transition.
 * 
 * @author Idios
 * 
 */
enum State {

	/**
	 * Initial state
	 */
	INITIAL {
		@Override
		public State accept() {
			return ACCEPTED;
		}
	},

	/**
	 * Accepted state
	 */
	ACCEPTED

	;

	/**
	 * To accept machine.
	 * 
	 * @return {@value #ACCEPTED}
	 */
	public State accept() {
		throw new IllegalStateException();
	}

}

public class Main {

	private State current = State.INITIAL;

	private void start() {
		current = current.accept();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Main machine = new Main();
		machine.start();
		System.out.println("State machine is " + machine.current);
	}

}

状態とその遷移の定義はStateクラス、状態遷移の管理はMainクラスで行う構造になっています。
遷移はINITIALからACCEPTEDのみ定義されているので、INITIALブロックにだけaccept()メソッドを宣言しています。もし、受容状態(ACCEPTED)の時にaccept()を呼び出すと、そんな遷移は定義していないので実行時例外になります。

状態の定義(RUNNING)を追加してみます。
f:id:Idios:20120707231643p:plain
これは初期状態からいきなり受容状態に遷移することがあれば、初期状態からRUNNING状態を経由して受容状態に遷移することもある状態機械を表しています。
そこで、初期状態からRUNNINGに至る遷移run()を定義しています。受容状態に至る遷移はaccept()のみのままです。

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Every values defines Machine state and transition.
 * 
 * @author Idios
 * 
 */
enum State {

	/**
	 * Initial state
	 */
	INITIAL {
		@Override
		public State run() {
			return RUNNING;
		}

		@Override
		public State accept() {
			return ACCEPTED;
		}
	},

	RUNNING {
		@Override
		public State accept() {
			return ACCEPTED;
		}
	},

	/**
	 * Accepted state
	 */
	ACCEPTED

	;

	/**
	 * To run the machine
	 * 
	 * @return
	 */
	public State run() {
		throw new IllegalStateException();
	}

	/**
	 * To accept the machine.
	 * 
	 * @return {@value #ACCEPTED}
	 */
	public State accept() {
		throw new IllegalStateException();
	}

}

public class Main {

	private State current = State.INITIAL;

	private void start() {
		current = current.accept();
	}

	private void start(final String string) {
		ExecutorService service = Executors.newFixedThreadPool(1);
		current = current.run();
		Thread runnable = new Thread() {
			@Override
			public void run() {
				// do something
			}
		};
		service.execute(runnable);
		try {
			runnable.join();
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} finally {
			service.shutdown();
			current = current.accept();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Main machine = new Main();
		if (args.length > 0) {
			machine.start(args[0]);
		} else {
			machine.start();
		}
		System.out.println("State machine is " + machine.current);
	}

}

このように、状態はEnum値、状態遷移はメソッドに定義することで割とシンプルに状態機械を実装できるのではないでしょうか。
また、定義されていない遷移が発生すると、ちゃんとチェックされるところが個人的なお気に入りポイントです。

状態遷移表を作ってあればソースコードの生成もできます。

なお、Java編以外の記載予定はありません。

Fedora17で最初はまったところ

ご無沙汰してます。
仕事を始めてから仕事・趣味にリソースを投入し、さらにTwitterばかりやってたもんで暇殺シはすっかり放置してました。最近は落ち着いてきたので暇殺シをHatena blogに移行した上でまたぼちぼちとやっていきたいと思います。

--本題--

しばらくFedora14で色々やっていたのですが隙を見て新規でFedora17に更新しました。
インストール対象と基本的な設定は以下の通り。

  • Lenovo T510
  • Fedora 17 64bit
  • Graphical Desktop Package Group
  • English(US)
  • Japanese Keyboard

インストールと起動自体はトラブル無く終了。Fedora16からGNOME3が採用され、GUIが大きく変わっていることは知っていたので驚きは少なかったです。ただし、やはり慣れないもので私がフリーズ。とりあえず画面上部をいじれば大抵のことができるのは分かりました。

その後、遭遇した問題は以下のようなもの

  • 日本語入力できない
  • キーボードからの入力内容が変
  • ネットワークの切り替えができない
  • 共有ファイルサーバの設定ができない

日本語入力ができない件はIMEを設定すれば解決します。私の場合、インストール時に言語設定をEnglis(US)にしたため、デフォルトではIMEが無効になっていたのだと思います。

以下はIME(Anthy)を有効にする手順

  1. デスクトップのActivitiesを選択
  2. 検索でInput methodを入力して候補に出てきたアプリ(正式名忘れた)を起動
  3. Fedora 17の日本語入力の設定を実施

このままだとIMEの起動はCtrl+Spaceとなります。上記のIBus設定時にKeyboard ShortcutHankaku-Zenkakuを指定&Applyすると半角/全角キーでIMEのon/offができるようになる。

 キーボードの入力内容がおかしい件はキーボードのレイアウトを設定することで解決。インストール時にJapaneseキーボードを設定した記憶があったがこれが上手く効いてなかったようだ。

システム設定からキーボードのレイアウトを変更できる。レイアウトは人によって異なるので色々お試しを

  1. 右上のユーザ名からSystem settings(名前曖昧…)を選択
  2. Keyboardを選択
  3. OptionからキーボードレイアウトをJapanese(Kana)に変更

新しいFedoraではネットワーク接続時に表示される右上のアイコンのクリックメニューから有線無線の切り替えができる。しかし、私は有線=>有線の切り替えがしたい。例えば固定IPからDHCPによる動的IP割り当てに変更するとか。

Fedora14の時はネットワーク設定を複数登録・選択できたので有線=>有線の切り替えは簡単だった。Fedora17では別のネットワーク設定アプリを使って複数の設定を登録してやればよい。そうするとアイコンのクリックメニューから切り替えができるようになる。ただ、この具体的な方法は忘れました。Activitiesからネットワークの設定アプリを試してたらFedora14と同じ画面になって、そこでうまく設定できたのは覚えているのですが

最後は共有ファイルサーバの利用について。普通はNautilusのFileメニューから共有を追加していけばよいはずです。私の環境ではフリーズしたり入力内容見なおせと言われてうまくいかない。

これはもうfstabに直設定で解決しました。そしたらNautilusはさも自力でマウントしたかのようにランチャにマウントポイントを表示してくるのが何か腹立たしい。

文字ばかりとなったけど、以上