Releases: heyvaldemar/dify-traefik-letsencrypt-docker-compose
Release list
v1.1.0
Added
- Traefik's timeouts also answer to the fleet-wide names.
TRAEFIK_READ_TIMEOUT,TRAEFIK_WRITE_TIMEOUTandTRAEFIK_IDLE_TIMEOUTnow
set the HTTPS entry point's timeouts here as in every other Traefik template
in the fleet. When set they win;DIFY_REQUEST_TIMEOUTkeep working exactly as before,
and a deployment that sets neither gets the same defaults.
v1.0.5
Fixed
- CI had never run the restore scripts. The test restored with its own
copy of the commands. The scripts read their database name, user, backup
directory and data paths from the shell that ran them rather than from
.envor the stack, so a value set in.envwas not the one they used, they
could only be run by hand, and a failed step left the stopped services
stopped. The data restore cleared withrm -rf dir/*, which leaves every
dotfile of the newer state in place. They now take every value from the running backups container,
accept the backup file name as an argument, start the services again
whatever happens, and CI runs both.
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.
Security
busybox:1.37was rebuilt upstream; the pin moved fromsha256:9db7b59979c3…tosha256:bdf57e528e45…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.
v1.0.4
Security
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.redis:7.4-alpinewas rebuilt upstream; the pin moved fromsha256:520775a41a63…tosha256:858f009f9709…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.postgres:15-alpinewas rebuilt upstream; the pin moved fromsha256:a46e076249ce…tosha256:f7d23353e1b1…. 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.0.3
Security
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.redis:7.4-alpinewas rebuilt upstream; the pin moved fromsha256:ff02b58f971e…tosha256:520775a41a63…. Same version, same tag, a rebuilt base image — the usual shape of a security fix in a base layer.postgres:15-alpinewas rebuilt upstream; the pin moved fromsha256:fe0737ba566a…tosha256:a46e076249ce…. 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.0.2
Fixed
- The vendored-configuration check compared the wrong thing. It captured
each upstream file in a shell variable, and$(...)strips trailing
newlines, so every file differed from its own byte-identical copy by exactly
its last byte. The job runs only on the schedule, so its first real run was
the morning after it shipped, and it failed on all ten files. It downloads to
a file and diffs files now.
Changed
- Re-vendored
ssrf_proxy/squid-agent.conf.templateand
ssrf_proxy/docker-agent-entrypoint.shat Dify 1.17.1, and gave
agent_ssrf_proxythe two variables that release added to it. 1.17.1 gives
the agent's proxy the same optional private-network allowlist the other
proxy already had:DIFY_SSRF_PROXY_ALLOW_PRIVATE_IPSand
DIFY_SSRF_PROXY_ALLOW_PRIVATE_DOMAINS, both empty by default, which is the
containment. This is the change the check exists to catch, and the first one
it caught.
Upgrading
git pull (or ./update.sh), then docker compose up -d. Nothing about the running stack changes: the two re-vendored files are read by the squid proxies at start, and the variables added to agent_ssrf_proxy are empty by default.
v1.0.1
Changed
langgenius/dify-web:1.17.0moved tolanggenius/dify-web:1.17.1. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.langgenius/dify-agent-local-sandbox:1.17.0moved tolanggenius/dify-agent-local-sandbox:1.17.1. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.langgenius/dify-api:1.17.0moved tolanggenius/dify-api:1.17.1. The freshness check reported the lag; the deploy job booted the stack on the new image before this landed.langgenius/dify-agent-backend:1.17.0moved tolanggenius/dify-agent-backend:1.17.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 1.17.0 -> 1.17.1
Verdict: NEEDS ATTENTION — the GitHub release notes for langgenius/dify-agent-backend could not be read (404), so no breaking changes, migrations, or config requirements for this bump can be confirmed from upstream; a manual check is required before applying.
Breaking changes
- Unknown. Release notes were not available (see below). None can be reported or ruled out.
Variables
- None found in the notes (notes unavailable). From the compose/.env.example themselves: no renamed, removed, or newly-required variables are indicated for this bump. Note the existing coupling constraint in
.env.example: "The api, web, local-sandbox and agent-backend images are one Dify release: move them together or not at all."DIFY_AGENT_BACKEND_IMAGE_VERSIONis currently1.17.0alongsideDIFY_API_IMAGE_VERSION=1.17.0,DIFY_WEB_IMAGE_VERSION=1.17.0,DIFY_LOCAL_SANDBOX_IMAGE_VERSION=1.17.0. Bumping onlyagent-backendto1.17.1without moving the other three violates this stated rule.
Data and dependencies
- None found in the notes (notes unavailable).
- No companion service (Postgres, Redis, Weaviate) version is named by the notes, so the compose file's existing pins (
postgres:15-alpine,redis:7.4-alpine,weaviate:1.27.0) cannot be checked against upstream's expectations for this release — check by hand.
Before applying
- Fetch and read the actual 1.17.1 release notes (or changelog/commit log) for
langgenius/dify-agent-backendbefore upgrading; the standard release-notes URL returned 404. - Decide whether
1.17.1foragent-backendis a standalone patch or part of a coordinated Dify1.17.1release; if the latter,DIFY_API_IMAGE_VERSION,DIFY_WEB_IMAGE_VERSION, andDIFY_LOCAL_SANDBOX_IMAGE_VERSIONmust move to matching versions per the template's own "move together or not at all" rule. - Take a database backup (the
backupsservice / manualpg_dump) before any upgrade that touches migration-running containers (api,worker,worker_beat), as a precaution given the notes are unverified. - After confirming compatibility, update
DIFY_AGENT_BACKEND_IMAGE_VERSION(and its digest) in the compose file'sx-imagesblock, not just.env, since that block is the pinned source of truth.
Notes read
- None. GitHub releases for
langgenius/dify-agent-backendcould not be read: HTTP Error 404: Not Found. No other changelog source was provided.
Upstream changes 1.17.0 -> 1.17.1
Verdict: NEEDS ATTENTION — release notes for langgenius/dify-api 1.17.0 and 1.17.1 could not be read (404), so the content of this upgrade is unverified; proceed only after manual review.
Breaking changes
- none found in the notes — the notes themselves could not be retrieved, so this is "not found" due to absence of source material, not a confirmed absence of breaking changes.
Variables
- none found in the notes, for the same reason. The compose file's own defaults still read
DIFY_API_IMAGE_VERSION=1.17.0in .env.example,web,local-sandbox, andagent-backendimages: note the compose file already pinsagent-backendto1.17.1whileapiandwebdefaults remain at1.17.0— the .env.example comment states "The api, web, local-sandbox and agent-backend images are one Dify release: move them together or not at all," so confirm this version skew (api/web/local-sandbox at 1.17.0, agent-backend at 1.17.1) is intentional in the template's tested combination and not an accidental partial bump.
Data and dependencies
- none found in the notes. No information available on whether 1.17.1 requires a Postgres, Redis, or Weaviate version beyond what's already pinned (
postgres:15-alpine,redis:7.4-alpine,weaviate:1.27.0). Since the notes are unavailable, there is no way to confirm the companion services this release expects are the ones the compose file pins — check upstream's own docker-compose.yaml or CHANGELOG for 1.17.1 by hand before applying.
Before applying
- Take a database backup (the
backupsservice / manualpg_dump) before pulling, since migrations run automatically viaMIGRATION_ENABLEDonapi,worker, andworker_beatand are not described as reversible. - Manually check upstream's actual release notes/changelog for
langgenius/dify-api1.17.1 (e.g. on the project's GitHub or Docker Hub tag description) since the automated source returned 404. - Confirm whether
web,local-sandbox, andagent-backendimages should also move to1.17.1to stay a matched set, per the .env.example instruction that these four images are "one Dify release: move them together or not at all." - After confirming compatibility, update the
DIFY_API_IMAGE_VERSIONdefault (and its digest) in the compose file'sx-imagesblock rather than relying on.envoverrides.
Notes read
- Release notes for
langgenius/dify-api1.17.0 and 1.17.1 could not be read: GitHub releases returnedHTTP Error 404: Not Found. No upstream text was available to base this review on; all statements above are inferred from the compose file and .env.example alone.
Upstream changes 1.17.0 -> 1.17.1
Verdict: NEEDS ATTENTION — release notes could not be read, and the compose file itself pins a version mismatch: local-sandbox is still on 1.17.0 while api, agent-backend are already on 1.17.1, and the template's own comment says these images "move together or not at all."
Breaking changes
- none found in the notes — notes were not available (see below)
Variables
- none found in the notes — notes were not available (see below)
Data and dependencies
- none found in the notes — notes were not available (see below)
- Independent of the notes, observed directly in the compose file: the
x-imagesblock pinsapiandagent-backendto1.17.1butlocal-sandbox(langgenius/dify-agent-local-sandbox) is still pinned to1.17.0. The block's own comment states: "The api, web, local-sandbox and agent-backend images are one Dify release: move them together or not at all.".env.examplelikewise still listsDIFY_LOCAL_SANDBOX_IMAGE_VERSION=1.17.0alongsideDIFY_API_IMAGE_VERSION=1.17.0— i.e. neither reference in the repo has been updated consistently for this bump.
Before applying
- Do not apply the
local-sandboxbump to1.17.1in isolation without also confirmingwebmoves with it: the compose file currently showswebstill at1.17.0too. Resolve the whole "api, web, local-sandbox, agent-backend" set to the same release together, not just the one image named in this ticket. - Since the release notes for
langgenius/dify-agent-local-sandbox404, check by hand before applying:- The main
langgenius/difyrepository's release notes for 1.17.1, which normally cover the whole platform including the local sandbox. - The diff between the 1.17.0 and 1.17.1 tags of
langgenius/dify-agent-local-sandboxon GitHub or Docker Hub directly (Dockerfile/CHANGELOG in the image source), since no GitHub Release exists for this repo at these tags. - Whether
DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKENor any other agent/sandbox-facing variable changed shape between versions, since this cannot be confirmed from the notes.
- The main
- Take a database and volume backup before any upgrade in this stack per the existing
backupsservice, as standard practice — not because the notes call for a migration (they don't say anything, since they couldn't be read).
Notes read
- GitHub releases for
langgenius/dify-agent-local-sandboxcould not be read: HTTP Error 404: Not Found. No release notes were available for either 1.17.0 or 1.17.1 of this image.
Upstream changes 1.17.0 -> 1.17.1
Verdict: NEEDS ATTENTION — release notes for langgenius/dify-web could not be read (404), and the compose file as given already pins web at 1.17.0 while api, local-sandbox and agent-backend are pinned at 1.17.1, which the template's own .env.example says must never happen: "The api, web, local-sandbox and agent-backend images are one Dify release: move them together or not at all."
Breaking changes
- Unknown. The release notes source could not be fetched, so nothing can be confirmed either way.
Variables
- none found — no notes to check against. Do not assume
.env.exampleis still complete for 1.17.1; it was written against 1.17.0.
Data and dependencies
- none confirmed from notes (none available).
- Directly observed in the supplied compose file:
web: &web-image ... DIFY_WEB_IMAGE_VERSION:-1.17.0...is out of step withapi,local-sandboxandagent-backend, all pinned to1.17.1. Whate...
v1.0.0
First release. A production deployment of Dify behind Traefik with automatic Let's Encrypt TLS, built to the fleet standard.
Dify is eighteen containers. Most of what this template does is make that number stop mattering.
What it changes about deploying Dify
Nine URL variables become one hostname. Dify reads a separate URL for the console API, the console web, the service API, the app API, the app web, the files endpoint, the trigger URL, the endpoint template and the socket, and ships them all empty. Empty means "guess from the request", which is exactly what breaks behind a reverse proxy: e-mail links to localhost, a Human Input node with nowhere to send anybody, file URLs signed for the wrong origin. Set DIFY_HOSTNAME and all nine follow.
Twelve published defaults become twelve required secrets. Dify's compose file carries working values for its database and Redis passwords, the sandbox key, the plugin daemon key, the inner API key, an agent token whose own name says "for-dev-only", and a Weaviate API key. They are defaults, so they are on the internet. None survives in this repository, and the stack refuses to start without a value for each. .env.example carries the command that generates every one.
Five moving tags become digest pins. Upstream says :latest for busybox, nginx and both squid proxies. Thirteen images are pinned to tag@sha256:<digest> here, and the four that carry the Dify release must agree with each other or CI fails the run.
Dify's own nginx is kept, with Traefik in front. Its routing table has eleven entries and one of them builds the public webhook URL per request, which a static Traefik label cannot express. So the table stays Dify's, the ten configuration files it and the squid proxies read are vendored here, and CI diffs each of them against Dify at the pinned version. A routing change upstream is a red build rather than a deployment quietly serving last release's table.
The sandbox containment is asserted, not assumed. Code that users of the platform write runs in a container whose only way out is a squid proxy. The deploy job reads that container's networks and fails if the routable one is among them.
Proven, not asserted
The deploy job boots from .env.example itself and then requires: the console API answers its setup state through Traefik, the Celery worker completes a scheduled task rather than merely running, the code sandbox answers the api while being on no routable network, a dump and an archive are produced and readable, eight backup and restore scenarios pass, and Dify comes back up on the database the restore test replaced underneath it. All of it ran before this was published, and again in CI on the first push.
Five things only running it finds
Each cost a deploy here so it does not cost one for you:
DIFY_AGENT_SERVER_SECRET_KEYmust be unpadded base64url decoding to exactly 32 bytes.openssl rand -base64 42produces something that looks fine and is rejected.- nginx needs the Debian image: Dify's nginx entrypoint is a bash script and the alpine image has no bash.
conf.dcannot be mounted read-only. The entrypoint renders the routing table into it at boot; a read-only mount makes that write fail silently and nginx comes up listening on nothing while its log looks normal.- Dify's
.envis not a shell script.LOG_DATEFORMAT=%Y-%m-%d %H:%M:%Sis a fine compose value and a syntax error for anything reading the file withsource. - The plugin debugging port upstream publishes has no place in a production deployment.
Getting started
git clone https://github.com/heyvaldemar/dify-traefik-letsencrypt-docker-compose
cd dify-traefik-letsencrypt-docker-compose
docker network create traefik-network
docker network create dify-network
cp .env.example .env && $EDITOR .env
docker compose -f dify-traefik-letsencrypt-docker-compose.yml -p dify up -dFourteen values to fill in, each with its generation command written above it. The api runs the database migrations at start under a Redis lock; the console answers within a few minutes. Then open /install and create the administrator account before anyone else does.
Dify itself is licensed Apache 2.0 with additional terms: a single-tenant self-hosted deployment may be commercial, but a multi-tenant service, or removing the console's logo and copyright, needs a commercial licence from Dify. This repository is the deployment template and is MIT.
Full details in README.md and CHANGELOG.md.