Tutorial

How To Configure Nginx as a Reverse Proxy for Apache

How To Configure Nginx as a Reverse Proxy for Apache

This tutorial is out of date and no longer maintained.

Note: This tutorial is out of date and unmaintained. Updated versions are available for Ubuntu 18.04 and Ubuntu 16.04

Why Run Nginx and Apache Together

Both nginx and apache are powerful and effective servers. Apache currently reigns as the #1 server for websites and since its public release in 2006, nginx has taken the world by storm and is now the #2 server for active sites. The reasons for each respective server’s popularity are clear: apache’s power and nginx’s speed are well known. However, both servers do have drawbacks—apache is hard on server memory, while nginx (great at static files) needs the help of php-fpm or similar modules for dynamic content.

However, one can combine the two web servers to great effect, with nginx as static web server front and apache processing the back end.

Setup

To perform the steps in this tutorial, you will need to have sudo privileges on your virtual private server.

To create a user with sudo privileges, go through the third and fourth steps of the initial ubuntu server setup tutorial

Install nginx

To start off, we need to install and configure nginx which will serve the front end of our site.

Let’s download it from apt-get:

sudo apt-get install nginx

Once it has downloaded, you can go ahead and configure the virtual host to run on the front end.

There are a few changes we need to make in the configuration.

Configure nginx

Open up the nginx configuration.

sudo nano /etc/nginx/sites-available/example

The following configuration will set you up to use nginx as the front end server. It is very similar to the default set up, and the details are under the configuration.

server {
        listen   80; 

        root /var/www/; 
        index index.php index.html index.htm;

        server_name example.com; 

        location / {
        try_files $uri $uri/ /index.php;
        }

        location ~ \.php$ {
        
        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $host;
        proxy_pass http://127.0.0.1:8080;

         }

         location ~ /\.ht {
                deny all;
        }
}

The following changes were implemented in the configuration:

  • The root was set to the correct web directory
  • index.php was added on the index line
  • try_files attempts to serve whatever page the visitor requests. If nginx is unable, then the file is passed to the proxy
  • proxy_pass lets nginx the address of the proxied server
  • Finally the "location ~ /\.ht {" location block denies access to .htaccess files, if Apache's document root concurs with nginx's one

This configuration sets up a system where all extensions with a php ending are rerouted to the apache backend which will run on port 8080.

Activate the virtual host.

sudo ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example

Additionally, delete the default nginx server block.

sudo rm /etc/nginx/sites-enabled/default

The next step is to install and configure apache.

Install Apache

With nginx taken care of, it’s time to install our backend, apache.

sudo apt-get install apache2

Since nginx is still not turned on, Apache will start running on port 80.

Configure Apache

We need to configure apache to take over the backend, which as we told nginx, will be running on port 8080. Open up the apache ports file to start setting apache on the correct port:

sudo nano /etc/apache2/ports.conf

Find and change the following lines to have apache running on port 8080, accessible only from the localhost:

NameVirtualHost 127.0.0.1:8080
Listen 127.0.0.1:8080

Save and Exit.

Subsequently, open up a new virtual host file, copying the layout from the default apache file:

sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/example
sudo nano /etc/apache2/sites-available/example

The main issue that needs to be addressed here is that the virtual host needs to be, once again, running on port 8080 (instead of the default 80 given to nginx).

The line should look like this:

<VirtualHost 127.0.0.1:8080>

Make sure your Document Root is correct. Save and exit the file and activate that virtual host:

sudo a2ensite example

Before we start testing anything out, we need to equip apache with php. Go ahead and install it now:

 sudo apt-get install php5

Restart both servers to make the changes effective:

sudo service apache2 restart
sudo service nginx restart

Finish Up

We have set up the VPS with nginx running on the front end of our site and apache processing php on the back end. Loading our domain will take us to our site’s default page.

We can check that information is being routed to apache is working by running a common php script.

Go ahead and create the php.info file:

sudo nano /var/www/info.php

Paste the following lines into that file:

<?
phpinfo( );
?>

Save and exit.

