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?

Minecraft serverをDockerで安全運用する

0
Posted at

はじめに

前回の記事「Docker環境の構築」で Docker を導入したので、今回はその上で Minecraft Java サーバを2ワールド構成で運用できるようにしました。さらに、友人向けに SSH 操作を開放しつつ、サーバ全体に触れられないように 操作範囲を強制的に限定しています。
今回のゴールは次の3つです。

  • サバイバル/クリエイティブを Docker Compose で分離運用する
  • 起動・停止・ログ管理をスクリプト化して保守しやすくする
  • 友人用ユーザーに最小権限だけを渡し、誤操作や悪用時の被害を抑える

マインクラフトのサーバ構成は、minecraft-server(GitHub) で管理しています。

運用構成

  • Ubuntu Server 上で Docker Compose を使用
  • mc-survival25565)と mc-creative25566)を別コンテナで運用
  • ワールドデータはDocker Composeのボリューム設定data-survival / data-creative に分離して永続化
  • 起動時にログ整理を自動判定するラッパースクリプトを利用
  • 友人用ユーザー guest-minecraftTailscale 経由 SSH + 許可コマンドのみ実行

minecraft server architecture

Docker Compose で2ワールドを分離

docker-compose.yml では、ポート・メモリ・ワールド保存先を分けています。
restart: "no" にしているのは、「遊ぶときだけ起動」の運用に合わせるためです。

services:
  mc-survival:
    image: itzg/minecraft-server:java21
    container_name: mc-survival
    ports:
      - "25565:25565"
    environment:
      MEMORY: "4G"
      ENABLE_WHITELIST: "TRUE"
    volumes:
      - ./data-survival:/data
    restart: "no"

  mc-creative:
    image: itzg/minecraft-server:java21
    container_name: mc-creative
    ports:
      - "25566:25565"
    environment:
      MEMORY: "2G"
      MODE: "creative"
      FORCE_GAMEMODE: "true"
    volumes:
      - ./data-creative:/data
    restart: "no"

日常運用はスクリプト化

起動・停止は次のスクリプトで統一しています。

./scripts/start-minecraft.sh mc-survival
./scripts/start-minecraft.sh mc-creative
./scripts/stop-minecraft.sh mc-survival
./scripts/stop-minecraft.sh mc-creative
./scripts/stop-minecraft.sh

start-minecraft.sh は、前回ログ整理から24時間以上経っていたら cleanup-minecraft-logs.sh を実行し、30日超の圧縮ログ(*.gz)を削除します。
加えて、コンテナログ側も max-size: 10m / max-file: 5ログローテーションしており、長期運用でディスクが詰まりにくい構成にしています。

友人向け SSH は「実行できる操作」を固定

「SSH を渡す = 何でもできる」状態にしないため、入口を固定しました。

  1. 友人用ユーザー guest-minecraft を作成
  2. パスワードログインを無効化し、SSH公開鍵認証のみ許可
  3. authorized_keyscommand="/usr/local/bin/mc-guest-entrypoint" を強制
  4. mc-guest-entrypoint で許可コマンドをホワイトリスト化
  5. sudoers/usr/local/bin/mc-ctl の限定サブコマンドだけ許可

authorized_keys 例:

restrict,command="/usr/local/bin/mc-guest-entrypoint" ssh-ed25519 <public-key>

この1行は、次の意味です。

  • ssh-ed25519 <public-key>: この公開鍵で認証できる
  • command="/usr/local/bin/mc-guest-entrypoint": 鍵認証に成功したら、ユーザーが ssh ... "任意コマンド" を指定しても無視し、常にこのスクリプトを実行する
  • restrict: authorized_keys 側の包括制限で、ポートフォワーディング(-L/-R/-D)、agent forward、X11 forward、PTY割り当て、~/.ssh/rc 実行を無効化する

つまり、接続時の実行フローは次のようになります。

  1. 公開鍵認証が通る
  2. mc-guest-entrypoint が強制実行される
  3. 元のコマンドは SSH_ORIGINAL_COMMAND としてスクリプト側で受け取り、ホワイトリスト判定
  4. 許可コマンドのみ sudo -n /usr/local/bin/mc-ctl ... を実行
  5. 不許可コマンドは即時拒否

command=... だけだと SSH 側のフォワーディング機能が残るため、今回のように restrict を併用して入口を狭める構成にしています。
許可しているのは以下のみです。

  • start survival
  • start creative
  • stop survival
  • stop creative
  • stop all
  • status

それ以外はサーバ側で拒否されます。
また、guest-minecraftdocker グループには入れていません(docker グループは実質 root 相当のため)。

再現性を上げるための配置方針

/usr/local/bin/etc/sudoers.d を直接手編集すると、差分管理が難しくなります。
そこで、正本はリポジトリ配下の scripts/admin/ に置き、インストーラで反映する方式にしました。

sudo ./scripts/admin/install-guest-minecraft.sh

主な管理対象:

  • scripts/admin/mc-ctl
  • scripts/admin/mc-guest-entrypoint
  • scripts/admin/guest-minecraft-mc.sudoers
  • scripts/admin/install-guest-minecraft.sh

友人側の操作導線(Windows)

友人向けには、workspace/Guide_for_Friends/.bat と PowerShell UI を用意しました。
中身は最終的に ssh guest-minecraft@<tailscale-ip> "<allowed-command>" を叩くだけなので、実行範囲はサーバ側ポリシーで担保されます。

「悪意ある相手でも安全か?」への整理

この構成は、被害を小さくする設計としては有効です。
ただし「絶対安全」ではありません 例えば次のリスクは残ります。

  • 鍵の漏えい(正規ユーザーとして接続される)
  • 許可スクリプト自体のバグ
  • ホスト OS / Docker / SSH の脆弱性

運用では、鍵ローテーション・OS更新・ログ監視を継続し、必要に応じて接続元制限(UFW + Tailscale ACL)を強化するのが現実的です。

まとめ

今回の構成で、Minecraft サーバ運用は次の状態になりました。

  • 2ワールドを明確に分離し、運用コマンドを統一
  • ログ肥大化を自動で抑制
  • 友人には「必要な操作だけ」委譲し、ホスト全体の露出を最小化

「動けばOK」で終わらせず、運用・保守・権限設計まで含めて形にできたのが一番の収穫でした。


この記事はReo's Tech Blogの同名記事にも掲載しています。

Reo's Tech Blogでは、個人開発や日々の技術的な取り組みを記録しています。興味がありましたら、ほかの記事もご覧ください

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?