I was using my own IP & Letsencrypt (with HTTP->HTTPS 301) to publish my site but after configuring cloudflare to use it's proxy I ran into the too many redirect issue. I switched cloudflare SSL/TLS over to full/strict and now it works.
But now I'm thinking doesn't the certbot challenge use HTTP? Am I going to break that with this configuration?
Recommended changes?
My domain is: jalbert.me
I ran this command: none yet, all changes done in Cloudflare proxy.
My web server is (include version): nginx/1.18.0 (Ubuntu) and has a mix of static and reverse proxy in the config.
The operating system my web server runs on is (include version): Ubuntu 20.04.5 LTS
I can login to a root shell on my machine (yes or no, or I don't know): yup
The version of my client is (e.g. output of certbot --version): certbot 0.40.0
Certbot has a --dry-run mode for testing which can be very helpful for this.
As for Cloudflare, there are many options. These are just three:
One option is because Cloudflare is configured to redirect the HTTP Challenge to HTTPS you need to have your origin server handle the challenge in its HTTPS server block.
Another option is to use CF page rule so the HTTP challenge is not redirected. See linkp comment (link here) or the Cloudflare page rule docs (link here)
Another option is to use a Cloudflare Origin CA Cert on your origin server. Then, you don't use a Let's Encrypt cert on your origin at all. The CF Origin CA cert is long-lived. (link here)
I forgot about that! I was very much not expecting this error;
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx
Obtaining a new certificate
An unexpected error occurred:
The server will not issue certificates for the identifier :: Error creating new order :: Cannot issue for "ry-run": Domain name needs at least one dot
Please see the logfiles in /var/log/letsencrypt for more details.
The only thing I changed recently was this;
#root /var/www/html; #this WAS the default folder
root /var/www/jalbert.me/html; # my site
# Add index.php to the list if you are using PHP
index index.html index.htm index.htm index.nginx-debian.html; # added htm
I don't get any results with this below so I don't think certbot uses that folder??
egrep "/var/www/html" letsencrypt.log
I'm going to turn cloudflare proxy off and try again after a while.
OK, looks like we are good. I waited a while and I'm definitely seeing cloudflare IP for my site. Cloudflare proxy is turned ON and SSL/TLS in Cloudflare is set to Full (strict). Certbot dry run says it is happy still.
When using any CDN, you should not expect to see any HTTP connections to your server.
If you do, the last thing you need to do is to redirect them to HTTPS.
[that should be done by the CDN]
When you do, you might be redirecting what you think is an HTTP connection to HTTPS, but it might have already been an HTTPS connection it was just being proxied by the CDN to your server via HTTP.
If so, that creates an endless redirection loop to the originating client.
When they request HTTP:
HTTP > HTTPS > HTTPS > HTTPS ...
When they request HTTPS:
HTTPS > HTTPS > HTTPS > HTTPS ...
Yes, in my case I wasn't considering what the Cloudflare reverse proxy was doing. When set wrong it seems it was asking for http from my back end site leading to the loop. According to the listen statement certbot adds to the nginx config it's only listening on 80, and if Cloudflare is set right the back end server only ever sees https. Or at the very least it doesn't attempt the 301 independently, lets the back end server do it and not fight?
This is exactly what lead to my question, where does this leave the certbot challenge? I still don't exactly know but it seems to work. Maybe Cloudflare has a stock exception for the challenge? Maybe it will accept the challenge over https? I haven't really found the hook certbot listens on in the nginx config.
But this is the redirect certbot adds to the nginx sites configured:
server {
if ($host = www.jalbert.me) {
return 301 https://$host$request_uri;
} # managed by Certbot
if ($host = jalbert.me) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name jalbert.me www.jalbert.me;
return 404; # managed by Certbot
Yes, that's the redirect and what caused trouble when you were using Flex in Cloudflare.
Flex means Cloudflare always uses HTTP to your Origin. Your Origin then redirected that to HTTPS. So, the browser responded by sending in that HTTPS request which Cloudflare converted to HTTP to your Origin and repeats forever.
But, you fixed that by using Full(Strict)
The server block you show now is only the one for HTTP (port 80). There is also a server block for port 443 which has your cert definitions.
When using the --nginx plug-in Certbot adds temp code to both port 80 and port 443 server blocks so it will see the challenge from Cloudflare even on HTTPS
With a CDN there are two distinct comms interactions. One is between the client (browser) and the CDN and the other between the CDN and the Origin Server.
As of Certbot v1.13.0 (released March 2021), Certbot's --nginx plugin added support for authenticating your domain when using Cloudflare's Full (Strict) setting. From this version, Certbot will set up the nginx challenge for both port 80/HTTP and port 443/HTTPS.
Prior to Certbot v1.13.0, you would either have to use Cloudflare's Flexible setting, or use the --webroot plugin. because Certbot would only set the nginx challenge up on port 80/HTTP.
If you intend to use Cloudflare on Full (Strict), then I strongly suggest that you use a newer version of Certbot, either from the snap or pip.