0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Terraform(OpenTofu)でPalworldの専用サーバーをAWS上に構築した

0
Posted at

タイトルの通りです。

フレンドとPalworldをやろう!ということになり、せっかくなのでAWSに専用サーバーを建てよう、せっかくなのでIaCでスマートに作ろう、という流れでこうなりました。

公式DockerイメージをEC2の上で動かします。遊ぶときだけサーバーを起動し、遊ばない期間はEC2インスタンスを撤去しつつ、セーブデータやパスワード、バックアップは安全に残せる構成をOpenTofuで作りました。

コードと詳しい作業手順は GitHubリポジトリ にまとめています。

作った理由

Palworldを遊ぶ期間は専用サーバーが欲しいものの、常にEC2インスタンスを起動しておくとお金がもったいないです。一方で、遊ばない期間にサーバーを撤去するたび、セーブデータの退避や環境の再構築を手作業で行うのは面倒です。

そこで、次のような運用を目指しました。

  • 遊ぶときはOpenTofuでサーバーを構築する
  • 遊ばない期間はEC2インスタンスを撤去する
  • EC2インスタンスを撤去してもセーブデータは残す
  • セーブデータをS3へバックアップする
  • バックアップをローカルへ持ち出したり、サーバーへ戻したりできるようにする

AWS構成

全体の構成は次のとおりです。

ゲームサーバーにはAmazon Linux 2023のEC2インスタンスを使用し、Palworld公式のDockerイメージを起動します。

EC2インスタンスのルートEBSにはOSやDockerなどを置き、セーブデータを含む Saved ディレクトリ全体は独立したEBSへ保存します。EC2インスタンスを再作成しても、このセーブ用EBSを新しいインスタンスへ接続することで続きを遊べます。

さらに、セーブデータは手動でS3へバックアップできます。EC2インスタンスとEBSを分けるだけでは、EBS自体の障害や誤操作には備えられないためです。

管理接続にはAWS Systems Manager Session Managerを使い、SSHポートは開放していません。ゲーム用のUDPポートも、設定したIPv4 CIDRからの通信だけをSecurity Groupで許可します。

OpenTofuでサーバーを起動・撤去する

サーバーを起動するかどうかは、変数 server_enabled で切り替えます。

server_enabled = true

この状態でplanとapplyを実行すると、EC2インスタンスとElastic IPが作成されます。

tofu plan -out palworld.tfplan
tofu apply palworld.tfplan

遊ばない期間は server_enabledfalse に戻してapplyします。

server_enabled = false

これによりEC2インスタンスとElastic IPは削除されますが、セーブ用EBS、S3バックアップ、Secrets Managerは残ります。再び true にしてapplyすれば、新しいEC2インスタンスへ既存のセーブ用EBSが接続されます。

なお、Elastic IPはサーバーの再構築時に作り直すため、接続先のIPアドレスは変わる可能性があります。

初回構築だけは二段階

パスワードはOpenTofuの管理対象にしていないため、初回構築は二段階に分けています。

最初は server_enabled = false の状態でapplyし、Secrets Manager、セーブ用EBS、S3バケットなど、サーバーを撤去しても残すリソースを先に作成します。その後、付属のPowerShellスクリプトから参加用パスワードと管理用パスワードをSecrets Managerへ登録します。

./scripts/Set-PalworldCredentials.ps1

パスワードを登録してから server_enabled = true に変更し、もう一度applyしてEC2インスタンスを作成します。

データとパスワードを安全に残す

セーブ用EBSとS3バケットには prevent_destroy を設定しています。そのため、通常の tofu destroy では保護対象のリソースを削除できません。完全に削除するときは、バックアップをローカルへエクスポートしたうえで、明示的に保護を外す必要があります。

パスワードについては、OpenTofuはSecrets Managerの入れ物と、EC2インスタンスから読み取るための権限だけを管理します。パスワードそのものはOpenTofuの設定、plan、state、EC2のuser dataへ保存しません。

EC2インスタンスはPalworldの起動時にSecrets Managerから現在のパスワードを取得します。パスワードを変更するときも、OpenTofuでEC2インスタンスを再作成する必要はありません。

実際の運用

サーバーの初回起動時には、cloud-initがDockerのインストールや公式イメージの取得、systemdユニットの作成を行います。

ここで注意が必要なのは、tofu apply の完了がPalworldの起動完了を意味するわけではないことです。apply後もEC2インスタンス内では初期化が続くため、Session Managerで接続してcloud-initの完了を待ちます。

aws ssm start-session --target "$(tofu output -raw instance_id)"
sudo cloud-init status --wait
sudo systemctl status palworld
sudo docker logs --tail 100 palworld-server

接続先はOpenTofuのoutputから取得できます。

tofu output server_address

バックアップ

手動バックアップ用のスクリプトをEC2インスタンス内へ用意しています。

sudo /usr/local/sbin/backup-palworld

バックアップ中はゲームサーバーを一時停止し、Saved ディレクトリ全体を圧縮してS3へ送信したあと、サーバーを再開します。バックアップはAWS CLIでローカルへダウンロードできます。

ローカルに保存したバックアップは、付属のPowerShellスクリプトでS3へアップロードし、EC2インスタンス上へ復元できます。

./scripts/Restore-PalworldBackup.ps1 './palworld-saved-<timestamp>.tar.gz'

復元前のセーブデータもS3へ退避し、展開やPalworldの再起動に失敗した場合は元の状態へ戻すようにしています。

費用見積り

2026年7月26日時点の東京リージョンにおける概算です。Palworldがメモリ32 GiBを推奨しているため、EC2インスタンスは r7i.xlarge を選択しています。

EC2インスタンスを撤去している間も、セーブデータを保持するための費用は発生します。

項目 概算
セーブ用gp3 EBS 100 GiB 9.60 USD/月
Secrets Manager 1件 0.40 USD/月+API呼び出し料
S3 Standard バックアップの保存量に応じる
合計 約10.00 USD/月+S3など

サーバーを起動している間は、次の費用が加わります。

項目 概算
EC2 r7i.xlarge 0.3192 USD/時間
ルートgp3 EBS 50 GiB 約0.0066 USD/時間
パブリックIPv4アドレス 0.0050 USD/時間
合計 約0.3308 USD/時間

したがって、S3や通信などを除いた月額概算は「約10.00 USD+0.3308 USD×サーバー稼働時間」です。1 USDを160円と仮定すると、固定費は約1,600円/月、起動中の追加費用は約53円/時間になります。

実際の請求額は、利用時間、バックアップ容量、データ転送量、為替、税、AWSの料金改定などによって変わります。最新の料金は以下のページをご確認ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?