9

I am trying to implement Flexible SSL provided by CloudFlare to my site.

Here is my nginx config:

# PHP-FPM upstream; change it accordingly to your local config!
upstream php-fpm {
    server 127.0.0.1:9000;
}

server {
    listen         80;
    server_name    example.com www.example.com;
    return         301 https://$server_name$request_uri;
}

server {
    ## Listen ports
    listen 443;

    # use _ if you want to accept everything, or replace _ with domain
    server_name example.com www.example.com;

    location / {
      #proxy_set_header        X-Forwarded-Proto $scheme;
      proxy_set_header X_FORWARDED_PROTO https;
      proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header  Host $http_host;
      proxy_set_header  X-Url-Scheme $scheme;
      proxy_redirect    off;
      proxy_max_temp_file_size 0;
    }

(...rest of config...)

However, when I try to connect to the website (Wordpress), I get a redirect loop (chrome: ERR_TOO_MANY_REDIRECTS). How do I configure nginx to prevent this?

AD7six
  • 2,810
  • 2
  • 20
  • 23
Deqq
  • 141
  • 1
  • 1
  • 3

3 Answers3

29

Cloudflare's flexible ssl means the connection between cloudflare and your server is always over http:

connection is always http

Given this - the only server block in the question of relevance is this one:

server {
   listen         80;
   server_name    example.com www.example.com;
   return         301 https://$server_name$request_uri;
}

It should be obvious why that results in a redirect loop, there are 2 solutions to force https connections using their flexible ssl solution.

Use Cloudflare's page rules

If access to the server is exclusively via cloudflare you can use cloudflare's own page rules to modify responses for a domain, subdomain, or any url pattern:

Using cloudflare's page rules

One of the options is to force https:

Always use HTTPS

Test $http_x_forwarded_proto

There are times you may want to avoid using page rules (should be rare or transitional only), for these scenarios it's possible to test the forwarded protocol and redirect based on that:

server {
   listen         80;
   server_name    example.com www.example.com;

   if ($http_x_forwarded_proto = "http") {
     return 301 https://$server_name$request_uri;
   }

   ... directives to generate a response
}
AD7six
  • 2,810
  • 2
  • 20
  • 23
  • And will there be errors in my https connections such as not everything is transmitted over http in this case? – Deqq Dec 21 '14 at 12:19
  • How you setup cloudflare/nginx has no bearing on that, the html _contents_ will determine if there are such errors reported. – AD7six Dec 21 '14 at 12:49
  • The first line of this answer is incorrect: the connection between the browser and CloudFlare is TLS encrypted, the connection from CloudFlare to the origin server is http. Redirect loops can be caused by page rules or high level setting specifying the encryption type incorrectly - eg full when you really need flexible. – Tim Apr 10 '16 at 04:48
  • There's also a plugin that helps with this: https://en-nz.wordpress.org/plugins/cloudflare-flexible-ssl/ – Tim Oct 01 '16 at 20:41
5

This can fix the problem if you have the valid SSL certificate on your. [Crypto] box and select Full (strict) as in the image. enter image description here

Really no need to update the web server configuration file for Nginx.

prosti
  • 328
  • 1
  • 6
  • 17
  • Full (strict) only works if the origin web server has a valid SSL certificate with a valid certificate chain. Full works with any SSL certificate, including self signed. This isn't a good answer to the question. – Tim Oct 01 '16 at 20:40
  • Yes, I see now, the question mentioned the Flexible certificate. I will improve my answer thanks to your feedback and I will be more specific. We are improving the knowledge base in here. A valid SSL certificate has the best value for Google if we consider SEO perspective. I am not in regret after posting this. – prosti Oct 01 '16 at 23:18
  • Flexible/full/strict makes no difference to SEO, that setting is for connection to the origin server. Cloudflare presents a shared https certificate to whoever requests the page, how it connects to the origin is largely irrelevant. – Tim Oct 01 '16 at 23:54
  • Assuming the server *does* have a valid SSL cert (the OP doesn't specify, and I came here via an similar config google), this is a great option - note it can also be scoped to a particular subdomain via the Page Rules. – skoczen Oct 17 '17 at 03:46
  • This is a super good answer for me that had a valid SSL. – Philip Oct 23 '17 at 15:00
0

AD7six's answer is very good, though it appears there's a simpler solution that doesn't require page rules. I'm not sure if this is a new addition since the previous answers, but it should definitely be documented on this question, especially given that you only get 3 free page rules with Cloudflare at the time of writing.

When you have Flexible SSL turned on for a given domain, you can scroll down on the Crypto tab and enable the Always use HTTPS option. This option will seamlessly solve the redirect loop issue (explained thoroughly in AD7six's answer).

Cloudflare's "Always Use HTTPS" option

This option is confirmed working with nginx; furthermore, there should not be any server setup where this option does not work, provided that Flexible SSL is already enabled and works without issue.

Chad
  • 113
  • 4
  • If Cloudflare's ui has changed (or new options have been made available) it would be better to edit the existing answer rather than create a competing one. – AD7six Jun 20 '19 at 09:00
  • @AD7six I believe this is an addition to the old UI, not a replacement, which means the old answer should still be valid. Therefore a separate answer would be more logical than editing the original, would it not be? – Chad Jun 20 '19 at 20:55
  • I don't think "You used to have to do this the long way round, but now there's a button for it!" is a new answer, no :). – AD7six Jun 24 '19 at 08:29