Skip to content

Releases: heyvaldemar/dozzle-traefik-letsencrypt-docker-compose

v2.0.6

Choose a tag to compare

@heyvaldemar heyvaldemar released this 23 Sep 19:12

Fixed

  • CI had never run the restore script. The test restored with its own
    copy of the commands. The script read DATA_PATH and DATA_BACKUPS_PATH
    from the shell that ran it rather than from .env or the stack, so a path
    set in .env was not the one it listed or cleared, and it cleared with
    rm -rf dir/*, which leaves every dotfile of the newer state in place. It
    now takes every path and name from the running backups container, accepts
    the backup file name as an argument, starts the application again whatever
    happens, and CI runs it: a file written before a backup and deleted after it
    must be back once that backup is restored.

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.

v2.0.5

Choose a tag to compare

@heyvaldemar heyvaldemar released this 21 Sep 18:28

Changed

  • amir20/dozzle:v11.1.0 moved to amir20/dozzle:v11.1.1. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.

Security

  • traefik:3.7 was rebuilt upstream; the pin moved from sha256:1c32e7c36820… to sha256: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.

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 v11.1.0 -> v11.1.1

Verdict: SAFE TO APPLY — a features/bug-fix/performance release with no breaking changes, no new or renamed variables, and no companion-service version dependency (Dozzle only talks to the Docker daemon via the socket proxy already pinned in this compose file).

Breaking changes

  • none found in the notes

Variables

  • none. No entry in the release notes adds, renames or removes an environment variable. DOZZLE_AUTH_OIDC_SCOPES is mentioned as a new feature ("Add DOZZLE_AUTH_OIDC_SCOPES to request extra OIDC scopes") but it is optional and only relevant if OIDC auth is in use; this template uses DOZZLE_AUTH_PROVIDER=simple by default, so it does not apply to the default configuration and needs no .env.example change to stay working.

Data and dependencies

  • none. The proxy contract this template depends on (GET /containers/json, GET /info, EVENTS, PING, VERSION, log streaming, POST denied) is unaffected — none of the fixes ("Harden container store", "Discard a stale host refresh", "Read Podman's health status off the wire") change the set of Docker API endpoints Dozzle calls against the dockerproxy allow-list.
  • No database or cache is involved in this stack; the only companion service Dozzle talks to is dockerproxy, which stays at its current pin (v0.5.0) and is unaffected by this release.

Before applying

  • Bump the pin: DOZZLE_IMAGE_VERSION=v11.1.1 (or update the x-images default in the compose file) and update the accompanying digest.
  • No data migration, no config edit, no manual command. Take the routine backup you'd take before any bump (the backups service already covers /data), then docker compose pull && docker compose up -d.
  • If OIDC auth is in use, review whether DOZZLE_AUTH_OIDC_SCOPES should be set — otherwise skip.

Notes read

  • v11.1.1 (2026-09-20), covering the range v11.1.0...v11.1.1, as pasted above. No UPGRADING/BREAKING_CHANGES/CHANGELOG section was supplied for this range.

v2.0.4

Choose a tag to compare

@heyvaldemar heyvaldemar released this 19 Sep 16:13

Security

  • alpine:3.22 was rebuilt upstream; the pin moved from sha256:365499d9dccb… to sha256:5291449c3df7…. 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.

v2.0.3

Choose a tag to compare

@heyvaldemar heyvaldemar released this 18 Sep 14:52

Security

  • traefik:3.7 was rebuilt upstream; the pin moved from sha256:f86a2cab1b5c… to sha256:1c32e7c36820…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.
  • alpine:3.22 was rebuilt upstream; the pin moved from sha256:14358309a308… to sha256:365499d9dccb…. 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.

v2.0.2

Choose a tag to compare

@heyvaldemar heyvaldemar released this 15 Sep 17:27

Changed

  • amir20/dozzle:v11.0.1 moved to amir20/dozzle:v11.1.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.

v2.0.1

Choose a tag to compare

@heyvaldemar heyvaldemar released this 13 Sep 15:44

Dozzle v11.0.1, and the version line put back in order.

Two releases were cut for this repository within the hour: v2.0.0 for Dozzle v11, and v1.0.2 by fleet triage for v11.0.1 on top of it. Triage took the next version from the latest GitHub release rather than the highest tag, and v2.0.0 was a tag with no release page, so it was invisible to it.

The newer content ended up carrying the lower version. update.sh sorts tags, so it would have offered a deployed host v2.0.0 and then told it that it was current. This release puts the highest tag back on the newest content.

v1.0.2 stays where it is. It was published and somebody may be holding it; deleting a released tag to tidy a number is not worth the one person it breaks. The fix is in fleet-ops, which now follows the highest tag.

And a stale command in a refusal

The hash-generation command that init-auth prints when it refuses to start still named v11.0.0 while the pin had moved to v11.0.1, as did .env.example in three places. A refusal that tells somebody to run a command against a version they are not deploying is a refusal that wastes their evening. Every place that names the version moves with the pin now.

Upgrading: ./update.sh.

v2.0.0

Choose a tag to compare

@heyvaldemar heyvaldemar released this 13 Sep 15:44

Dozzle v11.

A major upstream release: the interface is redesigned, GitHub and OIDC sign-in are added, and the session token changed.

Everyone is signed out once after this upgrade. That is the whole of the user-visible disruption, and it is why this is a major here rather than a minor. Nobody loses access; they log in again.

The authentication contract is unchanged, and that was checked

users.yml is still the access allowlist, password login still works, and docker run amir20/dozzle:v11.0.0 generate still produces the same file, now with two additional optional fields (github and roles) that an existing file does not need. The DOZZLE_ADMIN_USERNAME and DOZZLE_ADMIN_PASSWORD_HASH path is untouched.

The new sign-in providers are opt-in and this template configures none of them, so a deployment that says nothing about GitHub or OIDC behaves exactly as it did.

Every reference to the old version moved with the pin, including the hash-generation command that init-auth prints when it refuses to start. A refusal that tells somebody to run a command against a version they are not deploying is a refusal that wastes their evening.

Upgrading: ./update.sh --allow-major, then log in again.

v1.0.2

Choose a tag to compare

@heyvaldemar heyvaldemar released this 13 Sep 12:36

Changed

  • amir20/dozzle:v11.0.0 moved to amir20/dozzle:v11.0.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 v11.0.0 -> v11.0.1

Verdict: SAFE TO APPLY — the notes contain only new features, UI redesign, and bug fixes; no breaking changes, no new/renamed variables, and no companion service version requirements appear.

Breaking changes

  • none found in the notes

Variables

  • none

Data and dependencies

  • none — no database, cache, or search engine version requirements appear in the notes. The image talks to the Docker daemon through dockerproxy (docker-socket-proxy:v0.5.0), which is unaffected by anything in this release.

Before applying

  • Bump the pin in the compose file: ${DOZZLE_IMAGE_VERSION:-v11.0.0@sha256:...} → v11.0.1@<new digest>, or set DOZZLE_IMAGE_VERSION=v11.0.1 (with the correct digest) in .env if overriding.
  • Update the digest, not just the tag — the compose file pins by tag@sha256, so the new release's actual digest must be substituted.
  • No config, auth, or proxy allow-list changes are needed; init-auth, dockerproxy permissions (CONTAINERS, EVENTS, PING, VERSION, INFO), and all .env values are unaffected by anything in these notes.
  • Restart normally (docker compose up -d); no manual migration or backup step is indicated by the notes.

Notes read

v1.0.1

Choose a tag to compare

@heyvaldemar heyvaldemar released this 11 Sep 03:01

A CI fix. Nothing in the running stack changes.

The socket proxy is watched and scanned like every other pinned image

It was added as a fourth image and then left out of both the daily freshness check and the Trivy matrix. A pin nobody watches goes stale in silence — and this is the one container in the stack holding the Docker socket, which makes it the last image that should be scanned by nobody.

Both now cover it: the freshness job re-resolves its digest against the registry every day, and Trivy scans it on every build alongside the rest.

How it was found

By the fleet conformance rule that asserts every digest-pinned image has a freshness job behind it. The gap was invisible from inside this repository, where every build was green and every check passed — which is the point of running that rule across the fleet rather than inside each template.

Upgrading

./update.sh

No variables changed, no data touched, no manual step.

v1.0.0

Choose a tag to compare

@heyvaldemar heyvaldemar released this 11 Sep 00:26

First release. A production deployment of Dozzle behind Traefik with automatic Let's Encrypt TLS, built to the fleet standard.

Dozzle answers one question — what actually broke? — without a log shipper, a storage backend or an index, because it streams from the Docker daemon rather than collecting anything. It is also the most dangerous container most people deploy, and it ships with two defaults that make it so. This template refuses both.

It will not start without authentication

DOZZLE_AUTH_PROVIDER defaults to none. None means an unauthenticated reader of every log line on the host — connection strings, tokens printed at startup, the bodies of failed requests — handed to whoever finds the hostname. Most compose files in circulation leave it there and publish the result.

Here the init container either builds users.yml from a hash in .env or stops the deploy before anything is listening:

ERROR: Dozzle would start with no authentication.

  There is no /data/users.yml, and DOZZLE_ADMIN_USERNAME and
  DOZZLE_ADMIN_PASSWORD_HASH are not both set in .env.
  …
  Generate the hash, then put both values in .env:

    docker run --rm amir20/dozzle:v10.10.0 generate \
      --name 'Your Name' --email you@example.com \
      --password 'YOUR_STRONG_PASSWORD' yourusername

CI checks both halves on every run: an anonymous request is redirected to a login page, and the generated credentials are accepted by the token endpoint. It also generates that hash by running the command the README gives you, which is how the instruction stays true instead of going stale.

Dozzle never gets the Docker socket

Dozzle's own security page says a container with the socket has root on the host unless restricted, and :ro on the mount is cosmetic — the API is root-equivalent whichever way the file is mounted, because the privilege is in what the API can do, not in who can write the socket file.

So a proxy holds it and forwards only what Dozzle needs, with POST denied. Measured on the stack rather than asserted, and checked every run:

through the proxy answer
GET /containers/json 200
POST /containers/<id>/restart 403
log streaming works

CI also reads the Dozzle container's mount list, because the cheapest way for this to disappear is somebody adding the socket back for an afternoon.

Container actions, if you want them

Restart and stop buttons need Dozzle's setting and the proxy's POST permission, so both live in container-actions.override.yml — setting one without the other silently does nothing, which is worse than either choice made on purpose.

There is no override for DOZZLE_ENABLE_SHELL and will not be. A restart button is a restart button; a browser shell inside the container holding your database credentials is arbitrary command execution on your host, one stolen session cookie away. You have SSH.

Two defects the first CI run found

A literal $$ inside an unquoted heredoc is the shell's PID. The step that writes the test .env substitutes the bcrypt hash with ${{ … }}, so bash saw $$2a$$11$$… — doubled for Compose — inside a heredoc that must stay unquoted. Every $$ became the process id, the hash reached the user file as 24972a2497112497…, and Dozzle refused the password against a file that looked entirely plausible.

/info had to be on the proxy's allow-list. Without it Dozzle reports the host as available: false with no CPU count, no memory figure and no daemon version — and then logs "Connected to Docker" on the very next line. Nothing in CI caught it, because every assertion asked what the proxy answered and the proxy was answering correctly. There is one now that asks what Dozzle made of it.

Also included

Four images pinned by tag@sha256:<digest>, a backup loop that reads its own archive back before naming it a backup, an end-to-end suite requiring users.yml in the archive by name, a restore script, update.sh, cap_drop: ALL on every service, resource limits, and OpenSSF Scorecard. Traefik's idle timeout is an hour rather than 180 seconds, because a live log tail is a response that never ends.

Full documentation: README · CHANGELOG