Home Lab · Game Servers

Updating a Palworld Server Without Losing Anything

Updated after losing an entire holiday weekend to a patch that had "already shipped" for over a day and just... hadn't, on the channel we were watching. Here's what actually happened, the official Docker image nobody mentions in the main setup guides, the one-button path we built once we found it, and the manual steps if you'd rather run them by hand.

Game Palworld dedicated server Tool Docker / docker compose Related Hosting Palworld on a Native x86 Debian Box
OVERVIEW

Why "already up to date" isn't always true

Your Palworld client updates the moment Steam decides to push a patch — you don't get a say in it. Your dedicated server does not. Depending on which channel you update it from, it might sit on the old version for minutes, hours, or — as we found out the hard way — over a full day, with the update tool telling you the whole time that everything's current.

This page is the actual sequence of events from a real patch day, not a clean-room rewrite: what looked broken, what turned out to just be a second, completely separate distribution channel we didn't know existed, and the update paths (one button, or by hand) we ended up with once we found it.

01

The depot-lag weekend

Palworld shipped a real patch on a Sunday. Every client updated within the hour, like always. Our dedicated server — self-hosted, SteamCMD-based, the setup most guides walk you through — did not, and kept not updating for the rest of that day and into the next.

We checked this five different ways before believing it: repeated metadata queries against the dedicated-server Steam depot, a completely fresh anonymous download into an empty directory, a real download through an actual authenticated Steam account via the normal Steam client GUI, cross-referencing a public Steam-depot tracking site, and a direct pull of just that one depot's files. All five agreed: the dedicated-server package genuinely had not been touched. Not a caching issue, not a "your tool is wrong" issue — Valve's own backend for that specific package hadn't received a new build.

!

If you're seeing this too, you're not doing anything wrong. This is a real, recurring pattern for this specific game — the client and the dedicated server binary are shipped on different schedules by the developer, and nothing on your end controls that.

02

Two channels, not one

What actually broke the stalemate: Palworld's developer publishes the dedicated server through two separate, independently-updated channels, and most setup guides — including the one this site walks through — only ever mention one of them.

  • Steam depot (SteamCMD)The one every Pterodactyl egg and most tutorials use. This is the one that lagged over a day behind the client patch.
  • Official Docker imageA container image the developer publishes directly, updated independently of the Steam depot. It was already current the entire time we were troubleshooting the other channel.

We only found the second channel because someone mentioned it in a community thread, almost in passing. It's genuinely official — the image and its example configuration are linked right from the developer's own technical documentation — it's just not the path most setup tutorials default to, ours included at the time.

i

The lesson that generalizes: if an update seems stuck on one distribution channel, check whether the same binary is published anywhere else before assuming the channel itself is just slow. We rebuilt our entire hosting setup around the Docker image once we found it, specifically because it's the channel that was actually current.

03

Checking whether an update actually exists

Since moving to the Docker image, checking for a new version doesn't require touching the live server at all — the image registry publishes its own list of every version it has, and it's a plain read-only API call:

List every published server version
TOKEN=$(curl -s "https://ghcr.io/token?scope=repository:pocketpairjp/palserver:pull" | grep -oP '"token":"\K[^"]+')
curl -s -H "Authorization: Bearer $TOKEN" https://ghcr.io/v2/pocketpairjp/palserver/tags/list

Compare the highest version tag it returns against whatever your server currently reports (its REST API's /v1/api/info, or the Game version is vX.X.X.XXXXXX line in its boot log). If they don't match, there's a real update sitting there — no guesswork, no "already up to date" ambiguity.

✓

We automated this. A background check runs every 10 minutes while a client-side patch is known to be pending, and posts to our Discord the moment a new server image is actually published — no more manually re-checking a channel that might not even be the right one.

04

The one-button path

Our admin console now has an Update control that does the whole safe sequence itself: refuse if anyone's currently online, snapshot the save data, pull the new image, recreate the container, wait for it to actually boot and confirm the new version — then automatically roll everything back if any step along the way fails. The version field pre-fills with whatever the monitor last saw published, so there's nothing to look up by hand.

That's the whole workflow now: tap Update, confirm, wait for the progress steps to finish. If a player happens to be online, it refuses outright rather than kicking anyone mid-session.

05

The manual path

If you're running the Docker image yourself and want to do this by hand instead of through a console button, it's a short sequence:

  • Confirm nobody's online (your server's REST API players endpoint)
  • Snapshot just the save-data folder — the image itself doesn't need snapshotting, it's immutable and always re-pullable
  • Edit your compose file's image tag to the new version
  • Pull and recreate
  • Watch the boot log for the real version-confirmation line, not just "the container didn't immediately exit"
  • Confirm the new version via the REST API
Edit the tag, then pull and recreate
# in your compose.yaml:
image: ghcr.io/pocketpairjp/palserver:v1.0.5.XXXXXX # whatever the registry check above returned

docker compose pull
docker compose up -d --force-recreate

Then watch the logs for the same two lines the automated path checks for:

What a healthy boot actually looks like
Game version is vX.X.X.XXXXXX
Running Palworld dedicated server on :8211
06

The rollback snapshot (still the whole safety net)

This part hasn't changed, and it's actually gotten cheaper. With the container image itself being immutable and always re-downloadable, the only thing that genuinely needs protecting before an update is your save data — usually well under a hundred megabytes, not the multi-gigabyte binary directory a SteamCMD-based install has to snapshot.

Near-instant snapshot of just the save data
cp -al Saved Saved.pre-update-snapshot

If anything goes wrong — the pull fails, or the server won't boot cleanly afterward — stop the container, delete the failed save directory, move the snapshot back into place, revert the compose file's tag, and start it back up. From the outside, it should look like nothing happened.

✓

Only discard the snapshot once you're actually confident the update is stable — ideally after someone's genuinely played on it for a bit, not the instant the boot check passes.

LEGACY

If you're still on the SteamCMD/Panel path

Kept for anyone still running the setup this site originally walked through — this is the channel that lagged, not something we'd recommend as your primary update path anymore, but the mechanics below are still accurate if you're on it.

SteamCMD update
steamcmd.sh +force_install_dir <your-install-dir> +login anonymous +app_update 2394010 +quit
!

Don't add validate as a reflex on this path — it's the textbook-correct flag for a from-scratch install, but it hit a well-documented SteamCMD bug for us three times in a row (a full re-download of SteamCMD itself, then a hang specifically during the extra checksum pass). Dropping it succeeded immediately. Only add it back for an actual corruption concern.

Same safe sequence applies here too — confirm nobody's online, snapshot the whole install directory (a hardlink clone, same as above, just of a much bigger directory since the binaries live inside it), update, restart, verify the real boot log line and REST API version, roll back the snapshot on any failure.