TrueNAS+DockerでRUSTのゲームサーバを構築した


# はじめに

Qiita初投稿です。

友人とサバイバルゲーム「RUST」にハマったので、自宅にコンテナ環境を用意してゲームサーバを稼働させることにしました。
なるべく再現性が高くなるように構築の流れを想定して執筆します。

ConoHa VPSやさくらのVPSといったレンタルサーバでも良かったのですが、サーバ管理やネットワーク周辺のお勉強も兼ねているので妥協せずにチャレンジしてみようと思います。
「ネットワーク勉強を始めました」「ゲームサーバに興味があり、調べています」等、ネットワークやコンテナを勉強したての方で、どなたかの琴線に触れられたらと思います。

# 目次

ボリュームある内容なので、目次を設けました。
正直、投稿を二回に分けても良かったと思いました。

- [ネットワーク図](#ネットワーク図)
- [NASのスペック](#nasのスペック)
- [ハードウェア要件と仮想マシンのスペック選定](#ハードウェア要件と仮想マシンのスペック選定)
- [コンテナ環境の整備](#コンテナ環境の整備)
- [コンテナネットワークの整備](#コンテナネットワークの整備)
    - [ユーザー定義ブリッジネットワークに利用するブリッジの準備](#ユーザー定義ブリッジネットワークに利用するブリッジの準備)
    - [ブリッジの作成](#ブリッジの作成)
    - [ブリッジを利用したユーザー定義ブリッジネットワークの作成](#ブリッジを利用したユーザー定義ブリッジネットワークの作成)
- [Rocky Linux 8の導入](#rocky-linux-8の導入)
- [ネットワークの整備](#ネットワークの整備)
    - [iptablesの設定](#iptablesの設定)
    - [ルーターのポートフォワーディング](#ルーターのポートフォワーディング)
- [ゲームサーバの構築](#ゲームサーバの構築)
    - [ゲーム構築ツールによるゲームサーバの作成](#ゲーム構築ツールによるゲームサーバの作成)
    - [ゲームサーバのパラメタ設定](#ゲームサーバのパラメタ設定)
    - [WAN側からゲームサーバへの接続確認](#wan側からゲームサーバへの接続確認)
- [おまけ](#おまけ)
- [まとめ](#まとめ)

# ネットワーク図

こんな感じのLAN構成を考えました。実際のIPアドレスは異なりますが、イメージしやすいように仮でつけております。

![network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703712/091c7c95-4859-360c-982a-b885d5cb6f37.png)

# NASのスペック

今回、ネットワークアタッチドストレージ（NAS）をサーバ用途に利用するため、メモリとCPUをアップグレートしました（元々メモリは16 GB、CPUはXeon E5-2620 v3）。換装したNASのスペックです。

OS: TrueNAS CORE 12.0
CPU: Intel Xeon CPU E5-2683 v3（14C/28T@2GHz）
MEM: 80 GB（8 GB x2, 32 GB x2）
SSD: 500 GB（ブート用）
HDD: 4 TB（データ用、RAID1）

# ハードウェア要件と仮想マシンのスペック選定

NASに導入しているNAS用OS「TrueNAS」ではコンテナ環境を用意するサービスが提供されていないので、仮想マシンのホストOSを用意してコンテナ環境を準備します。仮想マシンのスペック選定は、RUSTの要件をもとに選定します。

https://www.servermania.com/kb/articles/what-are-the-rust-dedicated-server-requirements/

```txt
RAM: Minimum RAM requirements is 4GB of RAM, but 8GB+ is recommended for optimal performance.
Operating System: Windows 7, 8.1, or 10 or Linux: Ubuntu, Debian, Fedora, or CentOS
Processor: Dual-core 3.4GHz or greater
Disk Space: 32GB+
Connection: Minimum 100Mbps+ Recommended 1Gbps
```

以下に選定した仮想マシンのスペックと、コンテナ～ゲームサーバを整備するツールについてまとめます。

- 仮想マシンのスペック
    - CPU: 4コア（vCPUs x1, Cores x4, Threads x1）
    - MEM: 10 GiB
    - HDD: 100 GiB
- 仮想マシンのホストOS
    - Ubuntu 22.04 LTS
- コンテナ管理ツール
    - Docker、Docker Compose
- ファイアウォール機能
    - iptables
- コンテナのOS
    - Rocky Linux 8（<https://rockylinux.org/ja/>）
- ゲームサーバ構築ツール
    - LinuxGSM（<https://docs.linuxgsm.com/>）

後からサーバ設定やゲームデータの管理が容易である側面から、既にコンテナ化されたゲームサーバのデプロイではなく別途OSを用意して一から構築することにします。ゲームサーバ構築ツールはLinuxGSMを利用します。LinuxGSMで推奨されているOSは、執筆している2022年10月時点で以下の通りです。

- Ubuntu 18.04 LTS is recommended
- Debian 10 "Buster" is recommended
- CentOS 8 is recommended

OSにRocky Linuxを選んだ理由として、CentOSがRHELと互換性があり、Rocky LinuxはRHELと100%互換性を持つように設計されているためです。ちなみに、2020年11月30日でサポート終了となったCentOS 6はLinuxGSMではサポートされないそうです（CentOS 6 is not supported by LinuxGSM）。

# コンテナ環境の整備

SSHでUbuntuに接続後、パッケージのアップデートを行います。パッケージ管理はapt-getは使用せず、aptで管理します。

```txt
$ sudo apt update && sudo apt upgrade -y
```

OSをインストールして直ぐはコンテナ環境が無いので、Dockerをインストールしてコンテナ環境を準備します。Documentにコードが載っているので、apt-getをaptに読み替えて実行します。

https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

Dockerのリポジトリをセットアップする

```txt
$ sudo apt install ca-certificates curl gnupg lsb-release -y
$ sudo mkdir -p /etc/apt/keyrings && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
Docker Engineをインストールする

```txt
$ sudo apt update
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
```
インストール後、Docker、Docker Composeバージョンの確認する

```txt
$ docker -v
Docker version 20.10.21, build baeda1f
$ docker compose version
Docker Compose version v2.12.2
```
Dockerは常にrootユーザーでの実行となるので、都度都度sudoを付けるのは面倒です。現ユーザーをdockerのグループに所属させることで回避します。

```mtxt
$ sudo gpasswd -a $USER docker
$ sudo systemctl restart docker && exit
```
再度SSHでログイン後、sudoが不要になっていることを確認する。

```txt
$ docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

# コンテナネットワークの整備

## ユーザー定義ブリッジネットワークに利用するブリッジの準備

コンテナを複数立ち上げる将来を見据えて、コンテナ外のネットワークから疎通が容易になる環境を構築します。ローカルネットワークからコンテナ内に接続できるように、ホストOSと同じネットワークに接続できるネットワークブリッジを作成して、ブリッジをコンテナに割り当てます。

コンテナ環境を導入してすぐのネットワークインターフェースの状態では、loとenp0s4の他にdocker0が追加されています。

```txt
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp0s4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:a0:98:39:f2:8d brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.90/24 brd 192.168.1.255 scope global noprefixroute enp0s4
       valid_lft forever preferred_lft forever
    inet6 240b:11:88e1:b800:add1:ab9d:30b:7b45/64 scope global temporary dynamic
       valid_lft 595283sec preferred_lft 76587sec
    inet6 240b:11:88e1:b800:5d46:a831:bc5a:becf/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591758sec preferred_lft 604558sec
    inet6 fe80::9923:a7ac:6ba:5bc7/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:c7:1d:ca:62 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
```

ここで、Ubuntu 18.04以降、`/etc/network/interfaces`という設定ファイルは廃止されています。Ubuntu 22.04でネットワークを触る場合、`/etc/netplan/`配下のyamlファイルでネットワークインターフェースを構築・管理します。

Ubuntu 22.04を採用しているので`/etc/netplan/*`でブリッジを作成します。`/etc/netplan/`には以下のファイルが存在しています。

```txt
$ ls /etc/netplan/*.yaml
/etc/netplan/01-network-manager-all.yaml
```

`netplan`のDocumentからyamlの扱いについて、重要な部分だけ抜粋すると、「OS起動時に`/{lib,etc,run}/netplan/*.yaml`のyaml全てがnetwork daemon渡され、辞書的にyamlを読み込み、前に読み込まれたyamlの設定を上書きする」との旨の記述がありました。


https://netplan.io/reference

```txt
Introduction
…
（中略）
…
During early boot, the netplan "network renderer" runs which reads /{lib,etc,run}/netplan/*.yaml and writes configuration to /run to hand off control of devices to the specified networking daemon.
…
…
General structure
…
（中略）
…
Lexicographically later files (regardless of in which directory they are) amend (new mapping keys) or override (same mapping keys) previous ones.
```

つまりは「`netplan`では接頭辞に大きな数字を持つ`/etc/netplan/99-*****.yaml`が優先される」ようです。
Documentを参考に、ブリッジbr0を構成するyamlを作成します。

https://netplan.io/examples/

```md:/etc/netplan/99-custom-network.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s4:
      dhcp4: no
  bridges:
    br0:
      dhcp4: false
      addresses: [192.168.1.90/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [192.168.1.1]
      interfaces:
        - enp0s4
```

## ブリッジの作成


`/etc/netplan/`にユーザー定義のyamlが作成されていることを確認します。

```txt
$ ls /etc/netplan/*.yaml
/etc/netplan/01-network-manager-all.yaml
/etc/netplan/99-custom-network.yaml
```

ネットワークの設定に適用します。

```txt
$ sudo netplan apply
```

適用後、ネットワークインタフェースにブリッジbr0が追加されています。

```txt
$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp0s4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel master br0 state UP group default qlen 1000
    link/ether 00:a0:98:39:f2:8d brd ff:ff:ff:ff:ff:ff
    inet6 fe80::adc5:ff2e:b64d:c6d2/64 scope link tentative noprefixroute
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
    link/ether 02:42:c7:1d:ca:62 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 62:12:d9:e9:5e:4c brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.90/24 brd 192.168.1.255 scope global br0
       valid_lft forever preferred_lft forever
    inet6 240b:11:88e1:b800:6012:d9ff:fee9:5e4c/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 2591997sec preferred_lft 604797sec
    inet6 fe80::6012:d9ff:fee9:5e4c/64 scope link
       valid_lft forever preferred_lft forever
```
## ブリッジを利用したユーザー定義ブリッジネットワークの作成

ブリッジネットワークを作成する前に、現在の状態を確認する。

```txt
$ docker network ls
NETWORK ID     NAME             DRIVER    SCOPE
be764a1f4cbe   bridge           bridge    local
ab3c107e73fe   host             host      local
7bbab5581bb8   none             null      local
```



Docker v20.10のDocumentを参考に、ブリッジネットワークを作成する。`--gateway, --ip-range, --aux-address`等のオプションはご自身のネットワーク環境に合わせてください。

https://docs.docker.jp/engine/reference/commandline/network_create.html

```txt
$ docker network create \
  --driver=bridge \
  --subnet 192.168.1.0/24 \
  --gateway 192.168.1.90 \
  --opt "com.docker.network.bridge.name"="br0" \
  docker-network
```

ブリッジネットワークdocker-networkが構築されており、コンテナ向けに用意されているbridgeが二つ存在する。

```
$ docker network ls
NETWORK ID     NAME             DRIVER    SCOPE
be764a1f4cbe   bridge           bridge    local
e340255eeea6   docker-network   bridge    local
ab3c107e73fe   host             host      local
7bbab5581bb8   none             null      local
```

# Rocky Linux 8の導入

Rocky Linuxの公式Documentを参考にDockerfileを作成します。

https://hub.docker.com/r/rockylinux/rockylinux



```txt: Dockerfile
FROM rockylinux/rockylinux:8.4
ENV container docker
RUN (cd /lib/systemd/system/sysinit.target.wants/; for i in *; do [ $i == \
systemd-tmpfiles-setup.service ] || rm -f $i; done); \
rm -f /lib/systemd/system/multi-user.target.wants/*;\
rm -f /etc/systemd/system/*.wants/*;\
rm -f /lib/systemd/system/local-fs.target.wants/*; \
rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
rm -f /lib/systemd/system/basic.target.wants/*;\
rm -f /lib/systemd/system/anaconda.target.wants/*;
VOLUME [ "/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
```
Dockerfileに加えて、docker-compose.ymlも準備します。RUSTでは28015番, 28016番, 28082番のポートを使うことが多いので、コンテナをデプロイする際に一緒に開放しておきます。コンテナのネットワークは、ブリッジネットワークdocker-networkを指定して、IPアドレスは`192.68.1.180/24`とします。

```txt: docker-compose.yml
version: "3.2"
services:
  app:
    build: ./
    container_name: rust
    ports:
      - "28015:28015"
      - "28016:28016/tcp"
      - "28082:28082/tcp"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /nfs/Medias/Projects/rust/rust_data:/data
    restart: always
    networks:
      docker-network:
        ipv4_address: 192.168.1.180
    mem_limit: 8g
    cpus: 3
networks:
    docker-network:
        external: true
```

Dockerfile、docker-compose.ymlのあるディレクトリでdocker composeコマンドを使ってコンテナを立ち上げます。

```txt
$ docker compose up -d
```

`docker scan`についてのメッセージが表示されますが、内容はbuildされたイメージの脆弱性を発見することができるという使い方の紹介のようです。

```txt
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
[+] Running 1/1
 ⠿ Container rust  Started                                                                                       12.1s
```

`docker ps`で稼働中のコンテナを表示させます。コンテナIDは`fbe944523562`のようなので、コンテナに入って作業する場合、このIDを指定してすれば良さそうです。

```txt
$ docker ps
CONTAINER ID   IMAGE           COMMAND            CREATED       STATUS           PORTS                                                                                                                  NAMES
fbe944523562   container-app   "/usr/sbin/init"   7 minutes ago   Up 6 minutes   0.0.0.0:28015-28016->28015-28016/tcp, :::28015-28016->28015-28016/tcp, 0.0.0.0:28082->28082/tcp, :::28082->28082/tcp   rust
```

# ネットワークの整備

## iptablesの設定

グローバルネットワークやロカールネットワークからコンテナの特定のポートに対して接続できるように、ポートフォワーディングを行います。RHEL7（CentOS 7）からファイアウォール機能はfirewalldを推奨していますが、今回は扱いやすさからiptablesをそのまま利用したいと思います。firewallへの移行は興味があるので、余力があれば行います。

iptablesのファイアウォールルールをどこか適当なディレクトリに保存します。せっかくなので、iptables関連のディレクトリを準備して配置します。

```txt
$ mkdir ~/iptables
$ sudo iptables-save > ~/iptables/iptables.org
```

iptablesはとてもセンシティブで、一歩間違えると不正アクセスや標的型攻撃等の踏み台にされる場合があります。セキュリティを踏まえたiptablesのシェルスクリプトは以下の記事を参考にしました。投稿日が2013年11月6日とかなり古いですが、iptablesの設定はそこまで変わらないと思います。セキュリティ要件はご自身の環境に合わせてください。


https://oxynotes.com/?p=6401

実際に使用したiptablesのファイルをそのまま載せる訳にもいかないので、記事と異なる点を載せます。
- Netfilterのルール管理にnetfilter-persistentを利用
    - 単純に使ってみよう、という考えで採用します。iptables-persistentをインストールすればモジュールのnetfilter-persistentも一緒に入ります。

```txt
$ sudo apt install -y iptables-persistent
```

- 必要なポートを開放し、コンテナやコンテナのホストOSでサービスを提供しない明らかに不要なポートの閉鎖
    - 必要なポート：RUSTに利用する
        - 28015/UDP, 28015-28016/TCP, 28082/TCP
    - 不要なポート：RUST以外のサービスは利用しない
        - 25/UDP, 25/TCP, 80/TCP, 443/TCP, 465/TCP, 587/TCP, 993/TCP, 995/TCP, 10022/UDP, 10022/TCP
- SSH向けのポートとIPソース変更
    - 22番ポートでの接続、サブネット`192.168.1.0/24`からの接続を許可する。
- 国別アクセス制御の削除
    - 元々外部へゲームサーバとして公開するので、気にしないです。
- ネットワークインターフェースの変更
    - 実際のネットワーク環境に合わせて変更してください。

後は、netfilter-persistentを使ってシェルスクリプトの最初と最後でゴニョゴニョします。

ポイントは、`/etc/init.d/netfilter-persistent flush`でiptablesの設定初期化と`systemctl restart docker.service`でdockerの再起動を明示することです。`/etc/init.d/netfilter-persistent stop`だと以前のiptablesの設定が残ったままルールを追加してしまう為、シェルスクリプトの使用回数を重ねるとフィルタが重複して管理しづらくなります（同じルールを追記しているので挙動には問題ありませんが）。また、iptablesを最初に初期化しており同時にチェインが初期化されているため、コンテナと通信ができなくなります。シェルスクリプトの最後で`systemctl restart docker.service`を実行してコンテナネットワークを再構築します。

```txt:~/iptables/iptables.sh
/etc/init.d/netfilter-persistent flush
...
（中略）
...
/etc/init.d/netfilter-persistent save
/etc/init.d/netfilter-persistent start

systemctl restart docker.service
```

間違えたルールを適用してしまった場合、iptablesの初期化（もしくはリストア）とコンテナネットワークの再構築で元の状態に戻し、正しいルールを適用します。

```txt
$ sudo /etc/init.d/netfilter-persistent flush
$ sudo systemctl restart docker.service
```
ちなみに、netfilter-persistentは以下のフォルダ配下のファイルに対してルールの保存＆読み出しをしています。

```txt
$ ls /etc/iptables/
rules.v4  rules.v6
```

参考にしたシェルスクリプトに加えるルールの設定は以下になります。

```txt
# Initialize iptables using netfilter-persistent
/etc/init.d/netfilter-persistent flush

# Use for RUST
iptables -A INPUT -p tcp -m state --state NEW --dport 28015 -j ACCEPT
iptables -A INPUT -p udp -m state --state NEW --dport 28015 -j ACCEPT
iptables -A INPUT -p tcp -m state --state NEW --dport 28016 -j ACCEPT # for RCON
iptables -A INPUT -p tcp -m state --state NEW --dport 28082 -j ACCEPT # for RUST+

# Use for SSH
iptables -A INPUT -s 192.168.1.0/24 -p tcp -m state --state NEW --dport 22 -j ACCEPT

# Start iptables with netfilter-persistent
/etc/init.d/netfilter-persistent save
/etc/init.d/netfilter-persistent start

# re-generate docker-chain
systemctl restart docker.service
```

作成したシェルスクリプトを実行します。


```txt
$ sudo sh iptables.sh
 * Flushing netfilter rules...
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables flush
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables flush
                                                                                   [ OK ]
 * Saving netfilter rules...
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
                                                                                   [ OK ]
Starting netfilter-persistent (via systemctl): netfilter-persistent.service.
```

二回目以降のシェルスクリプト実行も滞りなくiptablesが更新される。`/etc/init.d/netfilter-persistent flush`のコマンドで`iptables: Bad built-in chain name.`という警告が出るようになるが、出ている場合でもiptablesの設定は初期化されて続く処理が実行される。

```txt
$ sudo sh iptables.sh
 * Flushing netfilter rules...
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables flush
iptables: Bad built-in chain name.
iptables: Bad built-in chain name.
iptables: Bad built-in chain name.
iptables: Bad built-in chain name.
iptables: Bad built-in chain name.
iptables: Bad built-in chain name.
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables flush
                                                                                   [ OK ]
 * Saving netfilter rules...
run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save
run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save
                                                                                   [ OK ]
Starting netfilter-persistent (via systemctl): netfilter-persistent.service.
```


## ルーターのポートフォワーディング

RUSTで使用するポートは`28015/UDP, 28015-28016/TCP, 28082/TCP`になります。
外部から来た通信で以下の要件を満たすようにポートフォワーディングを設定します。

```txt
Protocol: <TCPもしくはUDP>
Source zone: WAN
External port: <上記のポート番号>
Destination zone: LAN
Internal IP Address: <Dockerをホストしている仮想マシンのIPアドレス>
Internal port: <上記のポート番号>
```

# ゲームサーバの構築

## ゲーム構築ツールによるゲームサーバの作成

`docker ps`で確認したRocky Linux 8のコンテナIDを使って、コンテナ内で作業します。まずはコンテナ内に入ります。

```txt
$ docker exec -it fbe944523562 /bin/bash
[root@fbe944523562 /]#
```

ゲームサーバを構築するツールが依存しているパッケージがあります。RHEL向けのLinux用の拡張パッケージ`EPEL`をインストールした上で、依存するパッケージをインストールします。ツールを使ってゲームサーバを構築しようとしてパッケージ不足でインストール処理が止まってしまう場合、不足しているパッケージが警告として表示されるので、ログに従ってインストールします。

https://linuxgsm.com/servers/rustserver/

```txt
# yum update
# yum install epel-release
# yum install curl wget tar bzip2 gzip unzip python3 binutils bc jq tmux glibc.i686 libstdc++ libstdc++.i686 zlib-devel
```

ゲーム構築ツールを導入する準備が整ったので、ツールをお迎えします。ツールはrootユーザによる実行はスクリプト処理を止める仕様なので、一般ユーザを作成して代わりに実行します。ユーザ名は何でも良いですが、ゲームに関連する名前を使うと管理しやすいです。

```txt
# adduser rustserver
# su - rustserver
$ wget -O linuxgsm.sh https://linuxgsm.sh && chmod +x linuxgsm.sh && bash linuxgsm.sh rustserver
$ ./rustserver install
```

後はツールが環境を準備してくれます。

## ゲームサーバのパラメタ設定

設定ファイルのテンプレートを`~/lgsm/config-lgsm/rustserver`にコピーして配置します。

```txt
cp ~/lgsm/config-default/config-lgsm/rustserver/_default.cfg ~/lgsm/config-lgsm/rustserver/rustserver.cfg
```

パラメタは任意の値に設定してください。特にRUSTサーバー管理ツールRCONのパスワードrconpasswordは推測されないように強力なパスワードを設定してください。

```txt:~/lgsm/config-lgsm/rustserver/rustserver.cfg
（前略）
## Predefined Parameters | https://docs.linuxgsm.com/configuration/start-parameters
ip="0.0.0.0"
port="28015"
rconport="28016"
appport=28082
rconpassword="<RCONのパスワード>"
rconweb="1" # Value is: 1 for the Facepunch web panel, Rustadmin desktop and Rustadmin Online; 0 for RCON tools like Rusty.
servername="<任意のサーバ名>"
gamemode="vanilla" # Values: vanilla, softcore ( Doc: https://wiki.facepunch.com/rust/server-gamemodes )
serverlevel="Procedural Map" # Values: Procedural Map, Barren, HapisIsland, SavasIsland
customlevelurl="" # Custom level url. +server.levelurl \"${customlevelurl}\"
seed="<任意のシード値>" # range: 1-2147483647, used to reproduce a procedural map.
salt="" # range: unknown, used to recover a known setting from an existing map.
maxplayers="20"
worldsize="3000" # default: 3000, range: 1000-6000, map size in meters.
saveinterval="300" # Auto-save in seconds.
tickrate="30" # default: 30, range: 15-100.
（後略）
```

パラメタの設定を終えたらゲームサーバを起動させます。

```txt
$ ./rustserver start
[  OK  ] Starting rustserver: <任意のサーバ名>
```

## WAN側からゲームサーバへの接続確認

一応、自宅に設置されているサーバなのでローカルIPアドレスを指定しても接続できるようになっているはず。
友人を招くためグローバルIPアドレスもしくはDDNSで取得したドメインを指定して接続を試みます。

ドメインの取得は以下あたりのDDNSが日本語対応していて扱いやすいです。
私は自宅はMyDNS、GCPはDDNS Nowからドメインを取得しています。

https://www.mydns.jp/


https://ddns.kuku.lu/index.php


RUSTのホーム画面でF1キーを押して、コンソールから以下のコマンドを入力してゲームが開始されれば成功です。
お疲れさまでした。

```txt
client.connect <グローバルIPアドレスもしくはドメイン>:28015
```

# おまけ

導入しているMOD一覧です。MODの機能はリンク先に説明があります。

https://umod.org/plugins/stack-size-controller

https://umod.org/plugins/gather-manager

https://umod.org/plugins/magic-loot

https://umod.org/plugins/npc-drop-gun

https://umod.org/plugins/custom-decay

https://umod.org/plugins/authentication


# まとめ

最後まで読んでいただきありがとうございました。

この記事は、仮想マシンの選定（もちろん物理マシンでもOKです）、コンテナやネットワーク環境の整備、ゲームサーバの構築まで一通り網羅しております。
記事を読みつつ、おそらくゲームサーバの構築ができるようになっていると思います。

正直、初投稿の内容がここまで長くなるとは思わず執筆しており、途中から飽きられているのではと考えることもありました。
私自身、自宅サーバに興味を持って勉強を始めた身なので、誰か一人でも、この記事を見てサーバに興味を持っていただけたら嬉しく思います。

そう高くはない頻度にはなりますが、少しずつアウトプットを増やしていこうと思います。
今後とも、どうぞよろしくお願いいたします。