2

I have a setup that roughly looks like this (I have tried to simplify this as much as possible):

Port 443 - nginx listens and forwards to port 80, config looks something like this

server {
  listen 443 ssl;
  location / {
  proxy_pass http://127.0.0.1:80;
  proxy_set_header X-Real-IP  $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto https;
  proxy_set_header X-Forwarded-Port 443;
  proxy_set_header Host $host;
}

Port 80 - Varnish (reverse proxy) which forwards traffic to port 8080 unless there is a cache hit.

port 8080 nginx setup for PHP with fastcgi. I have some common config:

location ~ \.php$ {
  ...
  include fastcgi_params;
}

and fastcgi_params file which looks like this

...
fastcgi_param   HTTPS           $https if_not_empty;

What I've been trying to do is to create a setup, where nginx when listening on port 8080 is able to detect if it's serving content to http or https. It needs to tell this to PHP so it can create URLs with the correct scheme.

I was thinking that somewhere I should listen for the X-Forwarded-Proto and then tell nginx that https is turned on. I don't know how/where to make some kind of if statement or if something like this is even possible or how to tell nginx that https should be on.

  • You should use the protocol relative version of URLs in your application, like //serverfault.com/path/to/resource or path relative URL /path/to/resource. This makes browser request the resource with the protocol current page has loaded with. – Tero Kilkanen Sep 24 '17 at 16:36
4

You may solve this in two ways... at the application level or at the Nginx level.

At the application level

Since, it is a PHP application, you may use the following at the top of the code / application...

if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') $_SERVER['HTTPS']='on';

At the Nginx level

Step 1: Map X-Forwarded-Proto to a variable whose value depends on X-Forwarded-Proto.

map $http_x_forwarded_proto $fastcgi_param_https_variable {
    default '';
    https 'on';
}

Step 2: Replace the existing line fastcgi_param HTTPS $https $if_not_empty with the following line that sets fastcgi_param HTTPS based on the above variable

fastcgi_param HTTPS $fastcgi_param_https_variable;

Personally, I prefer the first method since it requires just a single line to set things correctly. The second method should work too, but is not tested.

  • Note that not all PHP applications test $_SERVER['HTTPS'] the same. The PHP documentation says that a non-empty value means that the HTTPS protocol was used, but when I set this up for Phabricator, I found that it required the value to be true. So check your PHP application - setting it to 'on' may not work. – Peter Nov 24 '17 at 6:36

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.