Custom errors in nginx + php-fpm

Tested in Nginx 1.10 / PHP-FPM 5.6

By default php-fpm shows “File not found” when someone try to request a php file that doesn’t exist. If you use php-fpm in nginx with fastcgi for using custom errors just configure this in nginx.conf:

fastcgi_intercept_errors on;

Redirect http to https on the same port in nginx

Tested in Ubuntu 14 / Nginx 1.11

If you use a custom port to serve SSL and you want to force a secure connection redirecting from http to https, a solution is use error_page directive with code 497:

server {

        listen 8080 ssl;

        root /usr/share/nginx/mydomain;
        index index.html index.php;

        ssl_certificate /etc/ssl/certs/mydomain.com.crt;
        ssl_certificate_key /etc/ssl/private/mydomain.com.key;

        error_page 497  https://$host:$server_port$request_uri;

        ...

}

Don’t forget to reload nginx:

~ $ /etc/init.d/nginx reload

Varnish SSL redirect

Tested in Ubuntu 14 / Debian 8 / Varnish 4.1

If you have configured nginx as SSL proxy for varnish, you could be interested in redirecting requests from HTTP to HTTPS. We are going to suppose this configuration, so first in VCL recv, add this code:

sub vcl_recv {
    ...
    if (req.http.X-Forwarded-Proto !~ "(?i)https") {
        return (synth(750, ""));
    }
    ...
}

And then in VCL synth:

sub vcl_synth {
    ...
    if (resp.status == 750) {
        set resp.status = 301;
        set resp.http.Location = "https://domain.com" + req.url;
    }
    ...
}

Finally reload varnish:

~ $ /etc/init.d/varnish reload

Nginx status module

Tested on Debian 7 / NGINX 1.10

You can watch the nginx connections stats compiling nginx with the option http_stub_status_module:

~ $ ./configure --sbin-path=/usr/local/sbin --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --with-http_ssl_module --with-http_addition_module --with-pcre-jit --with-http_stub_status_module

Make and install:

~ $ make && make install

Now add this to the section server in the vhost config:

location /nginx_status {
                stub_status on;
                access_log off;
                allow x.x.x.x;
                deny all;
        }

Where x.x.x.x is your IP address. Also you can protect URL by http auth:

location /nginx_status {
                stub_status on;
                access_log off;
                auth_basic "Auth required";
                auth_basic_user_file /etc/nginx/htpasswd;
        }

Generate password file:

~ $ htpasswd -c /etc/nginx/htpasswd administrator
New password: 
Re-type new password: 
Adding password for user administrator
~ $ cat /etc/nginx/htpasswd
administrator:$apr1$kpTScFHe$A8W0.xtVq.gfiCY/9SdO71

Then reload nginx:

~ $ /etc/init.d/nginx reload

On load http://mydomain.com/nginx_status you will see:

Active connections: 2 
server accepts handled requests
 xxx yyy zzz 
Reading: 0 Writing: 2 Waiting: 0

Where:

mydomain.com: is your domain
xxx: total accepted connections
yyy: total handled connections
zzz: total handled requests

Real IP on nginx behind a proxy

Tested on Debian 7 / NGINX 1.10

When a web server is working behind a proxy, ha-proxy, varnish, or any web server in proxy mode, by default in the log file, you see the IP of proxy server not the real client IP, this can be a trouble for making statistics for example.

Usually you can configure the proxy server for making forwarding of the client IP by X-Forwarded-For header, for example in varnish4 you can do it so:

req.http.X-Forwarded-For = client.ip;

But it’s not enough because is still necessary modify the configuration in the destination web server.

Nginx can be configured to show the client IP but for do it we need to compile from the sources. At this article the workaround is for Debian 7.

First, install the development libraries needed:

~ $ apt-get install libpcre3-dev libgeoip-dev libssl-dev libc6 libpcre3 zlib1g lsb-base

Second, download sources from the official site and unpack files, then run configure with the desirable options, for our case we need with-http_realip_module option:

~ $ ./configure --sbin-path=/usr/local/sbin --prefix=/etc/nginx --conf-path=/etc/nginx/nginx.conf --pid-path=/var/run/nginx.pid --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_geoip_module --with-pcre-jit

Make:

~ $ make

And install:

~ $ make install

Finally add next configuration to nginx.conf file inside http block, where x.x.x.x is the proxy server IP:

set_real_ip_from x.x.x.x;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

And restart nginx:

~ $ /etc/init.d/nginx restart