3
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?

Webアプリエンジニアがゲーム用にEC2インスタンスを立ててみた

3
Last updated at Posted at 2026-08-17

はじめに

最近、友人と「7 Days to Die」というゾンビサバイバルゲームにハマっていて、休日の夜な夜な集まってプレイしています。

これまでは自宅PCでサーバーを立てて友人を招待していたのですが、

  • マシンスペックの限界(自分のPCが重くなる)
  • 自分がPCを起動していないと誰も遊べない

という2つの壁にぶつかっていました。せっかくなら勉強も兼ねて、AWS EC2にサーバーを移してみることにしました。

環境要件

  • 1人〜6人で遊べる程度のスペック
  • 誰でも(AWSアカウントを持っていない友人でも)簡単に起動・停止できる

全体像

インフラはすべてTerraformで管理し、大きく3つのパーツで構成しています。

  • EC2: 7 Days to Dieのサーバー本体。m6i.xlarge(4vCPU/16GB)でUbuntu 24.04を使用
  • Lambda: Discordでログインした友人だけが押せる起動・停止ボタン
  • EventBridge Scheduler: 消し忘れ対策として毎朝6時に強制停止する保険

CDKやCloudFormationは使わず、Terraformの素の.tfファイルのみ、しかもVPCも新規に作らずアカウントのデフォルトVPCをそのまま使っています。個人のホームラボ用途でネットワーク設計に凝っても得るものが少ないと判断し、あえてシンプルに倒しました。

ゲームサーバー本体の構築

EC2のuser_data(初回起動時に自動実行されるスクリプト)で、SteamCMDのインストールからゲームサーバーの起動まで全自動にしています。

# ライセンス同意を事前回答して無人インストール
echo steam steam/question select "I AGREE" | debconf-set-selections
echo steam steam/license note "" | debconf-set-selections
apt-get install -y steamcmd

# 7DTDサーバー本体(App ID: 294420)
sudo -u ubuntu /usr/games/steamcmd \
  +force_install_dir /home/ubuntu/7dtd \
  +login anonymous \
  +app_update 294420 validate \
  +quit

プロセス管理はsystemdに任せています。

「起動する度に最新版へ」への変更

最初はサーバー作成時(user_data実行時)にだけapp_updateを1回叩く形でした。しかしこれだと、Terraformでサーバーを作り直さない限りゲーム本体が更新されません。7 Days to DieはBeta版でアップデート頻度が高いゲームなのと、サーバーのバージョンとユーザーのsteamのバージョンが一致しない場合はゲームをすることが出来ません。

そこで、systemdのExecStartPreにSteamCMDの更新コマンドを移動し、サービスが起動するたびに(=EC2が起動するたびに)最新版を検証・更新してからサーバーを立ち上げる方式に変更しました。

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/7dtd
ExecStartPre=/usr/games/steamcmd +force_install_dir /home/ubuntu/7dtd +login anonymous +app_update 294420 validate +quit
ExecStart=/home/ubuntu/7dtd/startserver.sh -configfile=serverconfig.xml
Restart=on-failure
RestartSec=15
TimeoutStartSec=1800

更新チェック自体に数分かかることがあるためTimeoutStartSec=1800(30分)を設定し、After=network-online.target / Wants=network-online.targetでネットワークが確実に立ち上がってからSteamCMDが動くようにしています。別途アップデート用のcronやスクリプトを持たずに済むのが利点です。

「誰でも起動・停止できる」

Discord OAuth2でログインし、特定のDiscordサーバー(ギルド)のメンバーだけが使えるWeb操作パネルをLambda + 関数URLで作ることにしました。

  • API GatewayではなくLambda Function URLを直接公開(認証はLambda内部のDiscordログインで行うため、関数URL自体はauthorization_type = "NONE")
resource "aws_iam_role_policy" "control_panel" {
  policy = jsonencode({
    Statement = [
      {
        Effect   = "Allow"
        Action   = ["ec2:StartInstances", "ec2:StopInstances"]
        Resource = "arn:aws:ec2:ap-northeast-1:${data.aws_caller_identity.current.account_id}:instance/${aws_instance.server.id}"
      }
    ]
  })
}
  • 実際の画面が以下になります
    • こちらの画面で誰でも起動・停止を行えるようにしています
      image.png
    • また、起動時にIPアドレスを表示することによってスムーズにゲームに参加できるようにしています
      • image.png

お金の話

土日祝の夜、最大でも4時間程度しか遊ばない使い方なので、サーバーの停止し忘れを防ぐようにしました。

  1. 毎日6:00(JST)のEventBridge Scheduler強制停止
  2. 手動停止(Web操作パネルのStopボタン)
resource "aws_scheduler_schedule" "daily_shutdown" {
  schedule_expression          = "cron(0 6 * * ? *)"
  schedule_expression_timezone = "Asia/Tokyo"

  target {
    arn      = "arn:aws:scheduler:::aws-sdk:ec2:stopInstances"
    role_arn = aws_iam_role.scheduler.arn
    input    = jsonencode({ InstanceIds = [aws_instance.server.id] })
  }
}

すでに停止しているインスタンスに対してこのスケジューラが発火しても何も起きないので、安全に二重化できています。

見積もりは月2,500円前後(稼働40時間+EBS+固定IP)としていて、AWS Budgetsで$30/月のアラートも設定しています。

発展編(今後やりたいこと)

  • 15分間ゲームサーバーに人がいなかった場合に自動停止する
  • シャットダウン前のワールドデータS3自動バックアップ
  • 7days用サーバー構築MCP
  • サーバーのスケールアップの自動化

まとめ

初めてAWSのEC2を立てて見たのですが、AWSのコンソール画面でEC2が立ったときは感動しました。
これからもできるだけ安く運用(目指せ0円!)出来るように改良重ねたいと思います!

3
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
3
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?