Setting up Cloudflare with Caddy

1. Caddy version (caddy version):

v2.4.5 h1:P1mRs6V2cMcagSPn+NWpD+OEYUYLIf6ecOa48cFGeUg=

2. How I run Caddy:

Docker.

a. System environment:

Ubuntu 21.04
Docker version 20.10.9, build c2ea9bc
docker-compose version 1.29.2, build 5becea4c

b. Command:

docker-compose up -d

c. Service/unit/compose file:

docker-compose.yml

caddy:
    container_name: caddy
    image: caddy
    build:
      context: ./dockerfile/caddy/
      dockerfile: dockerfile
    ports:
      - "80:80/tcp"
      - "443:443/tcp"
    volumes:
      - type: bind
        source: ./config/caddy/config
        target: /config
      - type: bind
        source: ./config/caddy/Caddyfile
        target: /etc/caddy/Caddyfile
      - type: bind
        source: ./storage/caddy
        target: /data

dockerfile

ROM caddy:builder-alpine AS builder

RUN xcaddy build \
    --with github.com/caddy-dns/cloudflare

FROM caddy:alpine

COPY --from=builder /usr/bin/caddy /usr/bin/caddy

d. My complete Caddyfile or JSON config:

prism.thematrix.dev {
        tls {
                dns cloudflare ABCDE
        }

        reverse_proxy 127.0.0.1:2342
}

3. The problem I’m having:

Compiling with the additional Cloudflare DNS module, it seems Caddy is still registering SSL certificate from Let’sEncrypt for me, but not use the Cloudflare configuration.

4. Error messages and/or full log output:

