Setup nginx Reverse Proxy

Here is how to setup nginx reverse proxy with Apache web server for PHP files, but using nginx to deliver static files and also set browser cache.

nginx reverse proxy configuration

If you don’t have nginx installed on your system type the following commands

apt-get install nginx
update-rc.d nginx defaults
/etc/init.d/nginx restart

Add the following proxy parameters in /etc/nginx/proxy_params which we will include later on in the vhosts file

vi /etc/nginx/proxy_params
proxy_set_header Host $host;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 client_max_body_size 100M;
 client_body_buffer_size 1m;
 proxy_intercept_errors on;
 proxy_buffering on;
 proxy_buffer_size 128k;
 proxy_buffers 256 16k;
 proxy_busy_buffers_size 256k;
 proxy_temp_file_write_size 256k;
 proxy_max_temp_file_size 0;
 proxy_read_timeout 300;

Now we will create vhosts file for mydomain.com which will have the same document root as the Apache vhost. This way we can deliver static files directly without passing the request to Apache web server.

vi /etc/nginx/sites-available/mydomain.com.vhost
server {
       listen 80;
       server_name www.mydomain.com mydomain.com;
       root /var/www/mydomain.com/web;
       if ($http_host != "www.mydomain.com") {
                 rewrite ^ http://www.mydomain.com$request_uri permanent;
       }
       index index.php index.html;

       location / {
                proxy_pass http://localhost:8000;
                include /etc/nginx/proxy_params;
       }
}

To enable that vhost, we create a symlink to it from the /etc/nginx/sites-enabled/ directory and reload nginx

cd /etc/nginx/sites-enabled/
ln -s /etc/nginx/sites-available/mydomain.com.vhost mydomain.com.vhost
/etc/init.d/nginx reload

The configuration above is a very simple one and it proxies all the requests to the Apache web serevr, but because nginx is much better on delivering static files we will change the configuration file to serve the static files directly.

Also we can even set an Expires HTTP header for these files so that browsers will cache these files for longer time.

With the configuration below we will set the nginx to serve as many requests as it can fulfill and only pass the remaining requests plus PHP files to Apache

server {
       listen 80;
       server_name www.mydomain.com mydomain.com;
       root /var/www/mydomain.com/web;
       if ($http_host != "www.mydomain.com") {
                 rewrite ^ http://www.mydomain.com$request_uri permanent;
       }
       index index.php index.html;

       location / {
                try_files $uri @proxy;
       }
       location ~* \.(js|css|jpg|jpeg|gif|png|svg|ico|pdf|html|htm)$ {
                expires      30d;
       }
       location @proxy {
                proxy_pass http://127.0.0.1:8000;
                include /etc/nginx/proxy_params;
       }
       location ~* \.php$ {
                proxy_pass http://127.0.0.1:8000;
                include /etc/nginx/proxy_params;
       }
}
/etc/init.d/nginx reload

Apache Configuration

I will not go deep into Apache configuration I will just point few things you need to do.

Change the listening port to 8000

vi /etc/apache2/ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default
# This is also true if you have upgraded from before 2.2.9-3 (i.e. from
# Debian etch). See /usr/share/doc/apache2.2-common/NEWS.Debian.gz and
# README.Debian.gz

NameVirtualHost *:8000
Listen 8000

<IfModule mod_ssl.c>
    # If you add NameVirtualHost *:443 here, you will also have to change
    # the VirtualHost statement in /etc/apache2/sites-available/default-ssl
    # to <VirtualHost *:443>
    # Server Name Indication for SSL named virtual hosts is currently not
    # supported by MSIE on Windows XP.
Listen 443
</IfModule>

<IfModule mod_gnutls.c>
Listen 443
</IfModule>

Create vhost file for your website and make it listen only on 127.0.0.1 and posrt 8000

vi /etc/apache2/sites-available/mydomain.com.vhost
<VirtualHost 127.0.0.1:8000>
[...]
cd /etc/apache2/sites-enabled/
ln -s /etc/apache2/sites-available/mydomain.com.vhost mydomain.com.vhost
/etc/init.d/apache2 reload

Modify the LogFormat line in /etc/apache2/apache2.conf and replace %h with %{X-Forwarded-For}i so you can have the original IP address logged in Apache log files.

vi /etc/apache2/apache2.conf
[...]
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[...]

Apache web server: http://httpd.apache.org/
nginx wiki page: http://wiki.codemongers.com/Main

Nikola Stojanoski

System Administrator and Developer. Giving back to the community by blogging about my problems, solutions and practical howto's.