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?
 
10 Comments


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!

I have followed this tutorial as it is to install the nginix and apache together in a new basic droplet with ubuntu 14.04 64bit but unable to install it successfully. Everything went well till installing apache. When trying to change the ports as below 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

I don’t find this at all and my initial files look like

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.conf

Listen 80

<IfModule ssl_module> Listen 443 </IfModule>

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

vim: syntax=apache ts=4 sw=4 sts=4 sr noet

In this i have changed Listen 80 to 8080 and added the below two lines at the end of the file. NameVirtualHost 127.0.0.1:8080 Listen 127.0.0.1:8080

And then followed the next steps

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

After opening the file i dont see the line <VirtualHost 127.0.0.1:8080> in the file. Can someone guide me on this

Thanks in Advance and looking forward.

Just a heads up, in Ubuntu 13 /etc/apache2/sites-available/default has been renamed to 000-default.conf

Also, remember to add .conf to the end of your file as well or it won’t be recognized. Use:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/example.conf

I ran into the following errors when installing Apache:

* Starting web server apache2                                                                                                                                                       AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message
(98)Address already in use: AH00072: make_sock: could not bind to address [::]:80
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80
no listening sockets available, shutting down
AH00015: Unable to open logs
Action 'start' failed.
The Apache error log may have more information.

Then:

me@hostname:~$ sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/example
cp: cannot stat ‘/etc/apache2/sites-available/default’: No such file or directory
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.

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.

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?

I have a question – is this tutorial relevant for Debian 10, because it is written in 2012?

Hello, i am curios, if on Nginx i have worker_processes = 2 and worker_connections = 1024 that means a maximum of 2048 clients, and if on Apache i have a maximum of let’s say 700 clients (i don’t know the exact value), will work with the maximum clients from Nginx and the performance?

Hi I know this tutorial is old, but please fix the info.php test script, the first line needs to read

<?php

Or it will not get interpreted as a PHP script, and just render as a blank page.

I get as far as sudo cp /etc/apache2/sites-available/default /etc/apache2/sites-available/example

When I get this error cp: cannot stat ‘/etc/apache2/sites-available/default’: No such file or directory

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.