{"level":"info","ts":1633921310.0677338,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"info","ts":1633921310.0697114,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
{"level":"info","ts":1633921310.0699155,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000248070"}
{"level":"info","ts":1633921310.0699563,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
{"level":"info","ts":1633921310.0699692,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1633921310.0702145,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["prism.thematrix.dev"]}
{"level":"info","ts":1633921310.0702467,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
{"level":"info","ts":1633921310.0702686,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"info","ts":1633921310.0703993,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1633921310.0704076,"msg":"serving initial configuration"}
{"level":"info","ts":1633921310.0705378,"logger":"tls.obtain","msg":"acquiring lock","identifier":"prism.thematrix.dev"}
{"level":"info","ts":1633921310.0714858,"logger":"tls.obtain","msg":"lock acquired","identifier":"prism.thematrix.dev"}
{"level":"info","ts":1633921310.0720735,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["prism.thematrix.dev"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1633921310.0720863,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["prism.thematrix.dev"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"error","ts":1633921316.325541,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"prism.thematrix.dev","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 429 urn:ietf:params:acme:error:rateLimited - Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/"}
{"level":"warn","ts":1633921316.325894,"logger":"tls.issuance.zerossl","msg":"missing email address for ZeroSSL; it is strongly recommended to set one for next time"}
{"level":"info","ts":1633921317.388339,"logger":"tls.issuance.zerossl","msg":"generated EAB credentials","key_id":"aV4lF5ZjT1ehwKH_KdgOGA"}
{"level":"info","ts":1633921318.9381707,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["prism.thematrix.dev"],"ca":"https://acme.zerossl.com/v2/DV90","account":""}
{"level":"info","ts":1633921318.9381888,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["prism.thematrix.dev"],"ca":"https://acme.zerossl.com/v2/DV90","account":""}
{"level":"info","ts":1633921319.5761466,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"prism.thematrix.dev","challenge_type":"dns-01","ca":"https://acme.zerossl.com/v2/DV90"}
{"level":"error","ts":1633921320.0300062,"logger":"tls.issuance.acme.acme_client","msg":"cleaning up solver","identifier":"prism.thematrix.dev","challenge_type":"dns-01","error":"no memory of presenting a DNS record for prism.thematrix.dev (probably OK if presenting failed)"}
{"level":"error","ts":1633921320.3427887,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"prism.thematrix.dev","issuer":"acme.zerossl.com-v2-DV90","error":"[prism.thematrix.dev] solving challenges: presenting for challenge: adding temporary record for zone thematrix.dev.: got error status: HTTP 403: [{Code:10000 Message:Authentication error}] (order=https://acme.zerossl.com/v2/DV90/order/B3L8wC8jeqZM3RHTvIQxHg) (ca=https://acme.zerossl.com/v2/DV90)"}
{"level":"error","ts":1633921320.3428075,"logger":"tls.obtain","msg":"will retry","error":"[prism.thematrix.dev] Obtain: [prism.thematrix.dev] solving challenges: presenting for challenge: adding temporary record for zone thematrix.dev.: got error status: HTTP 403: [{Code:10000 Message:Authentication error}] (order=https://acme.zerossl.com/v2/DV90/order/B3L8wC8jeqZM3RHTvIQxHg) (ca=https://acme.zerossl.com/v2/DV90)","attempt":1,"retrying_in":60,"elapsed":10.271306642,"max_duration":2592000}

caddy adapt --config /etc/caddy/Caddyfile

{"apps":{"http":{"servers":{"srv0":{"listen":[":443"],"routes":[{"match":[{"host":["prism.thematrix.dev"]}],"handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"reverse_proxy","upstreams":[{"dial":"127.0.0.1:2342"}]}]}]}],"terminal":true}]}}},"tls":{"automation":{"policies":[{"subjects":["prism.thematrix.dev"],"issuers":[{"challenges":{"dns":{"provider":{"api_token":"ABCDE","name":"cloudflare"}}},"module":"acme"},{"challenges":{"dns":{"provider":{"api_token":"ABCDE","name":"cloudflare"}}},"module":"zerossl"}]}]}}}}

5. What I already tried:

Googled. Seems everything is doing with the same way.

6. Links to relevant resources:

Hi @y2kbug,

In the logs you posted, it looks like LetsEncrypt rate limited you (too many failed requests) and ZeroSSL is also giving you authorization failures.

I think Code:10000 Message:Authentication error comes from Cloudflare - maybe there’s an issue with your API key?

1 Like

Yeah I have just found out it is due to the API token permission.

According to this page:

These two permissions should be granted:

  • Zone.Zone READ
  • Zone.DNS EDIT

But I wonder why I can still see something about Let’s Encrypt.
There is only one site I have configured in Caddyfile and it uses Cloudflare.

{"level":"info","ts":1633923893.2528377,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"info","ts":1633923893.254878,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
{"level":"info","ts":1633923893.255192,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000455dc0"}
{"level":"info","ts":1633923893.25541,"logger":"http","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
{"level":"info","ts":1633923893.255426,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1633923893.2556336,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["prism.thematrix.dev"]}
{"level":"info","ts":1633923893.2556775,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/data/caddy"}
{"level":"info","ts":1633923893.255703,"logger":"tls","msg":"finished cleaning storage units"}
{"level":"info","ts":1633923893.2559645,"logger":"tls.obtain","msg":"acquiring lock","identifier":"prism.thematrix.dev"}
{"level":"info","ts":1633923893.2563121,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1633923893.25632,"msg":"serving initial configuration"}
{"level":"info","ts":1633923893.2571273,"logger":"tls.obtain","msg":"lock acquired","identifier":"prism.thematrix.dev"}
{"level":"info","ts":1633923893.2577696,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["prism.thematrix.dev"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1633923893.2577813,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["prism.thematrix.dev"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
{"level":"info","ts":1633923894.602586,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"prism.thematrix.dev","challenge_type":"dns-01","ca":"https://acme-v02.api.letsencrypt.org/directory"}
{"level":"info","ts":1633923900.1842225,"logger":"tls.issuance.acme.acme_client","msg":"validations succeeded; finalizing order","order":"https://acme-v02.api.letsencrypt.org/acme/order/234281250/31022304320"}
{"level":"info","ts":1633923901.613348,"logger":"tls.issuance.acme.acme_client","msg":"successfully downloaded available certificate chains","count":2,"first_url":"https://acme-v02.api.letsencrypt.org/acme/cert/03e82bbd1d6da39420aab971441686ff6ed8"}
{"level":"info","ts":1633923901.6142883,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"prism.thematrix.dev"}
{"level":"info","ts":1633923901.6143053,"logger":"tls.obtain","msg":"releasing lock","identifier":"prism.thematrix.dev"}

Cloudflare does not distribute public HTTPS certificates.

You still get the actual certificate itself from LetsEncrypt or ZeroSSL, the Cloudflare module just allows Caddy to use Cloudflare to solve the DNS challenge for one of those issuers.

1 Like

Cloudflare proxy the traffic between my server and users. The public certificate is managed by Cloudflare. The module is used to handle the certificate between Cloudflare and my server (HTTPS strict mode). So does it mean Caddy thinks I still need a public certificate so it keeps asking Let’sEncrypt for it? May I stop this so as to stop distrubing LE?

This is a concept that is very easy to misunderstand.

Yes, Cloudflare reverse-proxies your server for your clients. However, Cloudflare must still connect backwards to your server - through the internet.

Do you need one? No, the system will work without it, and you can configure Caddy to run on HTTP-only.

BUT, just because your DNS points to Cloudflare’s proxy doesn’t mean that people can’t just connect to your origin server directly. Because of this and because of Cloudflare still having to connect to you through the internet, it is important to still have a HTTPS certificate for your origin server!

HOWEVER, that doesn’t mean that you can’t ditch LE/ZeroSSL if you’re opposed to letting Caddy manage those short-lived certs for you. Look into Cloudflare’s “Origin Certificate” - a very long-life certificate trusted only by Cloudflare itself - designed specifically to ensure Cloudflare can validate your origin server without having to worry about getting publicly valid certs for it. You can download it from your Cloudflare dashboard and load it directly into Caddy for the sites Cloudflare is proxying.

You can go one step further and configure Authenticated Origin Pulls to have Caddy validate Cloudflare itself. Fully configured, Caddy will authenticate only Cloudflare itself to connect, Cloudflare will be able to validate your Caddy server, the entire transaction will be encrypted, and you won’t need to worry about public certificates since your valid users will be communicating through the Cloudflare edge.

3 Likes