For various reasons (performance + clustering + slowloris protection), putting nginx in front of your apache+php application is a Good Thing. In addition to http, we usually let nginx fronting https for apache, so to simplify your load balanced php apps.
Some additional benefits of doing this:
- This also enables you to serve multiple domains off a single IP (aka Named Based Virtual Hosts over https), something that Apache doesn't do very well. Your browser may complain loudly about mismatched https certs, though
- HTTP referer hiding. If you have an internal custom site with less security, say http://private.home/ behind a firewall, you don't have to worry about users from the Internet accessing it, but any links from http://private.home/ to, say, http://www.bytecraft.com.my/ your browser will still leak the internal URL to the webmaster of the external site. Convert the internal site to https://private.home/ and all referers are not sent.
One downside is that the PHP app must realize that it is separated from the actual browser from itself. So the traditional way for checking the remote IP and whether a connection is https or not would not work. ($_SERVER['REMOTE_ADDR'] & $_SERVER['HTTPS'])
To fix this, there are two parts we must changed: get nginx to send additional headers, and get the PHP app to recognize the alternate headers.
1. nginx config
both http and https sections:
location / {
proxy_pass http://10.0.0.1:80/; # Replace with your apache ip/port
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Scheme $scheme;
}
X-Forwarded-For and
Scheme are the important ones here.
2. PHP
Highly dependant on your PHP app, but in general, search for $_SERVER['REMOTE_ADDR'] and $_SERVER['HTTPS'].
Example snippet to force https connection (say, for the login page):
if (isset($_SERVER['HTTP_SCHEME']) && $_SERVER['HTTP_SCHEME'] == 'http') {
header('Location: https://'.$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
exit;
}