[Bug] Worker nodes get providers.swarm in Traefik config → endless "not a swarm manager" retry loop floods logs until disk fills
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 37.4k
- Forks
- 3k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 73
Description
Summary
On a Docker Swarm cluster where Traefik runs as the per-node standalone container, Dokploy writes a default traefik.yml with providers.swarm enabled to every node — including worker nodes — even though the Swarm provider can never work on a non-manager. The resulting infinite retry loop floods Traefik's container log and the daemon journal/syslog until disk fills.
Environment
- Dokploy server
dokploy/dokploy:v0.30.0(also verified on latest upstreamded23bb, Aug 17 2026) - Docker Swarm cluster, server running as a Swarm service on the manager node; 1 manager + 2 workers
- Traefik
traefik:v3.6.7as a standalonedokploy-traefikcontainer on each node (verified viadocker inspect; not a Swarm service)
To Reproduce
- Stand up a Dokploy Swarm cluster with ≥1 worker node; add the worker in Dokploy.
cat /etc/dokploy/traefik/traefik.ymlon the worker →providers.swarmis present.docker logs -f dokploy-traefikon the worker → repeated
Error response from daemon: This node is not a swarm manager. Worker nodes can't be used to view or modify cluster state.while retrying forever (backoff ~0.6–3s).- Leave it running; the container json log (and the daemon journal/
syslog) grow without bound.
Expected behavior
The Swarm provider should not be enabled (or Traefik not scheduled) on nodes that cannot serve the Swarm API, so no guaranteed-failure retry loop and no unbounded log growth.
Current behavior
Observed on a real cluster: worker dokploy-traefik container logs reached 1.5 G each (two workers), and syslog.1 reached 2.5 G (~17,800 repetitions), ≈ 5.5 G before mitigation.
Each failed poll is written twice: into the container json log and into the daemon journal (→ syslog).
Root cause (verified in source)
packages/server/src/setup/traefik-setup.ts:
-
getDefaultTraefikConfig()(:253) — its production branch (around:265) emitsproviders.swarmunconditionally:: { swarm: { exposedByDefault: false, watch: true }, docker: { exposedByDefault: false, watch: true, network: "dokploy-network" } }There is no
isManager/node-role check in this path. -
getDefaultServerTraefikConfig()(:~322) does the same (providers.swarmat:326). -
createDefaultTraefikConfig()(:377) writes that config to<MAIN_TRAEFIK_PATH>/traefik.yml(i.e./etc/dokploy/traefik/traefik.yml), early-returning only if the file already exists. It runs at every Dokploy bootstrap on any node running the Dokploy app/agent (apps/dokploy/server/server.ts:35,apps/dokploy/setup.ts:27). -
The standalone Traefik deployed per node
initializeStandaloneTraefik()(:35) has no placement constraint and binds the local socket plus that config.
Contrast: the Swarm-service variant initializeTraefikService() (:150+) does correctly constrain Traefik to managers:
Placement: { Constraints: ["node.role==manager"] },
So the defect is specific to the standalone per-node path: it neither constrains Traefik to the manager nor strips the Swarm provider from worker configs. On a worker, GET /services is a manager-only API, so the loop is guaranteed and permanent.
Suggested fix
Make Swarm-provider inclusion role-aware, least→most invasive:
- In
createDefaultTraefikConfig/getDefaultTraefikConfig, detect whether the local node is a Swarm manager (e.g.docker info→Swarm.LocalNodeState+Swarm.ControlAvailable) and omitproviders.swarmwhen not a manager. - Apply a
node.role==managerplacement constraint to standalone Traefik ininitializeStandaloneTraefikwhen in Swarm mode (mirrors the already-correctinitializeTraefikService). - Add a per-node/settings toggle for which providers Traefik enables, defaulting sensibly per node role.
Related
Different from — but in the same Swarm/Traefik/log space: #4835 (daemon CPU from stale log readers), #4519 (database deploy failing with this error), #3516 (database backup on worker).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/server/src/setup/traefik-setup.ts, especially getDefaultTraefikConfig(), getDefaultServerTraefikConfig(), createDefaultTraefikConfig(), initializeStandaloneTraefik(), and initializeTraefikService(). Compare the existing manager placement constraint with the standalone path, then inspect apps/dokploy/server/server.ts and apps/dokploy/setup.ts for bootstrap behavior. Done means worker nodes no longer enable or run a Swarm provider in the standalone path, while manager behavior remains functional and the retry loop is prevented.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, typescript
- Domain
- devops, infrastructure
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 72/100