Skip to content

Cloudflare Origin CA: "Certificate: None" does not stop Let's Encrypt for the domain (websecure entrypoint default) #4949

Description

@onlyilkr

To Reproduce

  1. Deploy an application and create a domain with Certificate: Let's Encrypt. Wait until Traefik has issued the certificate, so that an entry for the hostname exists in /etc/dokploy/traefik/dynamic/acme.json.
  2. In the Cloudflare dashboard, go to SSL/TLS > Origin Server > Create Certificate and create an Origin CA certificate covering the domain, for example example.com and *.example.com, valid for 15 years.
  3. In Dokploy, go to Certificates > Add Certificate and paste the Origin Certificate and Private Key, following Using Cloudflare's Origin CA.
  4. Edit the existing domain and change the Certificate field from Let's Encrypt to None.
  5. In Cloudflare, set the SSL/TLS encryption mode to Full (Strict).
  6. On the server, check which certificate Traefik actually serves for that hostname:
echo | openssl s_client -connect 127.0.0.1:443 -servername app.example.com 2>/dev/null \
  | openssl x509 -noout -issuer -enddate

Current vs. Expected behavior

Current behavior

Traefik keeps serving the old Let's Encrypt certificate, not the Origin CA one:

issuer=C = US, O = Let's Encrypt, CN = R12
notAfter=Jul 28 14:45:05 2026 GMT

Traefik also keeps attempting to renew it. Once that certificate expires, Cloudflare returns Error 526 (Invalid SSL certificate) in Full (Strict) mode, even though the Origin CA certificate was uploaded correctly and the domain is set to Certificate: None. Nothing in the UI indicates which certificate is in use, so the setup looks correct while the site is down.

Expected behavior

Setting Certificate: None should stop Let's Encrypt for that domain and let the uploaded Origin CA certificate take over.

Workaround

Removing the hostname's entry from acme.json and restarting Traefik makes the Origin CA certificate take over immediately. On my instance all 13 hostnames switched to CloudFlare Origin SSL Certificate Authority (valid until 2041) with no other change.

Provide environment information

Operating System:
  OS: Ubuntu 24.04.4 LTS
  Arch: x86_64
  Kernel: 6.8.0-136-generic
Dokploy version: v0.29.13
Traefik version: v3.6.7
Docker version: 29.4.1 (Swarm active)
VPS Provider: Hetzner
What applications/services are you trying to deploy?
  Next.js apps, Node APIs, PostgreSQL, MinIO, Redis, Uptime Kuma

Which area(s) are affected? (Select all that apply)

Traefik, Application

Are you deploying the applications where Dokploy is installed or on a remote server?

Same server where Dokploy is installed

Additional context

Two separate mechanisms seem to be involved.

1. Certificate: None only clears the router-level resolver.

The websecure entrypoint carries an instance-wide default that applies to every router which does not define its own TLS block, so the router still falls back to the ACME resolver.

packages/server/src/setup/traefik-setup.ts L286-L298:

websecure: {
  address: `:${TRAEFIK_SSL_PORT}`,
  http3: { advertisedPort: TRAEFIK_HTTP3_PORT },
  ...(process.env.NODE_ENV === "production" && {
    http: { tls: { certResolver: "letsencrypt" } },
  }),
},

The same block exists unconditionally in getDefaultServerTraefikConfig (L344-L354), while Certificate: None only skips the per-router assignment in packages/server/src/utils/traefik/domain.ts L213-L217.

2. Certificate selection favours the old certificate.

Traefik picks the more specific match, so a Let's Encrypt certificate with DNS:app.example.com wins over an Origin CA certificate with DNS:*.example.com. I confirmed this on my instance: hostnames that only the wildcard could match were already served the Origin CA certificate, while hostnames with an exact-match Let's Encrypt entry kept the expired one.

What I could not verify

My ACME challenges were being intercepted by Cloudflare Access, so Traefik could never obtain a new Let's Encrypt certificate. I therefore could not observe whether, on an instance where ACME succeeds, the entrypoint default causes a fresh certificate to be issued for a Certificate: None domain and shadow the Origin CA one. That last link is inferred from Traefik's documented entrypoint-default semantics, not measured. It would be good if someone could confirm it.

Possible directions

  • Do not set certResolver at the entrypoint level, and rely on the per-router value Dokploy already writes for Let's Encrypt domains. Mixed setups keep working, since those routers carry their own tls.certResolver.
  • Or, when a domain is switched away from Let's Encrypt, drop its entry from acme.json.
  • At minimum, document the migration path. I have opened a docs PR for this: docs: document migrating an existing domain to Cloudflare Origin CA website#172

Related to #1839, which asked for Origin CA support before the Certificates feature existed.

Will you send a PR to fix it?

Maybe, need help

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions