Releases: heyvaldemar/zammad-traefik-letsencrypt-docker-compose
Release list
v1.7.6
Changed
- 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.
ghcr.io/zammad/zammad:7.1.3moved toghcr.io/zammad/zammad:7.2.0. 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 7.1.3 -> 7.2.0
Verdict: SAFE TO APPLY — the compose file's pinned Elasticsearch (8.19.20) already satisfies the new minimum the notes require, and no other breaking change needs host action beyond an index rebuild and a routing-scheme check.
Breaking changes
- Elasticsearch 7 is no longer supported, 8.15 is the new minimum. "the supported range is now Elasticsearch 8.15 up to, but not including, 10 ... Upgrade the Elasticsearch installation to 8.15 or newer before updating to Zammad 7.2." This compose file already pins
elasticsearch:8.19.20, so it satisfies the requirement — but this is exactly the class of mismatch this review watches for, and it is fine here only because the pin was already compliant. - Reverse proxy scheme handling changed. "The Docker images rebuild their nginx configuration from the shipped one on every start, so the change applies to them automatically ... If Zammad was reachable over HTTPS only because the proxy in front of it sent Forwarded or X-Forwarded-Ssl ... configure the scheme in Zammad's own web server instead: set NGINX_SERVER_SCHEME=https." This compose file already sets
NGINX_SERVER_SCHEME: httpsexplicitly on thezammadservice, and Traefik terminates TLS in front of it, so this should be unaffected — but verify after upgrade that login still works, since the notes also recordFixes #6305 - CSRF token verification failure during login after updating to Zammad 7.1as a related regression that was still being patched in this range. - Elasticsearch index gains a new field. "The 'Suggested searches' shortcut menu added to the Knowledge Base search introduced a new publication_state field ... Existing indices do not contain the field ... Rebuild the search index after the update:
zammad run rake zammad:searchindex:rebuild" - Self-links rejected, link-add endpoint now reports failures correctly. "A rejected link now answers 422 Unprocessable Content ... Update integrations that treat every response of the endpoint as a success." Only relevant if something automates
/api/v1/links/add. - Out-of-range dates now rejected on write. "Saving a value like 20026-08-18 now fails with the validation error 'must have a year between 1 and 9999' ... correct existing out-of-range dates to make the affected records findable again." Only actionable if such data exists.
- Stricter default CSP (
frame-ancestors 'self'). "Setups that previously re-enabled embedding by overriding the X-Frame-Options header at the reverse proxy are blocked again by it." Only relevant if Zammad is iframe-embedded elsewhere.
Variables
None renamed or newly required for this compose file. (The commit log mentions a MALLOC_ARENA_MAX/ZAMMAD_RUBY_MALLOC_ARENA_MAX naming fix, but that variable is not set in this compose file or .env.example, so nothing to change here.)
Data and dependencies
- Elasticsearch minimum raised to 8.15 (see above) — already satisfied by the pinned
8.19.20. - No database version requirement changes noted for PostgreSQL.
- No changed ports, volumes, or paths in the notes.
Before applying
- Take the routine backup before any Zammad upgrade (the
backupservice in this stack, or an equivalent snapshot). - After the upgrade completes, run:
zammad run rake zammad:searchindex:rebuildto pick up the newpublication_statefield. - Confirm login still works post-upgrade given the scheme-handling change and the
#6305CSRF fix landing in this range; this stack'sNGINX_SERVER_SCHEME: httpssetting is already correct, so this is a smoke test, not a config change. - If any user- or organization-facing dates were ever set outside the year 1–9999, expect saves on those records to start failing with a validation error; find and correct them if so.
WHAT THE IMAGES THEMSELVES DIFFER IN
- New
GEM_PATH,LD_PRELOAD(libjemalloc.so.2), andZAMMAD_DOCKER=trueenvironment defaults, and an updatedPATHprepending/usr/local/bundle/ruby/current/bin. These line up with the commit log entry "Maintenance: switch Dockerfile to jemalloc as recommended by Rails" — an internal memory-allocator change, not something this compose file overrides or needs to react to. No action required; noted for completeness since it is a genuine image-level difference the notes only partially describe (jemalloc is mentioned; theGEM_PATH/PATH/ZAMMAD_DOCKERenv additions are not).
Notes read
- Commit log (compare API) between
7.1.3and7.2.0forzammad/zammad— no dedicated GitHub release notes exist for these tags. BREAKING_CHANGES.md, sections "Upcoming releases", "7.2", and "7.1" (the range being moved through); earlier sections (7.0 and below) were skipped as out of range.
v1.7.5
Security
postgres:17-alpinewas rebuilt upstream; the pin moved fromsha256:f02121de6f74…tosha256:b0f9560a2de0…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.traefik:3.7was rebuilt upstream; the pin moved fromsha256:1c32e7c36820…tosha256:24841fe2de73…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.
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.
v1.7.4
Security
redis:7.4was rebuilt upstream; the pin moved fromsha256:71da9275c5f3…tosha256:c6eabf748fc7…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.memcached:1.6-alpinewas rebuilt upstream; the pin moved fromsha256:69ecd3c5701c…tosha256:9e4de012dc60…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.
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.
v1.7.3
Security
postgres:17-alpinewas rebuilt upstream; the pin moved fromsha256:18cfe3ef5e68…tosha256:f02121de6f74…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.memcached:1.6-alpinewas rebuilt upstream; the pin moved fromsha256:c29847751abb…tosha256:69ecd3c5701c…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.traefik:3.7was rebuilt upstream; the pin moved fromsha256:f86a2cab1b5c…tosha256:1c32e7c36820…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.
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.
v1.7.2
The restore roundtrip loaded the dump into a throwaway database of the same image, counted the tables, and passed if there were more than ten.
Ten is a number written in the test. It passes for a dump that restored a fifth of the schema, and it keeps passing as the application grows and the real number moves away from it.
The running stack knows how many tables it has. Asking it means the comparison stays true as the schema changes, and a partial restore fails instead of being blessed by a threshold nobody revisits. When the counts differ, the failure names the tables that did not come back.
A live schema the test cannot read is a failure rather than a pass: this check must not be able to succeed by failing to look.
Upgrading: git pull or ./update.sh. Nothing in the running stack changes — this is the test suite.
v1.7.1
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.7.0
Fixed
- A backup interrupted halfway no longer looks like a finished one. The
backup script writes the dump and the file archive under a.partialname
and renames each only once its write has succeeded. It already renamed a
failed file to.failed, but that branch only runs if the shell lives long
enough to reach it — a container stopped mid-dump does not, and left a
truncated file under exactly the name a restore would pick. The rest of the
fleet was fixed for this on 4 September; this repository was missed, because
its loop lives inscripts/backup.shrather than in the compose file. - Pruning now removes
.partialand.failedfiles too, and no longer
depends on a glob expanding.
Added
- Backup and restore tested end to end, nine assertions against the live
stack, driven through the script's own one-shot entrypoints rather than its
daily schedule. The dump is a complete gzip containing real SQL, the file
archive lists, no.partialsurvives a completed cycle, and the dump
restores into a throwaway database built from the same image as the live one
with zero SQL errors and a real schema. - The failure case is exercised, not assumed. A dump pointed at an
unreachable database must be reported as failed, must leave nothing under a
name a restore would choose, and must keep the partial file as.failedfor
diagnosis.
v1.6.0
Added
- A shutdown grace period for PostgreSQL and Redis. Docker stops a container with
SIGTERM and ten seconds, then SIGKILL. That default is not always enough:
PostgreSQL has a checkpoint to write, MariaDB has InnoDB to flush, and Redis
saves its dataset on the way out. Killed halfway, the next start does crash
recovery, and a Redis holding another application's file locks leaves them
behind for a person to clear by hand. Sixty seconds now, overridable per
service with<PREFIX>_STOP_GRACE_PERIODin.env. The backup sidecar is
deliberately left alone: its failure mode is a truncated dump file, which a
longer grace period does not fix.
v1.5.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.
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.4.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.