Help with CloudFlare SSL certificate config

1. Caddy version (caddy version):

Version 2

2. How I run Caddy:

I am using the Docker Image that is bundled with Hasura

a. System environment:

b. Command:

paste command here

c. Service/unit/compose file:

paste full file contents here

d. My complete Caddyfile or JSON config:

    graph.estratega.ec {
       reverse_proxy graphql-engine:8080
       transport http {
       tls /root/estratega.com.pem /root/estratega.com.key
       }
    }

    graph.telefonia.grupoviteri.com {
       reverse_proxy graphql-telefonia:8080
       tls /root/grupoviteri.com.pem /root/grupoviteri.com.key

    } 

e. Docker-Compose File

version: '3.6'
services:
  graphql-engine:
    image: hasura/graphql-engine:v1.3.3
    restart: always
    environment:
      # database url to connect
      HASURA_GRAPHQL_DATABASE_URL: 
       ## enable the console served by server
      HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set "false" to disable console
      ## enable debugging mode. It is recommended to disable this in production
      HASURA_GRAPHQL_DEV_MODE: "true"
      ## uncomment next line to set an admin secret
      
    command:
    - graphql-engine
    - serve
  caddy:
    image: caddy/caddy
    depends_on:
    - "graphql-engine"
    restart: always
    ports:
    - "80:80"
    - "443:443"
    volumes:
    - ./Caddyfile:/etc/caddy/Caddyfile
    - ./caddy_certs:/root/
  graphql-telefonia:
    image: hasura/graphql-engine:v1.3.3
    restart: always
    environment:
      HASURA_GRAPHQL_DATABASE_URL: 
      HASURA_GRAPHQL_ENABLE_CONSOLE: "true"
      HASURA_GRAPHQL_DEV_MODE: "true"
    command:
    - graphql-engine
    - serve
volumes:
  db_data:
  caddy_certs:

Certificates are in /caddy_certs

3. The problem I’m having:

I’ve been testing and it seems I did not have a volume attached to the docker image thus Lets Encrypt just banned the cert generation.

I am behind cloudlfare so I want to use their SSL certicicates so everything is easier.

However, it is not working and I have no idea if this config would be correct. I am not too sure if this config is for version one or two.

4. Error messages and/or full log output:

