🔑 重要なポイント
✦ AI·GEN友達のためにパルワールド(Palworld)専用サーバーを、常時起動の家用マシンに Docker で立てた一部始終を、そのまま辿れる教程としてまとめた記録。発端は友達が Radmin VPN で繋いでいたことだが、この手の P2P は NAT を抜けられないと第三者の中継に退避し、トラフィックが外を回る。だから筆者は自分の常時起動マシンで自ホストした。まず一つ迷信を崩す:業者のスペックは判で押したように「16GB から」だが、小規模の日常はとても軽く、筆者の実測は 3~5 人で約 1.2GB;本当に防ぐのはパルワールド名物のメモリリークで、mem_limit + 毎日再起動で押さえる。続いて枝葉を落とした docker-compose(port に /udp を忘れず、RCON は 127.0.0.1 に固定)、そして最も詰まる UDP 接続の三関門:ufw で udp 許可、ルーター port forwarding(必ず UDP)、DDNS。加えて二つの誤解を正す:Cloudflare は必ず灰色の雲(オレンジの雲のプロキシは UDP を通さず、有効にすると繋がらない)、UDP のゲームパケットは nginx を一切経由しない。後半はワールド設定の落とし穴(ini を直接いじると環境変数で再生成され上書き)、友達の「バージョン不一致」の直し方(buildid 比較、再起動で SteamCMD 更新、更新前に RCON でブロードキャスト + 保存)、そして 18GB のゲーム本体を毎日バックアップに入れないこと。最後に自ホストのチェックリスト付き。
友達がパルワールド(Palworld)の 1.0 を見て、一緒にやろうと誘ってきた。彼らは二年前に一度クリア済みで、この大型アップデートを機にもう一周したいらしい。私もちょうどその時期は暇だった。
正直、このゲームへの第一印象はよくなかった。当時の「ポケモンのパクリ」騒動があったからだ。でも後にその訴訟に勝ち、1.0 の更新幅も本当に大きいので、思ったほどひどくないのかもと、私も手を出した。
友達は最初、Radmin VPN でみんなを繋いでいた。この方法は駄目とは言わないが、私にはいつも資安面のもやもやが残る。Radmin のような仮想 LAN は P2P で動く。両端が直接繋げるなら直接繋ぎ、相手の NAT やファイアウォールを抜けられないと、サービス提供元自身のに退避する。友達の家のネットワークを考えると、どの組も全部抜けられるとは思えず、大半は中継に落ちるだろう。中継の代償は二段階ある。一つは遅い(パケットが遠回りする)、もう一つはゲームのトラフィックが無料・クローズドソースのサービスのサーバーを通ること。確かに全体は暗号化されている。だが接続を第三者に一周させるかどうかは、私にとっては不要なリスクだ。そして私にはちょうど 24/7 で動いている家用マシンがあったので、彼らの進行がまだ浅いうちに割り込んだ。専用サーバーを立てよう、みんな私の家に直接繋げばいい。
というわけでこの記事だ。Docker でパルワールド専用サーバーを立てるのは難しくない。docker compose up で数分で動きだす。難しいのは次の一歩:立ったのに、友達が入ってこられない。 ここで詰まる人は、「どう立てるか」で詰まる人よりずっと多い。この記事は全行程を一通り歩く。リソース見積もり、docker-compose、最も詰まりやすい UDP 接続、そして「友達がバージョン不一致で入れないと言う」の直し方まで。すべてのコマンドはそのまま実行でき、パスワードと IP はプレースホルダなので、自分のものに置き換えてほしい。
まず、どの image を使うか、そしてメモリは実際どれだけ食うか#
先に一言:多くの人が自ホストで使うのは公式の専用サーバーツール(SteamCMD で直接 PalServer を引く)で、必ずしも Docker ではない。 私が Docker を選ぶのは、単に使い慣れていて、マシン上の他サービスと一貫して管理しやすいからだ。あなたも常時起動のサーバーがあって docker が手に馴染むなら、この道は快適だ。使っている image はコミュニティ管理の で、SteamCMD のダウンロード、設定ファイル生成、バックアップ、RCON を全部包んでいる。
メモリはまず一つ迷信を崩したい。ホスティング業者のスペックページを見ると、判で押したように「16GB から、32GB でより安定」と書いてある。あの数字は保守的だ(彼らは RAM も売っている)。実際には小規模なら日常はとても軽い。私のこの Linux docker で 3~5 人を回して、実測はだいたい 1.2GB あたりだった(長時間監視ではなく、ふと見た値)。
ではなぜまだメモリを気にするのか。パルワールドにはという持病があるからだ。プロセス自体が時間とともに少しずつ肥大していく。ゲーム内で何を建てたかとは無関係に。コミュニティの実測では、4 人サーバーを再起動なしで回し続けると、一週間で 5G から 8~12G まで登ることがある。だから正しい手は 32G を用意することではなく、mem_limit で上限を抑え、毎日の定時再起動(メモリを解放する。誰かオンラインなら延期)を組み合わせ、リークを妥当な範囲に押さえること。そうすればいくら長く回しても、同じマシンの他サービスを巻き込まない。
最小限で動く docker-compose#
コアの設定はそう多くない。枝葉を落として、本当に押さえるべき数行だけ残したものがこれ:
services:
palworld:
image: thijsvanloef/palworld-server-docker:latest
restart: unless-stopped
container_name: palworld
stop_grace_period: 30s # 停止シグナル後、保存に 30 秒残す
ports:
- "8211:8211/udp" # ゲーム接続、UDP(重要、下で詳述)
- "27015:27015/udp" # Steam query、UDP
- "127.0.0.1:25575:25575" # RCON、ローカルのみ、外からは触れない
environment:
PLAYERS: "16"
SERVER_NAME: "My Palworld"
SERVER_PASSWORD: "<あなたのサーバーパスワード>"
ADMIN_PASSWORD: "<あなたの管理パスワード>"
UPDATE_ON_BOOT: "true" # コンテナ起動時にゲーム更新を確認
RCON_ENABLED: "true" # 自動バックアップ/再起動が優雅な終了に使う
BACKUP_ENABLED: "true"
AUTO_REBOOT_ENABLED: "true" # 毎日再起動、肥大したメモリを解放
mem_limit: 16g
volumes:
- ./data:/palworld # ゲーム本体 + セーブがここ今は目立たないが後で踏むポイントがいくつか:
8211と27015の後ろの/udpを落とさないこと。パルワールドは UDP で動く。うっかり TCP と書くと、サーバーは起動し、自分のローカルからも繋げるが、外の人は一人も入れない。- RCON を
127.0.0.1に固定:自動バックアップ/再起動が先に警告をブロードキャストして優雅に終了するための管理チャネルで、ローカル専用、外に出してはいけない。 mem_limitとAUTO_REBOOT_ENABLEDは一組で、上のメモリ肥大に真正面から対処するもの。
本当に詰まるのはネットワーク:UDP 接続の三つの関門#
docker compose up -d のあと、サーバーは 8211 で動き、同じネットワークから LANのIP:8211 に繋ぐのは大抵問題ない。そして友達が繋ぐと、入ってこられない。
パケットがインターネットからあなたの家のあのコンテナまで届くには、途中に三つの関門があり、一つでも欠けると通れないからだ:
まずパケットをホストに届かせる。 で二つの UDP port を開ける:
sudo ufw allow 8211/udp comment 'Palworld game'
sudo ufw allow 27015/udp comment 'Palworld query'プロトコルは必ず udp。ここが三関門の中で最も tcp と書き間違えられる関門だ。
パケットがインターネットからあなたの家に届くには、ルーターがそれをそのホストに転送する必要がある。ルーターの管理画面で転送ルールを二本追加する:
| 外部 (WAN) | → 内部ホスト | プロトコル |
|---|---|---|
| 8211 | 192.168.x.x : 8211 | UDP |
| 27015 | 192.168.x.x : 27015 | UDP |
家庭用ネットワークの公開 IP は普通変動するので、 をぶら下げて、友達が固定のアドレス一つを覚えればいいようにする。毎回 IP を聞かなくて済む。Cloudflare でドメインを管理しているなら、致命的な細部が次の節にある。
WARNING
Cloudflare は「灰色の雲」(DNS only)にすること、「オレンジの雲」(Proxied)は駄目 Cloudflare のオレンジの雲のプロキシは HTTP/HTTPS のトラフィックしか転送しない。任意の UDP パケットは転送しない。パルワールドのドメインをオレンジの雲にすると、友達は 100% 繋がらず、しかも静かに失敗する(ウェブ系サービスは正常で、ゲームだけ繋がらない。ここが原因とは結びつけにくい)。必ず灰色の雲にして、ドメインを家の IP に直接解決させること。
二つのよくある誤解を、時間を無駄にする前にはっきりさせておく:
NOTE
nginx はいじらなくていい、一文字も
ウェブサービスを立て慣れた人は、「外向け」と聞いた途端にリバースプロキシを思い浮かべる。だが 。パルワールドは UDP のゲームパケットで、「ルーター → ufw → コンテナ」を直通し、nginx とは完全に無関係だ。今回 /etc/nginx は一文字もいじらない。
では 27015 は開ける必要があるのか。これは で、「あなたのサーバーの状態が Steam のサーバーブラウザに表示されるかどうか」だけに関わる。最小限にしたいなら まず 8211 だけ開ける。友達は あなたのアドレス:8211 に直接繋いで遊べる。誰かが本当に Steam のお気に入りからオンライン状態を見たがったら、あとで 27015 を足せばいい。
ワールド設定の落とし穴:ini を直接いじると上書きされる#
サーバーが繋がったら、経験値倍率などを調整したくなるはずだ。ここに必ず踏む落とし穴がある:この image は起動のたびに環境変数から PalWorldSettings.ini を再生成する。 その ini ファイルを手で書き換えても、次のコンテナ再起動で上書きされ、直したのに直っていない状態になる。
正しいやり方は、設定を docker-compose.yml の environment ブロックに書き、生成時にあなたの値を持たせること。よく使うもの:
よく使うワールド設定(compose の environment に書く)
| 環境変数 | 効果 | 例 |
|---|---|---|
EXP_RATE | 経験値倍率 | 3.0 |
COLLECTION_DROP_RATE | 採集ドロップ倍率 | 3.0 |
DEATH_PENALTY | 死亡ペナルティ | Item(アイテムのみ落とす、装備は保持) |
PAL_EGG_DEFAULT_HATCHING_TIME | 卵の孵化時間(時間) | 1(デフォルト 72) |
BASE_CAMP_WORKER_MAX_NUM | 拠点の作業パル上限 | 20 |
SERVER_PLAYER_MAX_NUM | 人数上限 | 32 |
PVP / ENABLE_FRIENDLY_FIRE | PvP / フレンドリーファイア | true / false |
書き換えたら docker compose up -d でコンテナを再構築し、新しい環境変数から ini を再生成すれば設定が効く。効いているか確かめるには、コンテナ内の生成された ini を見る(docker exec palworld cat .../PalWorldSettings.ini)。自分の値になっているのを確認してから終える。
友達が「バージョン不一致」で入れない:サーバーが遅れている#
数日遊んで、ある友達が「入れない、バージョン不一致と出る」と報告してきた。ほぼ必ず同じ原因だ:彼の client はすでに新版に自動更新され、あなたの server は旧版に止まっている。
どう確認する? を比べる:ローカル server の buildid を Steam 最新の buildid と突き合わせ、違えば遅れている。
ここに厄介な錯覚を暴いておく:コンテナのログに container is up to date と出ていて、もう最新だと思い込むこと。あの一行は Docker image が最新という意味で、ゲームファイルが最新という意味ではない。 ゲーム更新は UPDATE_ON_BOOT がコンテナ起動時に SteamCMD を一度走らせて引くもので、コンテナが数日再起動なしで回り続けていたら、この数日の新版を掴む機会がなかったわけだ。
直し方はコンテナを再起動して、SteamCMD 更新を一度トリガーすること:
docker compose up -d --force-recreateだが再起動はオンラインの人を蹴り出す。直接やってはいけない。優雅なやり方は、まず RCON でブロードキャストして保存し、それから再起動すること:
TIP
更新前にブロードキャスト + 保存、遊んでいる最中にいきなり蹴らない
RCON で一言ブロードキャスト(「サーバーは 5 分後に更新のため再起動します」)をオンラインプレイヤーに送り、保存を一度トリガーしてから --force-recreate。蹴られた人は自分の client も更新が終われば(普通は自動、数分)、そのまま再接続すればいい。セーブは影響を受けない。更新は一~二分(~5GB ダウンロード)、完了後にローカル buildid が友達の client と揃う。
毎回手動で見張りたくなければ、AUTO_UPDATE_ENABLED をオンにする。server が定時に自分で更新を確認し(誰かオンラインなら先にブロードキャストしてから更新するよう設定もできる)、ゲームに新版が出ても友達が入れなくなることは二度と起きない。
18GB のゲーム本体を毎日バックアップディスクに入れない#
最後に見落としやすい運用の罠。私のように、サーバーのディレクトリ全体を毎日 rsync でバックアップする仕組みがあるなら、パルワールドを足したあとは要注意だ:あの data/ フォルダはゲーム本体まるごと、18GB 近くを抱えていて、放っておくと毎日バックアップディスクに詰め込まれる。
本当にバックアップが要るのはセーブだけで、あの 18GB のゲームファイルではない(ゲームファイルはいつでも再ダウンロードできる)。だから:
- メインの
rsyncからpalworld/data(ゲーム本体)を除外する - セーブディレクトリ(
Pal/Saved)を単独でバックアップする。消えたら痛いのはそこだ - パルワールドのセーブも既存の古いバックアップ整理ループに入れる(例:7 日だけ残す)
.gitignore の方も data/ が除外されているかついでに確認し、18GB のゲームファイルがバージョン管理に紛れ込まないようにする。
一ページのチェックリスト#
全行程を、そのまま写せる順番に凝縮:
パルワールド自ホストチェックリスト
- RAM に怯えない:小規模なら実測 1~2G で足りる(業者の 16G は保守的);本当に防ぐのはメモリリークで、
mem_limit+ 毎日再起動で押さえる。 - compose:port に
/udpを忘れない;RCON は127.0.0.1に固定;パスワードは環境変数に。 - ネットワーク三関門:ufw で
udp許可 → ルーター port forwarding(UDP!)→ DDNS。 - Cloudflare は灰色の雲、オレンジの雲のプロキシは UDP を転送しない、有効にすると繋がらない。
- nginx は触らない、UDP のゲームパケットはリバースプロキシを経由しない。
- ワールド設定は compose の environment に書く、ini を手でいじらない(再生成で上書きされる)。
- 友達のバージョン不一致 = server が遅れている;buildid を比べ、コンテナを再起動して SteamCMD 更新をトリガー、更新前にまず RCON でブロードキャスト + 保存。
- バックアップからゲーム本体を除外(18GB)、セーブディレクトリだけを単独でバックアップ。
- thijsvanloef/palworld-server-docker —— この記事で使った Docker イメージGitHub
- パルワールド公式の専用サーバー説明Palworld Wiki
- Cloudflare —— なぜ Proxy(オレンジの雲)は HTTP/HTTPS しか通さないのかCloudflare Docs
まだコメントがありません
✨ 最初のコメントを残しませんか