Visiting your domain/info.php should show you php info screen, and you’ll be able to see that this was handled by apache. (screenshot here)

Finally, you can see which ports are open and which application is on each one by typing in this command.

sudo netstat -plunt

See More

Configuring nginx and Apache together can be a great boost to a server, and this was just a brief overview. If you have any specific questions about the configuring the two together, feel free to post your questions in our Q&A Forum and we’ll be happy to answer them.

By Etel Sverdlov

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
40 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Very, very good!

setup everything following the steps but only loads default nginx page from /usr/share/nginx/www instead from the /var/www

How does one get this working?

Moisey Uretsky
DigitalOcean Employee
DigitalOcean Employee badge
October 22, 2012

After updating your root path did you give nginx a restart?

Etel Sverdlov
DigitalOcean Employee
DigitalOcean Employee badge
October 22, 2012

It may also be that the default nginx page is showing up. You can disable the default nginx server block by removing it from the sites-enabled folder. I have added this step to the tutorial in “Configure nginx” step.

jason54886
DigitalOcean Employee
DigitalOcean Employee badge
November 8, 2012

Hi, in the example nginx.conf, in the PHP section, you have written “127.0.0.1:9000” in one place and “127.0.0.1:8080” in another. Is this intentional?

Etel Sverdlov
DigitalOcean Employee
DigitalOcean Employee badge
November 8, 2012

Hi Jason—thanks for catching that. It was a typo that originated because the configuration was based on the the default configs, and I had not removed that comment. It is gone now!

Thanks!

It’s awesome Etel, I’m trying Nginx+Apache on an Ubuntu 12.04, and found that the setting works right-away for most pages. However, the cgi calls seems to stuck on Nginx. I’ve tried adding the following, location ~ .cgi$ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Host $host; proxy_pass http://127.0.0.1:8080; } but no luck. Any comments?

jeff
DigitalOcean Employee
DigitalOcean Employee badge
November 27, 2012

jessehaung, I think that question might be outside the scope of this article. (I don’t know the answer off hand just by looking at your syntax).

Moisey Uretsky
DigitalOcean Employee
DigitalOcean Employee badge
November 27, 2012

Hi Jesse,

Given that the request is being redirected back to your Apache server at http://127.0.0.1:8080 you should attempt to make that request directly to the Apache server to see if its processing correctly:

telnet 127.0.0.1 8080

GET /path/to/script.php HTTP/1.1 Host: domain.com

Then you will see if Apache is returning any kind of weird behavior. Since nginx is just serving as a reverse proxy and it isn’t returning its own error it may be breaking down there.

So you would want to test each piece individually to narrow down where you may be running into an issue.

Jesse, I just wanted to let you know, more than 2 years after you posted this tip, to try telnet, with the specific instructions, this was hugely helpful to some dude (me). I had heard of telnet, but had no idea it could be used test Apache set up. It wasn’t long after trying what you suggested that I was able to get nginx running a reverse proxy to Apache, with right pho info coming back. :thumbs-up:

This worked perfectly. Thank You!

Question: If i’m going to be using wordpress, will I need to create a seperate nginx virtual hosts file for wordpress?

Moisey Uretsky
DigitalOcean Employee
DigitalOcean Employee badge
December 19, 2012

You do not to create a separate config per domain, that’s really user preference.

If the wordpress instance will be on a totally separate domain than any other domain you will need to create a new server { } block definition for it but you can put that inside of your main nginx.conf if you prefer.

Hello,

How to do this on a live website? Meaning I want to put nginx in front of Apache on a live setup.

Moisey Uretsky
DigitalOcean Employee
DigitalOcean Employee badge
December 19, 2012

We’re going to update the documentation so that it mimics a live website which will make it clearer how the reverse proxy is working.

Otherwise we end up with two localhost 127.0.0.1 configs and it can be confusing.

Thanks for writing it, it should be updated hopefully by the end of today. =]

Moisey Uretsky
DigitalOcean Employee
DigitalOcean Employee badge
December 19, 2012

