I recently stumbled upon the problem of configuring a virtual host in Nginx so that it can serve HTTP and HTTPS writing just one configuration section.
I know that this is not the recommended way of configuring HTTP+HTTPS, but having two separate sections when the configuration is the same except for 3 lines (server certificates and listen 443) doesn’t make much sense.
I initially followed the official tutorial (most likely outdated) and added a part relative to PHP files
server { listen 80; listen 443 ssl; server_name domain.ext; ssl_certificate domain.crt; ssl_certificate_key domain.key; # ... rest of the configuration # PHP stuff location ~ \.php$ { include fastcgi_params; fastcgi_intercept_errors on; fastcgi_pass 127.0.0.1:9001; # Fixes random Bad gateway errors fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; } }
Everything worked smoothly on two computers running Ubuntu 10.04 + Nginx and PHP-fpm from the Nginx PPA. I then tried to do the same on Ubuntu 11.10 and PHP-fpm installed from the official repositories: all hell broke lose.
All of a sudden the $_GLOBALS["HTTPS"]
variable was not defined anymore even on secure connections. Setting such variable is an Apache specific behaviour, in all truth, but like most of the rest of the PHP community I learned to rely on it for secure connection detection.
Most of the guides I found online referred to setting the HTTPS variable explicitly in the appropriate server section via the fcgi_param
directive, but I didn’t want to have two completely separate configuration sections.
I then resorted to a hybrid, which makes use of dual server sections and one include file.
The configuration file looks like this:
# Nginx config file # HTTP server section server { listen 80; include domain.inc; } # HTTPS server section server { listen 443 ssl; server_name domain.ext; ssl_certificate domain.crt; ssl_certificate_key domain.key; include domain.inc; fastcgi_param HTTPS on; }
The include file looks like this:
# Nginx include file: domain.inc # ... rest of the configuration # PHP stuff location ~ \.php$ { include fastcgi_params; fastcgi_intercept_errors on; fastcgi_pass 127.0.0.1:9001; # Fixes random Bad gateway errors fastcgi_buffer_size 128k; fastcgi_buffers 4 256k; fastcgi_busy_buffers_size 256k; fastcgi_temp_file_write_size 256k; }
… and the magic is done!
[ALTERNATIVE]
The problem is due to the fact that the fastcgi_params
file is not present. Even if it were, the $https
variable is not defined anymore in recent versions of nginx.
The solution is to add the following lines to your nginx.conf
file
# Assigns $https depending on value of $scheme # $scheme is either "http" (default), or "https" map $scheme $https { default off; https on; }
and then create the fastcgi_params file with the following content (will set a few parameters commonly used by Apache/PHP)
fastcgi_param QUERY_STRING $query_string; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param SCRIPT_FILENAME $request_filename; fastcgi_param SCRIPT_NAME $fastcgi_script_name; fastcgi_param REQUEST_URI $request_uri; fastcgi_param DOCUMENT_URI $document_uri; fastcgi_param DOCUMENT_ROOT $document_root; fastcgi_param SERVER_PROTOCOL $server_protocol; fastcgi_param GATEWAY_INTERFACE CGI/1.1; fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; fastcgi_param REMOTE_ADDR $remote_addr; fastcgi_param REMOTE_PORT $remote_port; fastcgi_param SERVER_ADDR $server_addr; fastcgi_param SERVER_PORT $server_port; fastcgi_param SERVER_NAME $server_name; fastcgi_param HTTPS $https; # PHP only, required if PHP was built with --enable-force-cgi-redirect fastcgi_param REDIRECT_STATUS 200;