caddy_1              | 2021/02/06 23:25:22 [INFO][cache:0xc00001b040] Started certificate maintenance routine
caddy_1              | 2021/02/06 23:25:22 [INFO][cache:0xc00001b040] Stopped certificate maintenance routine
caddy_1              | run: loading initial config: loading new config: loading http app module: provision http: getting tls app: loading tls app module: provision tls: loading certificates: tls: failed to find any PEM data in certificate input
caddy_1              | {"level":"info","ts":1612658931.936018,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
caddy_1              | {"level":"info","ts":1612658931.9454453,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["[::1]:2019","127.0.0.1:2019","localhost:2019"]}

5. What I already tried:

Read all the docs and forum.

6. Links to relevant resources:

Which version exactly? It matters.

The syntax isn’t right here. transport is a subdirective of reverse_proxy, so you would need to use braces around it.

Also, tls is not a subdirective of transport, it’s a regular directive, and should not be inside the braces of another directive.

Your second site is more correct.

Yeah, Caddy v1 had proxy, v2 has reverse_proxy – that’s one telling difference usually.

Are you sure your files are actually mounted in your container? You didn’t share your docker-compose file or docker commands. Please fill out the template completely!

Are you sure your files are actually mounted in your container? You didn’t share your docker-compose file or docker commands. Please fill out the template completely!

Hi, thanks! I have just updated the question.

I updated this but still no luck.

You should be using caddy, not caddy/caddy. And you should be specifying a label, not using latest. See Docker Hub

Since root is the home directory in the container, I would recommend using a different directory for this mount. Maybe /certs.

Also, please remember to persist /data, even if you’re providing your own certs, because Caddy stores information in there that should not be lost between restarts. See Docker Hub

What does the content of your certificate file look like? (Don’t worry, there’s no secret info in the certificate, since it’s sent to browsers on every request – but don’t share the private key)

That error message is pretty clear - it wasn’t able to load the certificate from file, likely because the data wasn’t formatted correctly.

Hello,

Done, I am now using version 2.3.0.

I’ve made this change and changed the Caddyfile accordingly.

This is my new configuration (excluding redundant config):

    caddy:
        image: caddy:2.3.0
        depends_on:
        - "graphql-engine"
        restart: always
        ports:
        - "80:80"
        - "443:443"
        volumes:
        - ./Caddyfile:/etc/caddy/Caddyfile
        - ./caddy_certs:/certs
        - ./caddy_data:/data
        - ./caddy_config:/config

    volumes:
      db_data:
      caddy_certs:
      caddy_data:
      caddy_config:
graph.estratega.ec {
   reverse_proxy graphql-engine:8080
  tls /certs/estratega.ec.pem /certs/estratega.ec.key
}

this domain is now working

graph.telefonia.grupoviteri.com {
    reverse_proxy graphql-telefonia:8080
    tls /certs/grupoviteri.com.pem /certs/grupoviteri.com.key
 }

this one is not.

This is the new log output:

    {"level":"info","ts":1612660922.0382142,"logger":"tls.cache.maintenance","msg":"stopped background certificate maintenance","cache":"0xc0001a7110"}
    {"level":"warn","ts":1612660922.0384371,"logger":"tls.issuance.acme.acme_client","msg":"HTTP request failed; retrying","url":"https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA","error":"performing request: Post \"https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA\": context canceled"}
    {"level":"warn","ts":1612660922.040961,"logger":"tls.issuance.acme.acme_client","msg":"HTTP request failed; retrying","url":"https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA","error":"performing request: Post \"https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA\": context canceled"}
    {"level":"error","ts":1612660922.0413966,"logger":"tls.issuance.acme.acme_client","msg":"deactivating authorization","identifier":"graph.telefonia.grupoviteri.com","authz":"https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA","error":"request to https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA failed after 1 attempts: context canceled"}
    {"level":"error","ts":1612660922.0418832,"logger":"tls.obtain","msg":"will retry","error":"[graph.telefonia.grupoviteri.com] Obtain: [graph.telefonia.grupoviteri.com] solving challenges: [graph.telefonia.grupoviteri.com] checking authorization status: request to https://acme.zerossl.com/v2/DV90/authz/c8Cz8ictw24PNnHzXAJnNA failed after 1 attempts: context canceled (order=https://acme.zerossl.com/v2/DV90/order/8d0qeDLJl7vIxfQPiqGLdQ) (ca=https://acme.zerossl.com/v2/DV90)","attempt":1,"retrying_in":60,"elapsed":74.861158505,"max_duration":2592000}
    {"level":"info","ts":1612660922.042313,"logger":"tls.obtain","msg":"releasing lock","identifier":"graph.telefonia.grupoviteri.com"}
    {"level":"error","ts":1612660922.0428808,"logger":"tls.obtain","msg":"unable to unlock","identifier":"graph.telefonia.grupoviteri.com","lock_key":"issue_cert_graph.telefonia.grupoviteri.com","error":"remove /data/caddy/locks/issue_cert_graph.telefonia.grupoviteri.com.lock: no such file or directory"}
    {"level":"error","ts":1612660922.0434127,"logger":"tls","msg":"job failed","error":"graph.telefonia.grupoviteri.com: obtaining certificate: context canceled"}
    {"level":"info","ts":1612660922.5391304,"logger":"admin","msg":"stopped previous server"}
    {"level":"info","ts":1612660922.5399132,"msg":"shutdown done","signal":"SIGTERM"}
    {"level":"info","ts":1612661002.9037538,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
    {"level":"info","ts":1612661002.9138587,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["[::1]:2019","127.0.0.1:2019","localhost:2019"]}
    {"level":"warn","ts":1612661002.917027,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [cloudflare origin certificate *.grupoviteri.com grupoviteri.com]: no URL to issuing certificate"}
    {"level":"warn","ts":1612661002.9204423,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [cloudflare origin certificate *.estratega.ec estratega.ec]: no URL to issuing certificate"}
    {"level":"info","ts":1612661002.9225943,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc00021f730"}
    {"level":"info","ts":1612661002.9233167,"logger":"http","msg":"skipping automatic certificate management because one or more matching certificates are already loaded","domain":"graph.estratega.ec","server_name":"srv0"}
    {"level":"info","ts":1612661002.9241424,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
    {"level":"info","ts":1612661002.9247243,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["graph.telefonia.grupoviteri.com"]}
    {"level":"info","ts":1612661002.9284282,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
    {"level":"info","ts":1612661002.92857,"msg":"serving initial configuration"}
    {"level":"info","ts":1612661002.9308183,"logger":"tls.obtain","msg":"acquiring lock","identifier":"graph.telefonia.grupoviteri.com"}
    {"level":"info","ts":1612661002.9312532,"logger":"tls.obtain","msg":"lock acquired","identifier":"graph.telefonia.grupoviteri.com"}
    {"level":"info","ts":1612661002.9363582,"logger":"tls","msg":"cleaned up storage units"}
    {"level":"info","ts":1612661002.968607,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["graph.telefonia.grupoviteri.com"]}
    {"level":"info","ts":1612661002.9687939,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["graph.telefonia.grupoviteri.com"]}
    {"level":"info","ts":1612661003.3633466,"logger":"tls.issuance.acme","msg":"waiting on internal rate limiter","identifiers":["graph.telefonia.grupoviteri.com"]}
    {"level":"info","ts":1612661003.363665,"logger":"tls.issuance.acme","msg":"done waiting on internal rate limiter","identifiers":["graph.telefonia.grupoviteri.com"]}
    {"level":"info","ts":1612661004.7789128,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"graph.telefonia.grupoviteri.com","challenge_type":"http-01","ca":"https://acme.zerossl.com/v2/DV90"}
    {"level":"error","ts":1612661305.9727342,"logger":"tls.obtain","msg":"will retry","error":"[graph.telefonia.grupoviteri.com] Obtain: [graph.telefonia.grupoviteri.com] solving challenges: [graph.telefonia.grupoviteri.com] authorization took too long (order=https://acme.zerossl.com/v2/DV90/order/rc1hR6nojoWJ8sXzNV2cgw) (ca=https://acme.zerossl.com/v2/DV90)","attempt":1,"retrying_in":60,"elapsed":303.040599147,"max_duration":2592000}
    {"level":"info","ts":1612661366.455384,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"graph.telefonia.grupoviteri.com","challenge_type":"http-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
    {"level":"error","ts":1612661366.8237796,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"graph.telefonia.grupoviteri.com","challenge_type":"http-01","status_code":400,"problem_type":"urn:ietf:params:acme:error:tls","error":"Fetching https://graph.telefonia.grupoviteri.com/.well-known/acme-challenge/sGSCLZK9LyY83Rp9YKDs6NyZ1ywEVfjwysoHpNUzASY: remote error: tls: handshake failure"}
    {"level":"error","ts":1612661366.8240466,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"graph.telefonia.grupoviteri.com","error":"authorization failed: HTTP 400 urn:ietf:params:acme:error:tls - Fetching https://graph.telefonia.grupoviteri.com/.well-known/acme-challenge/sGSCLZK9LyY83Rp9YKDs6NyZ1ywEVfjwysoHpNUzASY: remote error: tls: handshake failure","order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/17953673/235317998","attempt":1,"max_attempts":3}
    {"level":"info","ts":1612661367.9577157,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"graph.telefonia.grupoviteri.com","challenge_type":"tls-alpn-01","ca":"https://acme-staging-v02.api.letsencrypt.org/directory"}
    {"level":"error","ts":1612661368.3394115,"logger":"tls.issuance.acme.acme_client","msg":"challenge failed","identifier":"graph.telefonia.grupoviteri.com","challenge_type":"tls-alpn-01","status_code":400,"problem_type":"urn:ietf:params:acme:error:tls","error":"remote error: tls: handshake failure"}
    {"level":"error","ts":1612661368.3396258,"logger":"tls.issuance.acme.acme_client","msg":"validating authorization","identifier":"graph.telefonia.grupoviteri.com","error":"authorization failed: HTTP 400 urn:ietf:params:acme:error:tls - remote error: tls: handshake failure","order":"https://acme-staging-v02.api.letsencrypt.org/acme/order/17953673/235318017","attempt":2,"max_attempts":3}
    {"level":"info","ts":1612661370.630251,"logger":"tls.issuance.acme.acme_client","msg":"trying to solve challenge","identifier":"graph.telefonia.grupoviteri.com","challenge_type":"http-01","ca":"https://acme.zerossl.com/v2/DV90"}

Please use ``` on the lines before and after your config to use code formatting when posting them to the forums, instead of using block quotes. It preserves whitespace and syntax correctly.

So seeing *.grupoviteri.com in here tells me that this is a wildcard certificate. The problem is that you’re use two subdomains. Wildcard certs are only valid for the next subdomain level down. You would need a wildcard certificate for *.telefonia.grupoviteri.com.

Because graph.telefonia.grupoviteri.com is not a match for the certificate provided, Caddy is trying to have a certificate issued for that domain. That’s all the ZeroSSL log messages you’re seeing.

Thanks for the heads up! I will.

I have updated the certificate to add *.telefonia.grupoviteri.com but still no luck.

Here is the new log:

{"level":"info","ts":1612662922.0696628,"logger":"tls.cache.maintenance","msg":"stopped background certificate maintenance","cache":"0xc0002565b0"}
{"level":"warn","ts":1612662922.0713215,"logger":"tls.issuance.acme.acme_client","msg":"HTTP request failed; retrying","url":"https://acme.zerossl.com/v2/DV90/authz/BsFR5NQPdmnPtg7U3RGMZw","error":"performing request: Post \"https://acme.zerossl.com/v2/DV90/authz/BsFR5NQPdmnPtg7U3RGMZw\": context canceled"}
{"level":"error","ts":1612662922.071781,"logger":"tls.issuance.acme.acme_client","msg":"deactivating authorization","identifier":"graph.telefonia.grupoviteri.com","authz":"https://acme.zerossl.com/v2/DV90/authz/BsFR5NQPdmnPtg7U3RGMZw","error":"request to https://acme.zerossl.com/v2/DV90/authz/BsFR5NQPdmnPtg7U3RGMZw failed after 1 attempts: context canceled"}
{"level":"info","ts":1612662922.072057,"logger":"tls.obtain","msg":"releasing lock","identifier":"graph.telefonia.grupoviteri.com"}
{"level":"error","ts":1612662922.072419,"logger":"tls.obtain","msg":"unable to unlock","identifier":"graph.telefonia.grupoviteri.com","lock_key":"issue_cert_graph.telefonia.grupoviteri.com","error":"remove /data/caddy/locks/issue_cert_graph.telefonia.grupoviteri.com.lock: no such file or directory"}
{"level":"error","ts":1612662922.0726774,"logger":"tls","msg":"job failed","error":"graph.telefonia.grupoviteri.com: obtaining certificate: [graph.telefonia.grupoviteri.com] Obtain: [graph.telefonia.grupoviteri.com] solving challenges: [graph.telefonia.grupoviteri.com] context canceled (order=https://acme.zerossl.com/v2/DV90/order/Sr7YpNP4Z1vCvvscTLqXCQ) (ca=https://acme.zerossl.com/v2/DV90)"}
{"level":"info","ts":1612663043.355046,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":"caddyfile"}
{"level":"info","ts":1612663043.3688407,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","enforce_origin":false,"origins":["localhost:2019","[::1]:2019","127.0.0.1:2019"]}
{"level":"warn","ts":1612663043.3773942,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [cloudflare origin certificate *.grupoviteri.com *.telefonia.grupoviteri.com grupoviteri.com]: no URL to issuing certificate"}
{"level":"warn","ts":1612663043.3779297,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [cloudflare origin certificate *.estratega.ec estratega.ec]: no URL to issuing certificate"}
{"level":"info","ts":1612663043.3800788,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc000221a40"}
{"level":"info","ts":1612663043.3828874,"logger":"http","msg":"skipping automatic certificate management because one or more matching certificates are already loaded","domain":"graph.telefonia.grupoviteri.com","server_name":"srv0"}
{"level":"info","ts":1612663043.3830316,"logger":"http","msg":"skipping automatic certificate management because one or more matching certificates are already loaded","domain":"graph.estratega.ec","server_name":"srv0"}
{"level":"info","ts":1612663043.3831067,"logger":"http","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
{"level":"info","ts":1612663043.3888478,"logger":"tls","msg":"cleaned up storage units"}
{"level":"info","ts":1612663043.3939857,"msg":"autosaved config","file":"/config/caddy/autosave.json"}
{"level":"info","ts":1612663043.3941538,"msg":"serving initial configuration"}

Seems like it should work now.

Maybe it is a CloudFlare config?
I am getting:
ERR_SSL_VERSION_OR_CIPHER_MISMATCH

Try with curl -v to make the request - browsers often give misleading messages.

Thank you so much!

What was the fix?

1 Like

Hello, I created a new cert for *.telefonia.grupoviteri.com but I also stopped using Cloudflare SSL for that domain.

The reason being, is that originally I wanted this domain only to be accessible via a private IP, but Caddy would try to get a certificate which would not resolve (due to being pointed to a private ip address) this I why I exposed this server to the internet when I asked this question.

However, after creating an SSL certificate for *.telefonia.grupoviteri.com allowed Caddy to stop complaining and I switched back to the private IP address. So all domains work as expected (one public and one private) :smiley:

2 Likes

This topic was automatically closed after 30 days. New replies are no longer allowed.