We’ve cleared out a lot of the comments from the nginx config.

You will see that the server { } definition in the nginx config has a : Listen 80 Directive, which means that it’s listening on all IPs with port 80 so if you have a public IP configured on the server it will be listening.

Then the server_name directive determines which domains will be served.

The reverse proxy directive then sends requests to 127.0.0.1:8080 which is the IP and Port that Apache runs on.

This is because Apache and Nginx can not both listen on the same IP and port. This way when nginx can not handle a request it will reverse proxy it back to Apache on 127.0.0.1:8080, let Apache handle the response and send it back through Nginx.

Hopefully that clears it up for. But if you have any specific questions please let us know.

Does anyone have any experience working with HaProxy as a front end webserver and apache processing the backend? I was going to use nginx but i was getting the redirect error after installing wordpress… “redirecting in a way that will never complete”. I couldnt get that resolved after reading and trying multiple resolutions. I’m now using haproxy on port 80 and apache on port 8080, everything works great. I just need to rewrite my frontend http_proxy in my haproxy.cfg file, can anyone help possibly?

Hi! I followed your tuts and it worked like breeze. I was hoping that you should make your tutorial a little bit complete for the sake of other beginners like me. 'Twas okay overall though. And also, if you want to use Varnish, you can direct your Apache to port 8888, Nginx to 8080 and Varnish to port 80. Dunno if varnish will work (I’m about to try), but I’ve tried Apache with port 8888 and Nginx with 80 and it worked. Thanks again!

Hello,

I followed all the steps properly. Then installed mysql and setup a php script on the server. However, all .php files are loading fine but none of the .html files are loading. When the browser requests a .html page it loads back to home page. Any fix for this?

Hey Digital , I was going through your : How to Configure Nginx as a Front End Proxy for Apache article and when I get to :

sudo nano /etc/nginx/sites-available/example, I get a blank page.

So I can’t do the modifications required

Is it normal ? I run Ubuntu 12.04 LTS x64 with nginx

Etel Sverdlov
DigitalOcean Employee
DigitalOcean Employee badge
February 27, 2013

That command should give you a blank page as there is nothing there. You can fill in the page with the configuration in the article.

Additionally, you don’t have to call it /example, you can give it whatever name is convenient for you.

Could someone help ? Just did this install and in trying to install phpMyAdmin when I get to restart my apache2 server after installing phpmyadmin

I get this error when trying to access the panel through my browser :

The requested URL /index.php was not found on this server. Apache/2.2.22 (Ubuntu) Server at 198.211.101.100 Port 8080

How can I solve this ?

i am trying to set up owncloud with this nginx / apache2 setup suggested in the article.

the owncloud install suggests another nginx config file. I am a bit lost with servernames, redirection and .htaccess.

http://doc.owncloud.org/server/4.5/admin_manual/installation.html

please help me figure out what configuration changes wouls be needed in order to run owncloud in this setup.

rafael

Is there really much of a benefit to doing this in 2013? I have a MT server setup similarly but most benchmark’s I’ve seen now say Nginx, if properly configured, can handle the PHP with PHP-FPM all on its own just as well or better.

I am new at server setup. So, I got the idea that it would be awesome to combine fastCGI with nginx/apache. Google has nothing for any set that sounds like that, so I kind figured out, but am not sure, running nginx with apache includes something fastCGI already. Can you possibly tell me if that is right?

With set ups today, no, there is no benefit. The standard Wordpress.com set up would be even faster. Properly configured Nginx, php-fpm and mysql, utilizing memcache and the batcache plugin will be much faster. It’s getting fairly easy to get around Wordpress’s scalability issues, but even on smaller cloud servers, 512MB Ram and possibly 1GB Ram, the killer will be Php-fpm, it uses a lot of resources when traffic grows. For a developer working with Wordpress on a cloud server, New Relic (even the free account) can show you a lot of information that you would normally ever ever think about. I don’t recommend many products but New Relic’s system has definitively played a major part in what I do every day. Check out the wordpress optmization article by the guy from Mashable.com, http://blog.newrelic.com/2013/02/07/web-performance-optimization-automation/

