Releases: heyvaldemar/minecraft-server-docker-compose
Release list
v1.6.1
Changed
itzg/minecraft-server:2026.9.1moved toitzg/minecraft-server:2026.9.2. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.- The freshness check has its own workflow, Pin Freshness. It ran inside Deployment Verification, whose badge is the one at the top of this README. Across the fleet, nine red runs in ten were a pin one version behind - which the fleet's triage moves within the day - and a reader cannot tell that from a stack that does not boot. The badge now says whether the stack boots. The job itself is unchanged.
itzg/mc-backup:2026.9.1moved toitzg/mc-backup:2026.9.2. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.
Upgrading
git pull (or ./update.sh), then docker compose up -d. Containers on a refreshed image are recreated; data volumes and .env are untouched. This release was cut by fleet triage after the deploy job booted the stack on the refreshed images.
Full history in CHANGELOG.md.
What upstream changed
Read by fleet triage from the upstream release notes (or the commits between the tags) against this compose file, before the bump was applied.
Upstream changes 2026.9.1 -> 2026.9.2
Verdict: SAFE TO APPLY — no breaking changes in the notes, no required variable changes, and the image configuration fields (user, entrypoint, cmd, ports, volumes, healthcheck, environment) are unchanged between the two versions.
Breaking changes
- none found in the notes
Variables
- none. Two new opt-in features were added, neither required:
REMOVE_OLD_CONFIGS— "Add REMOVE_OLD_CONFIGS to clear old configs before modpack install"PRE_START_SCRIPT— "Add PRE_START_SCRIPT, run after setup and before the server starts"
Neither is referenced in this compose file or.env.example; no action needed unless you want to adopt them.
Data and dependencies
- none. This release only bumps internal helper tools (
mc-image-helperto v1.70.0,mc-monitorto v0.18.1,mc-server-runnerto v1.16.0) and doc/build dependencies. No companion service (database, cache, search engine) is named in the notes, and this template has no such service to check against. - One behavioural note worth flagging for modded/plugin servers: "Force-include Simply Tooltips and s-lib: mis-tagged client-only libraries that server mods hard-depend on" — affects mod/modpack installs, not this template's PAPER + plugin setup, but worth knowing if
MINECRAFT_SERVER_TYPEorMODRINTH_PROJECTSis ever changed to a modded loader.
Before applying
- none required. Standard practice still applies: the
backupsservice already runs before/after any restart, so no manual backup step is needed beyond your normal routine.
Notes read
- 2026.9.2 (itzg/docker-minecraft-server), covering the full range from 2026.9.1 to 2026.9.2 as linked in the compare URL. No UPGRADING/BREAKING_CHANGES/CHANGELOG document was supplied separately; the GitHub release notes above are the only source available for this range.
v1.6.0
Added
tools/plugins-for-version.sh: ask whether the plugins exist before a world is converted. A Minecraft release always outpaces its plugin ecosystem, andVERSIONdefaults toLATEST— so the server takes the new one the moment it appears, fails to resolve plugins that have no build for it yet, and exits during resolution in a loop, with its version already bumped and its backup already taken. The check reads the project list out of the compose file so it cannot drift from what the server would download, and the daily verification runs it. A question Modrinth could not answer exits2rather than condemning the plugins: that is not a no. Shown both answers intests/plugins-for-version.sh.
Upgrading
git pull (or ./update.sh). Nothing about the running server changes. Before you move to a new Minecraft version, run tools/plugins-for-version.sh — or read the daily verification, which now asks for you.
Full history in CHANGELOG.md.
v1.5.5
The restore test unpacked an archive into a throwaway directory and accepted a level.dat found anywhere underneath. That proves the archive is a world. It says nothing about whether restoring it puts that world where the server reads it, and those are different claims.
The documented procedure is to extract an archive over ./minecraft-server-data. An archive whose world sits one directory deeper unpacks perfectly, leaves the server with an empty data directory, and the server does not complain — it generates a fresh world over the one being restored. On a sibling stack that exact difference kept a quarterly drill green for months: the documented command produced data/data/world/level.dat, and the drill looked for level.dat anywhere.
So the running server is the reference now. Whatever relative path it keeps its level.dat at is the path the archive has to unpack to, and when the layout changes this fails instead of blessing the old shape. The failure names both paths and says what a restore would actually produce.
Proven in three directions against synthetic archives before it shipped: the right layout passes, one directory too deep fails with that message, and an archive with no world at all fails differently.
Upgrading: git pull or ./update.sh. Nothing in the running stack changes — this is the test suite.
v1.5.4
Changed
itzg/minecraft-server:2026.9.0moved toitzg/minecraft-server:2026.9.1. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.
Upgrading
git pull (or ./update.sh), then docker compose up -d. Containers on a refreshed image are recreated; data volumes and .env are untouched. This release was cut by fleet triage after the deploy job booted the stack on the refreshed images.
Full history in CHANGELOG.md.
What upstream changed
Read by fleet triage from the upstream release notes (or the commits between the tags) against this compose file, before the bump was applied.
Upstream changes 2026.9.0 -> 2026.9.1
Verdict: SAFE TO APPLY — the notes contain only documentation, dependency-bump, and internal build-tooling changes; no breaking changes and no companion-service version requirement outside what the compose file already pins.
Breaking changes
- none found in the notes
Variables
- none — no new, renamed, or removed environment variables are mentioned. All
MINECRAFT_SERVER_*variables inminecraft-server-docker-compose.ymland.env.exampleare unaffected.
Data and dependencies
- none. The only dependency change is internal to the image build: "Update dependency itzg/mc-image-helper to v1.68.0" and an earlier "v1.67.2" bump —
mc-image-helperis bundled inside theitzg/minecraft-serverimage itself, not a separately pinned companion service (unlike a database, cache, or search engine), so this does not create a compose-file mismatch to flag. - No database, cache, or search-engine version is named in these notes, so the SAFE TO APPLY exclusion for un-pinned companion services does not apply here.
Before applying
- Update the pin: the compose file's
x-imagesblock currently defaultsMINECRAFT_SERVER_IMAGE_VERSIONto2026.9.0@sha256:4e29d14082d94748f945edad3ee5307b97adc730fec49860199f5e52218a9ae3. To move to 2026.9.1, bump this default (and its digest) inminecraft-server-docker-compose.yml, or setMINECRAFT_SERVER_IMAGE_VERSION=2026.9.1(with the matching digest, per.env.example's guidance) in.env. - No data migration, backup, or manual command is called for by these notes — this is a routine dependency/doc release.
Notes read
- 2026.9.1 (2026-09-12) — full text as provided above, covering the 2026.9.0...2026.9.1 range.
v1.5.3
Changed
itzg/mc-backup:2026.9.0moved toitzg/mc-backup:2026.9.1. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.
Upgrading
git pull (or ./update.sh), then docker compose up -d. Containers on a refreshed image are recreated; data volumes and .env are untouched. This release was cut by fleet triage after the deploy job booted the stack on the refreshed images.
Full history in CHANGELOG.md.
What upstream changed
Read by fleet triage from the upstream release notes (or the commits between the tags) against this compose file, before the bump was applied.
Upstream changes 2026.9.0 -> 2026.9.1
Verdict: SAFE TO APPLY — the only change is a CI dependency bump, no runtime code affected.
Breaking changes
- none found in the notes
Variables
- none
Data and dependencies
- none
Before applying
- No manual steps required. Update the digest/tag in the compose file's
x-imagesblock (mc-backup: &mc-backup-image ...itzg/mc-backup:${MINECRAFT_SERVER_BACKUP_IMAGE_VERSION:-2026.9.0@sha256:...}) to the 2026.9.1 tag and its new sha256 digest, thendocker compose pull backups && docker compose up -d backups.
Notes read
- 2026.9.1 (2026-09-08) — full text quoted above: "* build(deps): bump docker/setup-qemu-action from 4.2.0 to 4.3.0 in the docker group by @dependabot[bot] in itzg/docker-mc-backup#319"
v1.5.2
Changed
update.shnames any new required variable before it moves. An update can add a required variable;docker compose upused to stop on it after the checkout, with the tree already on the new tag. The script now lists the variables that appeared in.env.examplesince your version and refuses, before anything has moved, when a required one is not in your.env. Names only, never values.
Upgrading
git pull (or ./update.sh). Nothing running changes: this release adds or extends the update script and touches no image pin.
Full history in CHANGELOG.md.
v1.5.1
Changed
- The server image moves to
itzg/minecraft-server:2026.9.0. The release
is bug fixes and hardening: a modpack archive that cannot be extracted, a
CUSTOM_SERVERdownload that returns an HTTP error, and a failed FTB
installer now stop startup instead of leaving a half-installed server
running. Percentage memory sizes are computed with integer arithmetic. The
compose file boots and the backup cycle is exercised against the new image
before this lands.
Fixed
.env.examplenamed image versions the compose file no longer pins. It
still showed2026.8.2for the backup image while the compose default was
2026.9.0, so anyone copying the commented line as a starting point pinned
something older than the tested combination.
Upgrading
git pull (or ./update.sh), then docker compose up -d. The server container is recreated on the 2026.9.0 image; the world volume and .env are untouched. First start after the pull runs a normal Paper update.
Full history in CHANGELOG.md.
v1.5.0
Added
- Backup and restore tested end to end. Nine scenarios against the live
stack: an archive is produced, it is readable, it contains alevel.dat
rather than an empty directory tree, a file written after the last archive
reaches the next one, the archive unpacks into a world, and pruning is
configured rather than merely intended. - The world is proved to have been flushed before it was read. Before each
archive the sidecar tells the server over RCON to stop writing and flush.
What happens when that fails was measured, not assumed, against a sidecar
given a deliberately wrong password:itzg/mc-backupretries five times,
never archives without a successful flush, and exits 2 — which under
restart: unless-stoppedbecomes a restart loop producing no backups at all,
while everything indocker compose pslooks ordinary. Nobody watches a
restart count, so the test reads the sidecar's own log for the flush having
run and for the absence of RCON errors. Both assertions were confirmed to
fire against the broken sidecar before being trusted. - Every content assertion names an archive whose cycle BEGAN after the state
it is asserting about, and no assertion pipes into an early-exitinggrep.
Which of the two settled the flake is not established: the run carrying only
the first still failed and the run carrying both passed, but a synthetic
reproduction of the SIGPIPE case never triggered it. The test prints the
archive's contents on failure now, so the next occurrence is diagnosed from
data rather than from a third guess. "The newest completed archive" is not the same
thing: the cycle that finishes next may have started before the change, and
it is entirely correct for it not to contain it. That ordering trap produced
three separate CI failures before it was written down as one helper used
everywhere. - A cold start can archive before there is a world, and the test says so
rather than working around it. The sidecar waits for the server's
healthcheck, and that passes when the server answers — which on a slow
machine is before the world directory has been written. The first archive
then legitimately contains the server's files and no world. Never an issue at
the shipped 23 hour interval; real for anyone who shortens it or restarts
often. - The archive under test is chosen from the sidecar's log, not by
modification time. The newest file on disk is very often the one being
written, and a half-written gzip is readable bytarfor as far as it goes.
Picking by mtime reported a world with nolevel.datand an archive that
would not unpack — both true of the file it was handed, and neither anything
to do with the backups. An archive named by a log line that has asave-on
after it is complete by definition.
v1.4.0
Added
- Per-image version overrides. Every pin in the
x-imagesblock is
now${<PREFIX>_IMAGE_TAG:-repo:${<PREFIX>_IMAGE_VERSION:-tag@sha256:digest}}.
Set<PREFIX>_IMAGE_VERSIONin.envto run a different version of one
image while every other pin stays as tested (Compose pulls that tag
without a digest), or<PREFIX>_IMAGE_TAGto replace the whole
reference as before. A deployment that sets neither is unchanged. The
freshness job, the Trivy matrix and the fleet digest automation resolve
the nested default before reading a pin. Needs Docker Compose v2.5 or
newer (2022): v2.0 to v2.4 leave the inner${...}unexpanded and
docker compose upfails with an invalid reference instead of
deploying something unexpected.
Changed
itzg/mc-backup2026.8.2 to 2026.9.0.
Upgrading
git pull (or ./update.sh). A deployment that sets no _IMAGE_VERSION or _IMAGE_TAG variable renders exactly the same image references as before, so docker compose up -d recreates nothing. Requires Docker Compose v2.5 or newer.
Full history in CHANGELOG.md.
v1.3.0
Security
- Container hardening. Every service runs with
security_opt: no-new-privileges:true(no privilege escalation via
setuid binaries even if a process escapes its initial capability
set). Infrastructure containers (the reverse proxy, databases,
caches, backups) drop every Linux capability and add back only what
their entrypoints need (bind :80/:443, chown a data directory, drop to
the service user). Application containers keep the default capability
set: upstream images assume it, and a wrong guess there is a boot loop
in production, not a hardening win. CI boots the stack under these
settings on every push.
Upgrading
git pull and docker compose up -d (or ./update.sh). Containers are recreated once with the new security settings; data volumes are untouched.
Full history in CHANGELOG.md.