A typical Nginx setup uses fastcgi_pass directives to pass the request to the PHP-FPM daemon. If you would be running an Apache setup, Apache would automatically set the HTTPS server variable, that PHP code can check via $_SERVER['HTTPS'] to determine if the request is HTTP or HTTPs.
In fact, that’s how most CMS’s (WordPress, Drupal, …) determine the server environment. They’ll also use it for redirects from HTTP-to-HTTPs or vica versa, depending on the config. So the existence of the $_SERVER['HTTPS'] variable is pretty crucial.
Nginx doesn’t pass the variable by default to the PHP-FPM daemon when you use fastcgi_pass, but it is easily added.
A basic example in Nginx looks like this.
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Check if the PHP source file exists (prevents the cgi.fix_pathinfo=1 exploits)
if (-f $request_filename) {
fastcgi_pass backend_php; # This backend is defined elsewhere in your Nginx configs
}
The example above is a classic one, that just passes all to PHP. In order to make PHP-FPM aware of your HTTPs setup, you need to add a fastcgi_param environment variable to the config.
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(.*)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Make PHP-FPM aware that this vhost is HTTPs enabled
fastcgi_param HTTPS 'on';
# Check if the PHP source file exists (prevents the cgi.fix_pathinfo=1 exploits)
if (-f $request_filename) {
fastcgi_pass backend_php; # This backend is defined elsewhere in your Nginx configs
}
The solution is in the fastcgi_param HTTPS 'on'; line, which passes the HTTPS variable to the PHP-FPM daemon.