If i install varnish, will be config nginx listen port?

I followed the directions and installed my wordpress, but ended up with a redirect loop error.

The wp-admin page loads fine. Any idea?

A cloned version of this article for CentOS would be nice as well =]

It’s working. What do I have to do, to make phpmyadmin works after this config???

I had to the do similar setup with one of my servers. I had to install mod_rpaf ( http://stderr.net/apache/rpaf/ ) because apache was getting 127.0.0.1 as remote_addr field.

Like many people before me, I want to know how to run phpmyadmin using this configuration. I have added location /phpmyadmin { index index.php index.html index.htm; proxy_pass http://127.0.0.1:8080/phpmyadmin; allow 1.1.1.1; #deny all; } to /etc/nginx/sites-enabled/example but that does not seem to work.

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
May 28, 2013

@Prasenjit: Check both nginx’s error logs and apache’s error logs.

Hi! It all seems to work (almost). The PHP is showing the info.php page correctly and nginx is working on port 80.

But I do bump into two problems:

  1. nginx now shows “403 Forbidden” on the domain (but not on the info.php, as this is executed via PHP, which must mean that it’s just an nginx permission issue?)
  2. When restarting Apache I keep getting “[warn] default VirtualHost overlap on port 80”

Please advise

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
June 11, 2013

Did you configure apache to listen on port 8080?

Yes. Executing “sudo netstat -plunt” shows nginx listening on “0 0.0.0.0:80” and apache on “127.0.0.1:8080”. I used to have another VirtualHost on this server before but I believe I deleted everything (/etc/nginx/sites-enabled/oldfile).

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
June 11, 2013
  1. When restarting Apache I keep getting “[warn] default VirtualHost overlap on port 80”

Delete the default virtualhost for sites-enabled.

  1. nginx now shows “403 Forbidden” on the domain (but not on the info.php, as this is executed via PHP, which must mean that it’s just an nginx permission issue?)

Try browsing to yourdomain:8080 - does it still return a 403 forbidden error? (You should also temporarily replace 127.0.0.1 with 0.0.0.0 in /etc/apache2/ports.conf so you can access it from your end)

Hi Kamal. Thanks for sticking with.

There was indeed a duplicate of a virtualhost, but in apache2/site-enabled and not in nginx/site-enabled like I was looking for. This sorted the port 80 overlap.

As for the 403 Forbidden issue, I had my Apache virtualhost root directory set wrong and it wasn’t picking up any index.php files (as there were no files in that directory).

Thanks for the help.

My new problem now is that going to the domain in the browser results in a redirect loop. Don’t even know where to start looking for the logs on this one.

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
June 12, 2013

Awesome, glad you solved the other two errors! As for the redirect loop --do you have any rewrite/redirect rules in your apache/nginx config files? If so, please pastebin your nginx and apache virtualhosts.

I actually felt frustrated enough that I already wiped everything and started over. Hopefully that will help. Will let you know how it goes. Thanks! :)

Hi, again. I set up the server with nginx handling static files and passing on PHP files to Apache. However, I bump into this problem: the server will display the homepage correctly but then when you start clicking around the page just refreshes despite the URLs changing. It’s probably easier to see than describe so please have a look:

http://miaoxren.cn will load the website first through nginx and then pass it to Apache if it’s PHP but content doesn’t load properly

http://miaoxren.cn:8080 will load the website using Apache, everything works correctly

Now, I assume the problem arises because: A) I assumed this article is about making nginx a reverse proxy to Apache, while it’s really about making it a forward proxy (the title is slightly confusing) and there is a difference that I’ve failed to grasp; B) the actual software installed is the culprit; or C) I’m still missing something from my server configuration

P.S. If this post is too much as a comment for this article, I’m happy to move it to PM or elsewhere.

Thanks!

Kamal Nasser
DigitalOcean Employee
DigitalOcean Employee badge
June 17, 2013

@witolot please pastebin both of your Apache and nginx virtualhost config files.

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.