ScaleScaleScaleScale

Tips / Nginx


How To Configure Nginx as a Reverse Proxy for Apache

Nginx as a reverse Proxy for Apache is one of the most usual ways to use Nginx, although nowadays you can replace Apache with Nginx at 100%, there are still some people who need to setup Nginx as a Reverse Proxy for Apache. In this guide I will teach you how to gain a lot of server performance by serving your static files (jpg,gif,png,css,js,html) with Nginx, and the dynamic files with Apache on the backend.

Install Apache

yum install httpd httpd-devel -y

Configure the Reverse Proxy settings on Apache

Edit Listen directive at httpd.conf

nano -w /etc/httpd/conf/httpd.conf

Then find:

Listen 80

And change it to be:

Listen 81

Then, move at the end of the file and paste this code:

NameVirtualHost 127.0.0.1:81

# Define Server document root
   DocumentRoot /var/www/html/

# Define the virtual host

   ServerName www.yourwebsite.com
   ServerAlias yourwebsite.com
   DocumentRoot /var/www/yourwebsite.com
       
               Options FollowSymLinks -Includes
               AllowOverride All
               Order allow,deny
               Allow from all
       
       RewriteEngine on

Replace yourwebsite.com with your real domain name, and /var/www/yourwebsite.com with your real root directory.

Restart httpd to apply the changes:

service httpd restart

Install Nginx

mkdir /root/temp; cd /root/temp
wget http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
rpm -i nginx-release-centos-6-0.el6.ngx.noarch.rpm
yum install nginx -y

Configure Nginx main configuration

nano -w /etc/nginx/nginx.conf

Place this configuration inside:

user  nobody;
worker_processes  4;
error_log  logs/error.log crit;

worker_rlimit_nofile  8192;

events {
worker_connections  1024; # you might need to increase this setting for busy servers
use epoll; #  Linux kernels 2.6.x change to epoll
}

http {
server_names_hash_max_size 2048;
server_names_hash_bucket_size 512;

server_tokens off;

include    mime.types;
default_type  application/octet-stream;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout  10;

# Gzip on
gzip on;
gzip_min_length  1100;
gzip_buffers  4 32k;
gzip_types    text/plain application/x-javascript text/xml text/css;

# Other configurations
ignore_invalid_headers on;
client_max_body_size    8m;
client_header_timeout  3m;
client_body_timeout 3m;
send_timeout     3m;
connection_pool_size  256;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
request_pool_size  4k;
output_buffers   4 32k;
postpone_output  1460;

# Cache most accessed static files
open_file_cache          max=10000 inactive=10m;
open_file_cache_valid    2m;
open_file_cache_min_uses 1;
open_file_cache_errors   on;

# virtual hosts includes
include "/etc/nginx/conf.d/*.conf";

}

Configure Nginx Reverse Proxy settings

Now create this file:

nano -w /etc/nginx/conf.d/yourwebsite.com.conf

Then paste this inside:

server {
listen    80;
server_name  yourwebsite.com yourwebsite.com;
access_log off;
error_log  logs/yourwebsite.com-error_log crit;

location ~* .(gif|jpg|jpeg|png|ico|wmv|3gp|avi|mpg|mpeg|mp4|flv|mp3|mid|js|css|html|htm|wml)$ {
root /var/www/yourwebsite.com;
expires 365d;
}

location / {
client_max_body_size    10m;
client_body_buffer_size 128k;

proxy_send_timeout   90;
proxy_read_timeout   90;
proxy_buffer_size    128k;
proxy_buffers     4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
proxy_connect_timeout 30s;

proxy_redirect  http://www.yourwebsite.com:81   http://www.yourwebsite.com;
proxy_redirect  http://yourwebsite.com:81   http://yourwebsite.com;

proxy_pass   http://127.0.0.1:81/;

proxy_set_header   Host   $host;
proxy_set_header   X-Real-IP  $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Replace yourwebsite.com with your real domain name, and /var/www/yourwebsite.com with your real root directory.
What we have done here:

1.- Defined the location of static files, and let Nginx cache those files for 1 year.
2.- Then we added the reverse proxy configuration so Nginx can serve the information from 127.0.0.1:81, which is the port and IP where Apache is listening to.

Install mod_rpaf

mod_rpaf will help Apache to know who connects to it (otherwise the only IP address you will see in your logs is 127.0.0.1):

mkdir /root/temp; cd /root/temp
wget https://github.com/y-ken/mod_rpaf/archive/master.zip
unzip master.zip
cd mod_rpaf-master/
apxs -i -c -n mod_rpaf-2.0.so mod_rpaf-2.0.c

Once it’s installed, we need to configure it. Create a new file:

nano -w /etc/httpd/conf.d/rpaf.conf

And place this inside:

LoadModule rpaf_module modules/mod_rpaf-2.0.so

  RPAFenable On
  RPAFsethostname On
  RPAFproxy_ips 127.0.0.1 YOUR.SERVER.IP

Replace YOUR.SERVER.IP with your public server IP address.

Now restart httpd to apply the changes:

service httpd restart

Test your Nginx Reverse Proxy

curl -I http://www.yoursite.com/

You should see something like this:

HTTP/1.1 200 OK
Server: nginx

If you see Nginx in the Server: result, that means your website is being served using Nginx in the front end, and the backend dynamic files (php) are served using Apache. Need a better test? Try shutting down Apache:

service httpd stop

Then try to load your website on the browser or using curl, you will probably get a 502 bad gateway error, and that means your proxy is actually working. Now, get your httpd bad ass server back:

service httpd start

Other ways to test it: create a phpinfo file.

nano -w /var/www/yourwebsite.com/info.php

Paste the following lines into that file:


Save and exit.

Now visit www.yourwebsite.com/info.php and you should show see the php server information on your screen, then search for the server that is serving the phpinfo file, if you see Apache then your proxy configuration is working fine.

Popular search terms:

  • return php from apache to nginx
  • https://www scalescale com/tips/nginx/how-to-configure-nginx-as-a-reverse-proxy-for-apache/
  • nginc proxy apache mod_raf
  • nginx apache proxy config
profile

Esteban Borges

Linux Geek, Webperf Addict, Nginx Fan. CTO @Infranetworking

  • Ken

    I made everything like you guided. However, even I perform “service httpd stop”. The page still show nginx. Moreover, phpinfo() not work.

  • Dan

    Good guide, got me working!
    Running apx to install mod_rpaf needed me to install libtool first.
    Also don’t forget to start the nginx service and chkconfig nginx on 😉

    Cheers dude, very helpful

  • Angelo Corbo

    Excellent stuff.

    I’m running nginx on Ubuntu 12.10 with 5 web apps in one box, AND then Apache on OS X (Mac Mini) with a web photo gallery (gallery3) serving a few thousand pictures and videos. I thought about configuring nginx as a reverse proxy for Apache for all the performance benefits it provides. It should be feasible to have Apache handle the gallery app except the actual media (static pictures and videos), which nginx would be ideal to handle, but I’m not sure on the actual details. Do you have any suggestions?

    Angelo C

  • admin

    Angelo

    You can do both things, running Apache on another port and Nginx proxy in front of it. Apache will handle the PHP with mod_php and you can serve static content with Nginx, you’ll notice a difference.

    But, if you need to increase performance, you may want to go for the big change and start working with Nginx + PHP-FPM, that way Nginx will handle all static stuff and PHP-FPM will parse php files. Check out this two guides if you are interested:

    http://www.nginxtips.com/install-nginx-with-php-fpm-mysql-support-on-centosrhel/
    http://www.nginxtips.com/nginx-php5-php-fpm-mysql-ubuntu-13-04/

    Regards

  • Pablo

    Hello!

    Thanks for your great tutorial 🙂

    Anyway, didn’t work for me in a strange way! If I test with Curl seems to be working, starting and stopping Apache. But if I test with PHP file shows me nginx as webserver.

    Where can I look?

    Thanks again!

  • I keep getting “curl(7) failed to connect to 3solstice.com port 80: connection refused” any ideas?

    • Oh, I forgot to say service nginx start. Figured it out!

  • Vitaliy

    Hello,

    Thank you, userful tips

  • Tural

    Thanks, .php not working 🙁

    yum install php ( i am install php after not working )

    and this confugiration supported ssl?

  • Windy

    Excellent tutorial!

    I have been stuck on this 2 days until I find your tutorial. Keep up running!

  • Hello!

    Thanks for your great tutorial 🙂

    Anyway, didn’t work for me in a strange way! If I test with Curl seems to be working, starting and stopping Apache. But if I test with PHP file shows me nginx as webserver.

    Where can I look?

    Thanks again!

  • root

    Thank you very much for writing this excellent resource!

  • Jay

    I follow this guide step by step but I guess it doesn’t work properly since the nginx cache folder is always empty.
    Any idea?

    • admin

      Check the permissions, and the logs at nginx.

  • Jay

    Thank you. What if I run PHP as fastcgi? Which directives need to be changed?

  • Ashish Srivastava

    Great Stuff,

    but i think SSL will not work for this configuration , It will be better to go for dedicated nginx configuration on server.

  • Jonathan

    Hi,

    For some reasons, I have to use nginx as a proxy serving for another nginx server. This idea is as below:
    Server nginx1 –> https://mywebsite.com
    Server nginx2 –> https://mywebsite.com/specificlink for displaying my blog articles.
    Both application servers are running on Cake PHP.

    On nginx1, I am configuring it as:


    location ^~ /specificlink/server/ {
    rewrite ^/specificlink/server(/.*)$ /server/$1 break;
    proxy_passhttps:///server;
    }

    location ^~ /specificlink/ {
    rewrite ^/specificlink(/.*)$ /$1 break;
    proxy_pass https://;
    }

    location /server {
    rewrite ^/server/(.*)$ /server/app/webroot/$1 break;
    try_files $uri $uri/ /server/app/webroot/index.php?q=$uri&$args;
    }

    location / {
    rewrite ^/(.*)$ /app/webroot/$1 break;
    try_files $uri $uri/ /app/webroot/index.php?q=$uri&$args;
    }

    On nginx2:


    location /server {
    rewrite ^/server/(.*)$ /server/app/webroot/$1 break;
    try_files $uri $uri/ /server/app/webroot/index.php?q=$uri&$args;
    }

    location / {
    rewrite ^/(.*)$ /app/webroot/$1 break;
    try_files $uri $uri/ /app/webroot/index.php?q=$uri&$args;
    }

    My current situation is:

    – https:// and https:///server/api/index are doing well
    https://mywebsite.com/specificlink/server/api/index is returning good

    – On https://mywebsite.com/specificlink
    * All statistic files are now referred as https://mywebsite.com/file which should be https://mywebsite.com/specificlink/file. It makes https://mywebsite.com/specificlink can’t display well.
    * https:///article.html is displaying good but https://mywebsite.com/specificlink/article.html always returns 500 on nginx2.

    Please help. Thank you.

    • Jonathan

      I didn’t notice that will be disappeared. Just want to correct above information:

      location ^~ /specificlink/server/ {
      rewrite ^/specificlink/server(/.*)$ /server/$1 break;
      proxy_passhttps://IP2:port/server;
      }

      location ^~ /specificlink/ {
      rewrite ^/specificlink(/.*)$ /$1 break;
      proxy_pass https://IP2:port;
      }

      location /server {
      rewrite ^/server/(.*)$ /server/app/webroot/$1 break;
      try_files $uri $uri/ /server/app/webroot/index.php?q=$uri&$args;
      }

      location / {
      rewrite ^/(.*)$ /app/webroot/$1 break;
      try_files $uri $uri/ /app/webroot/index.php?q=$uri&$args;
      }

      My current situation is:

      – https://IP2:port and https://IP2:port/server/api/index are doing well
      – https://mywebsite.com/specificlink/server/api/index is returning good

      – On https://mywebsite.com/specificlink
      * All statistic files are now referred as https://mywebsite.com/file which should be https://mywebsite.com/specificlink/file. It makes https://mywebsite.com/specificlink can’t display well.
      * https://IP2:port/article.html is displaying good but https://mywebsite.com/specificlink/article.html always returns 500 on nginx2.

      • Jonathan

        I figured out. Just I need to change Application Base in side the code, instead of rewrite it in nginx’s configuration. But in this case, I have to declared a new location for reflecting the new application base in my code.

        Hope it helps anyone who are looking for the same question.

        Thank you.

  • Richard

    Hi,

    How to configure to use apache mod rewrite htaccess instead of using Nginx mod rewrite? Since the nginx is running on front and apache running on back.

    Thanks

    • Hey Richard

      If apache is on the backend, you should be able to use .htaccess normally, as Nginx will act as a proxy only for the static content, not for the dynamic, mod_rewrite will still be served from Apache, and PHP executed using mod_php on most cases.

      Good luck with that!

  • Hi man,

    I notice that the nginx.conf’s user is nobody but I setup different ftp user for each website. When I curl the website, the result is HTTP/1.1 403 Forbidden, Is it related with the different ftp user, please?

    • It should’t be related to the FTP user. However, it can be related to your php-fpm installation if you are using per ftp/user accounts.
      Check your directory ownership and permissions, and of course, make sure you have placed an index.php file inside the directory, that is another reason for the 403 forbidden error.

      • Amitabh Ghosh

        Any idea why I see 403 Forbidden?

        [root@ip-.com]# curl -I http://.com/
        HTTP/1.1 403 Forbidden
        Server: nginx
        Date: Tue, 27 Dec 2016 12:21:55 GMT
        Content-Type: text/html; charset=UTF-8
        Content-Length: 4891
        Connection: keep-alive
        Last-Modified: Fri, 29 Jul 2016 21:40:52 GMT
        ETag: “131b-538cd1ac32100”
        Accept-Ranges: bytes

        I am new to these stuffs, so kindly bear with me

  • Anupam Jain

    For future users, I should mention that with the advent of mod_wsgi-express, we do not need to do any Apache config, no VirtualHost definitions, nothing in conf-available and sites-available folders. Its all done in a well-optimized way by mod_wsgi-express automatically. See Graham(mod_wsgi author)’s blog posts for details