getmeli / meli

Platform for deploying static sites and frontend applications easily. Automatic SSL, deploy previews, reverse proxy, and more.
Other
2.4k stars 97 forks source link

Site behind Cloudflare unable to get SSL cert #228

Open tanc opened 3 years ago

tanc commented 3 years ago

I recently set up a site hosted with Meli to use Cloudflare, which appeared to work fine until I restart the Meli docker images. Now every few seconds I'm seeing acme messages in my logs and Caddy is unable to provision a certificate:

meli_1   | {"level":"debug","ts":1621495306.9779413,"logger":"tls.issuance.acme.acme_client","msg":"http request","method":"POST","url":"https://acme.zerossl.com/v2/DV90/authz/O7Gby9Ko2-dfLOFSPmehhw","headers":{"Content-Type":["application/jose+json"],"User-Agent":["Caddy/(devel) CertMagic acmez (linux; amd64)"]},"status_code":200,"response_headers":{"Access-Control-Allow-Origin":["*"],"Cache-Control":["max-age=-1"],"Content-Length":["452"],"Content-Type":["application/json"],"Date":["Thu, 20 May 2021 07:21:46 GMT"],"Link":["<https://acme.zerossl.com/v2/DV90>;rel=\"index\""],"Replay-Nonce":["V8mmwu3M-V8D9SycXKFbaVYFy4eD4TDUE04nZgJ5hdk"],"Retry-After":["5"],"Server":["nginx"],"Strict-Transport-Security":["max-age=15552000"]}}
meli_1   | {"level":"debug","ts":1621495532.5305974,"logger":"http.stdlib","msg":"http: TLS handshake error from 162.158.62.114:13454: no certificate available for 'wildrockmtb.com'"}

And the site behind Cloudflare is complaining about the lack of an SSL certificate.

Is there some way to get the two working together nicely?

tanc commented 3 years ago

I've managed to get the site back up by changing Cloudflare to DNS-only for the domain so it essentially bypasses Cloudflare and goes straight to the Meli server where the certificate was then able to be provisioned.

I'm still seeing a load of these tls requests in the logs though:

"logger":"tls.issuance.acme.acme_client","msg":"http request"

Is that expected?

gempain commented 3 years ago

I've actually never used Cloudflare alongside Meli, so I'm not sure I can be of great help here, but the http log from Caddy looks normal. Does changing to DNS-only impacts your performance ?

tanc commented 3 years ago

Yes there is a slight performance impact but nothing I can't live with. I was trying to get the maximum performance possible and was testing various options including Cloudflare.

It looks like the use of Cloudflare with Caddy requires using the DNS challenge for TLS (from Caddy examples)

tls {
    dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}

I suppose this would mean an additional config option in the site's settings form that then pushed this config for this site. A cloudflare API token field would also be needed somewhere.

tanc commented 3 years ago

This is a really nicely written article about the Caddy and Cloudflare compatibility: https://sammckenzie.be/en/blog/using-caddy-with-cloudflare/

I accept that it may well be beyond the scope of Meli but if it's something you'd consider adding it would be appreciated.

gempain commented 3 years ago

Thanks for the link, very helpful. We'll have a look ! We'll add this to our backlog.

tanc commented 3 years ago

I'm now trying the more manual method of generating the cert on Cloudflare and pasting it into the Meli cert settings but Meli is throwing a 400 error.

The response is:

{"statusCode":400,"path":"/api/v1/sites/883e900d-eae1-42f2-9afa-3c84a270c6da","message":"Invalid body","error":[{"message":"\"domains[0].sslConfiguration\" does not match any of the allowed types","path":["domains",0,"sslConfiguration"],"type":"alternatives.match","context":{"message":"\"domains[0].sslConfiguration.type\" must be [acme]. \"domains[0].sslConfiguration.privateKey\" failed custom validation because Invalid RSA private key","details":[{"message":"\"domains[0].sslConfiguration.type\" must be [acme]","path":["domains",0,"sslConfiguration","type"],"type":"any.only","context":{"valids":["acme"],"label":"domains[0].sslConfiguration.type","value":"manual","key":"type"}},{"message":"\"domains[0].sslConfiguration.privateKey\" failed custom validation because Invalid RSA private key","path":["domains",0,"sslConfiguration","privateKey"],"type":"any.custom","context":{"error":{},"label":"domains[0].sslConfiguration.privateKey","value":"-----BEGIN PRIVATE KEY-----\n[key]\n-----END PRIVATE KEY-----\n","key":"privateKey"}}],"label":"domains[0].sslConfiguration","value":{"type":"manual","fullchain":"-----BEGIN CERTIFICATE-----\n[key]\n-----END CERTIFICATE-----\n","privateKey":"-----BEGIN PRIVATE KEY-----\n[key]\n-----END PRIVATE KEY-----\n"},"key":"sslConfiguration"}}]}

This looks similar to #189

Note that I've removed the contents of the pasted certs from the error above and replaced them with [key]

Edit: The private key is failing validation: failed custom validation because Invalid RSA private key

tanc commented 3 years ago

The private key that Cloudflare produces is RSA (2048) and for cert format is PEM

gempain commented 3 years ago

This is the test we run to check if your key is valid. It's not a great test I agree. So here it seems like you're missing the RSA word.

export function isRsaPrivateKey(value: string): string {
  if (!value.includes('-----BEGIN RSA PRIVATE KEY-----')
    || !value.includes('-----END RSA PRIVATE KEY-----')) {
    throw new Error('Invalid RSA private key');
  }

  return value;
}
tanc commented 3 years ago

Ah yes, it does look like that was the problem. If changing the match isn't too easy maybe there could be a hint under the field saying something like "Paste your private key including the beginning line -----BEGIN RSA PRIVATE KEY----- everything between and ending with -----END RSA PRIVATE KEY----- making sure they match those words exactly." That way at least it might be clearer that those words are expected.

I just made a fork to make that change but I couldn't find any examples of help or hint text on other forms to borrow the style from. Is it something you've added on any other forms that I can use as a example?

gempain commented 3 years ago

Glad it worked 😄 Thanks for suggesting these changes ! As for style, what I generally do is place a <div className="form-text">...</div> below the <input/> (this is what bootstrap recommends it).

yeahsid commented 3 years ago

You do not need to use the Cloudflare DNS plugin, set Automatic HTTPS to off, and create 2 page rules, one to allow /.well-known/* with SSL set to off and another to enable automatic HTTPS for all other URLs. Vercel has documented this under- using Cloudflare with proxy [https://vercel.com/support/articles/using-cloudflare-with-vercel]

tanc commented 3 years ago

@itsezsid I will try this, thanks!