Uploaded custom certificates are not loaded by Traefik because file provider does not recurse into certificates/ subdirectory
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 37.4k
- Forks
- 3k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 73
Description
To Reproduce
- Create an application in Dokploy and add a domain (e.g. example.com) with HTTPS: ON and Certificate: Let's Encrypt. Confirm it gets a valid LE cert.
- Go to Certificates (top-level) -> Add Certificate and paste a valid Cloudflare Origin CA certificate + private key covering example.com (and/or *.example.com). Save.
- Go back to the application -> Domains -> edit example.com and change Certificate to None. Save.
- Restart Traefik (
docker restart $(docker ps -q -f name=traefik)) to be safe. - From outside the server, inspect the cert served by the origin:
echo | openssl s_client -servername example.com -connect <ORIGIN-IP>:443 2>/dev/null \
| openssl x509 -noout -issuer -dates
Current vs. Expected behavior
Expected: Traefik serves the uploaded Cloudflare Origin CA certificate via SNI for example.com.
Actual: Traefik continues to serve the previously-issued Let's Encrypt certificate (or fails over to the default cert). The uploaded cert is never presented, even though it appears in the Dokploy UI under Certificates.
Root cause: Dokploy writes uploaded certificates to:
/etc/dokploy/traefik/dynamic/certificates/<cert-id>/certificate.yml
But the Traefik file provider is configured as:
providers:
file:
directory: /etc/dokploy/traefik/dynamic
watch: true
Traefik's file provider with directory: does not recurse into subdirectories, so certificates/<cert-id>/certificate.yml is never loaded. The cert PEM files exist on disk but are never registered with Traefik's TLS store, so SNI matching never picks them up.
Additionally, the websecure entrypoint has a default certResolver: letsencrypt, and router YAMLs generated by Dokploy include tls.certResolver: letsencrypt explicitly. Even after setting Certificate: None on the domain, the regenerated router YAML may still contain the resolver line, which takes precedence over SNI-matched certs.
Workaround that fixes it:
sudo cp /etc/dokploy/traefik/dynamic/certificates/<cert-id>/certificate.yml \
/etc/dokploy/traefik/dynamic/zz-<name>-cert.yml
docker restart $(docker ps -q -f name=traefik)
Suggested fixes:
- Write the certificate.yml registration file directly into /etc/dokploy/traefik/dynamic/ (not a subdirectory), while keeping the PEM files wherever convenient.
- Or use Traefik's filename: provider entries pointing to the subdir paths.
- Ensure router YAMLs generated by Dokploy fully remove tls.certResolver when the domain is set to Certificate: None.
Provide environment information
- OS: Ubuntu 22.04 (also reproduced on 20.04)
- Arch: x86_64
- Dokploy version: 0.29.4
- VPS Provider: Hetzner
- Application: Next.js frontend (also affects Docker Compose services)
Which area(s) are affected? (Select all that apply)
Traefik
Are you deploying the applications where Dokploy is installed or on a remote server?
Same server where Dokploy is installed
Additional context
Followed the official docs at https://docs.dokploy.com/docs/core/domains/cloudflare (Using Cloudflare's Origin CA section).
Will you send a PR to fix it?
No
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 by tracing how Dokploy generates Traefik configuration under /etc/dokploy/traefik/dynamic/, especially certificates//certificate.yml and the generated router YAMLs. Reproduce with the provided openssl SNI check and inspect whether the file provider loads the certificate and whether tls.certResolver remains after Certificate: None. Done means the uploaded certificate is served for the domain without the unwanted resolver.
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
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100