How to setup Nginx as a Web Server and Reverse Proxy for Apache.

Introduction

A web server is a server software and hardware that uses HTTP (Hypertext Transfer Protocol) and several other related protocols to respond to client requests made over the World Wide Web. Web server is used to display website content through storing, processing, and delivering webpages to users.

According to Nginx, a reverse proxy server is a type of proxy server that typically sits behind the firewall in a private network and directs client requests to the appropriate backend server. A reverse proxy provides an additional level of abstraction and control to ensure the smooth flow of network traffic between clients and servers.

Apache and Nginx are two most widely used, free, and popular open-source web servers in the world. Apache is famous for its power and backend compatibility. Nginx is majorly known for its speed, also it provides features such as load balancing, security, and acceleration.

If you want to host multiple websites with different requirements on a virtual machine then using apache and Nginx could prove useful. One of the basic solution to run two servers on a system is to either use different port numbers or multiple IP addresses.

In this article, you will learn how to install and configure Nginx as a reverse proxy for Apache webserver.

Note: Make sure you are using Ubuntu 18.04 VPS.  

Depending on the web application, code changes might be required to keep Apache reverse-proxy-aware, especially when SSL sites are configured. To avoid this, you will install an Apache module called mod_rpaf which rewrites certain environment variables so it appears that Apache is directly handling requests from web clients.

In this tutorial, we will be hosting four domain names on one server. Two will be served by Nginx: example.com (the default virtual host) and sample.org. The remaining two, foobar.net and test.io, will be served by Apache. We’ll also configure Apache to serve PHP applications using PHP-FPM, which offers better performance over mod_php.

Prerequisites

  • A configured Ubuntu 18.04 server VPS on Digital Ocean.
  • Four valid domain names configured to point to your server’s IP address. Use proper A records, if you host your domain names elsewhere.

Step 1: Installing and configuring Apache and PHP-FPM

The first step is to install Apache and PHP-FPM.

Additionally we will install the PHP FastCGI Apache module, libapache2-mod-fastcgi, to support FastCGI web applications.

Before installing Apache update your package list to ensure you have the latest packages.

sudo apt update

Once you have the latest packages, install Apache and PHP-FPM packages:

sudo apt install apache2 php-fpm

Note:  Download the FastCGI Apache module from kernel.org as it is not available in Ubuntu’s repository. Install it using the dpkg command.

wget https://mirrors.edge.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb
 
sudo dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb

Now it’s time to change Apache’s default configuration to use PHP-FPM.

In this step, we will change Apache’s port number to 8080 and configure it to work with PHP-FPM using the mod_fastcgi module.

Rename Apache’s ports.conf configuration file:

sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.default

Create a new ports.conf file with the port set to 8080:

echo "Listen 8080" | sudo tee /etc/apache2/ports.conf

Note: By default, while configuring reverse proxy, Web servers are generally set to listen on 127.0.0.1:8080  but doing so would set the value of PHP’s environment variable SERVER_ADDR to the loopback IP address instead of the server’s public IP. We will configure websites to listen on 8080 on all IP address as we don’t want apache server to see reverse proxy in front of it.

The next step is to create a virtual host file for Apache. Disable the default virtual host:

sudo a2dissite 000-default

Now, create a new virtual host file, using the existing default site:

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

Next step is to open the new configuration file:

sudo nano /etc/apache2/sites-available/001-default.conf

Change the listening port to 8080:

<VirtualHost *:8080>
    ServerAdmin [email protected]
    DocumentRoot /var/www/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

Save the file and activate the new configuration file:

sudo a2ensite 001-default

Then reload Apache:

sudo systemctl reload apache2

Verify that Apache is now listening on 8080:

sudo netstat -tlpn

The output should look like the following example, with apache2 listening on 8080:

Output

Active Internet connections (only servers)

Proto Recv-Q Send-Q Local Address     Foreign Address      State
PID/Program name
tcp        0      0 0.0.0.0:22        0.0.0.0:*            LISTEN   1086/sshd
tcp6       0      0 :::8080           :::*                 LISTEN
4678/apache2
tcp6       0      0 :::22             :::*                 LISTEN   1086/ssh

You can configure support for PHP and FastCGI once this is done.

Step 2: Apache Configuration to use mod_fastcgi

By default, Apache serves PHP using mod PHP, but it requires additional configuration to work with PHP-FPM. We will be adding a configuration block for mod_fastcgi which depends on mod_action. mod_action is disabled by default, so we first need to enable it:

sudo a2enmod actions

Now, rename the existing FastCGI configuration file:

sudo mv /etc/apache2/mods-enabled/fastcgi.conf /etc/apache2/mods-enabled/fastcgi.conf.default

The next step is to create a new configuration file:

sudo nano /etc/apache2/mods-enabled/fastcgi.conf

Add the following directives to the file to pass requests for .php files to the PHP-FPM UNIX socket:

<IfModule mod_fastcgi.c>
  AddHandler fastcgi-script .fcgi
  FastCgiIpcDir /var/lib/apache2/fastcgi
  AddType application/x-httpd-fastphp .php
  Action application/x-httpd-fastphp /php-fcgi
  Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi
  FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -socket /run/php/php7.2-fpm.sock -pass-        header Authorization
  <Directory /usr/lib/cgi-bin>
    Require all granted
  </Directory>
</IfModule>

Save the changes and do a configuration test:

sudo apachectl -t


Reload Apache if Syntax OK is displayed:

sudo systemctl reload apache2

Note: If you see the warning 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., you can safely ignore it for now. We’ll configure server names later.

Step 3: PHP Verification Functionality

In this step, we make sure that PHP is working properly by creating a phpinfo() file and accessing it from a web browser.

First, create the file /var/www/html/info.php which contains a call to the phpinfo function:

echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

To see the file in a browser, go to http://your_server_ip:8080/info.php. This will give you a list of the configuration settings PHP is using. Check that whether Server API says FPM/FastCGI. Also check if the PHP Variables section tells you the SERVER_SOFTWARE is Apache on Ubuntu. These confirm that mod_fastcgi is active and Apache is using PHP-FPM to process PHP files.

Step 4: Creating Virtual Hosts for Apache

In this step, create Apache virtual host files for the domains foobar.net and test.io.

Create the document root directories:

sudo mkdir -v /var/www/foobar.net /var/www/test.io

Now, create an index file for each site:

echo "<h1 style='color: green;'>Foo Bar</h1>" | sudo tee /var/www/foobar.net/index.html
	
echo "<h1 style='color: red;'>Test IO</h1>" | sudo tee /var/www/test.io/index.html

Now, create a phpinfo() file for each site so we can test that PHP is configured properly.

echo "<?php phpinfo(); ?>" | sudo tee /var/www/foobar.net/info.php

echo "<?php phpinfo(); ?>" | sudo tee /var/www/test.io/info.php

Now create the virtual host file for the foobar.net domain:

sudo nano /etc/apache2/sites-available/foobar.net.conf

Add the following code to the file to define the host:

    <VirtualHost *:8080>
        ServerName foobar.net
        ServerAlias www.foobar.net
        DocumentRoot /var/www/foobar.net
        <Directory /var/www/foobar.net>
            AllowOverride All
        </Directory>
    </VirtualHost>

The line AllowOverride All enables .htaccess support.

Save and close the file.

Now, create a similar configuration for test.io. First create the file:

sudo nano /etc/apache2/sites-available/test.io.conf

Add the configuration to the file:

    <VirtualHost *:8080>
        ServerName test.io
        ServerAlias www.test.io
        DocumentRoot /var/www/test.io
        <Directory /var/www/test.io>
            AllowOverride All
        </Directory>
    </VirtualHost>

Save the file and exit the editor.

Now that both Apache virtual hosts are set up, enable the sites using the a2ensite command. This creates a symbolic link to the virtual host file in the sites-enabled directory:

sudo a2ensite foobar.net
sudo a2ensite test.io

Check Apache for configuration errors again:

sudo apachectl -t

Syntax OK message will be displayed if there are no errors. If you see anything else, review the configuration and try again. Reload Apache once all your errors are resolved.

sudo systemctl reload apache2

To confirm the sites are working, open http://foobar.net:8080 and http://test.io:8080 in your browser and verify that each site displays its index.html file. You also need to ensure that PHP is working. This can be done by accessing the info.php files for each site. Visit http://foobar.net:8080/info.php and http://test.io:8080/info.php in your browser. We now have two websites hosted on Apache at port 8080. Let’s configure Nginx next.

Step 5: Installing and Configuring Nginx

In this step, you will install Nginx and configure the domains example.com and sample.org as Nginx’s virtual hosts.

First, install Nginx using the package manager:

sudo apt install nginx

Remove the default virtual host’s symlink

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

You will create your own default site later (example.com).

Now let’s create virtual hosts for Nginx First step is to create document root directories for both the websites:

sudo mkdir -v /usr/share/nginx/example.com /usr/share/nginx/sample.org

The next step is to create index and phpinfo() files for testing after setup is complete:

echo "<h1 style='color: green;'>Example.com</h1>" | sudo tee /usr/share/nginx/example.com/index.html
	

echo "<h1 style='color: red;'>Sample.org</h1>" | sudo tee /usr/share/nginx/sample.org/index.html
	

echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/example.com/info.php

echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/sample.org/info.php

Create a virtual host file for the domain example.com:

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

Nginx calls server {. . .} areas of a configuration file server blocks. Create a server block for the primary virtual host, example.com.

server {
    listen 80 default_server;

    root /usr/share/nginx/example.com;
    index index.php index.html index.htm;

    server_name example.com www.example.com;
    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        include snippets/fastcgi-php.conf;
    }
}

Copy, Save and close the file.

Now let’s create a virtual host file for Nginx’s second domain, sample.org:

sudo nano etc/nginx/sites-available/sample.org

Add the following to the file:

server {
    root /usr/share/nginx/sample.org;
    index index.php index.html index.htm;

    server_name sample.org www.sample.org;
    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        include snippets/fastcgi-php.conf;
    }
}

Copy, Save and close the file.

Now, enable both sites by creating symbolic links to the sites-enabled directory:

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

sudo ln -s /etc/nginx/sites-available/sample.org /etc/nginx/sites-enabled/sample.org
	

Test the Nginx configuration for erros.

sudo nginx -t

Reload Nginx if there are no errors:

sudo systemctl reload nginx

Now access the phpinfo() file of your Nginx virtual hosts in a web browser by visiting http://example.com/info.php and http://sample.org/info.php. In PHP Variables sections, [“SERVER_SOFTWARE”] should say nginx, and  [“DOCUMENT_ROOT”] should point to the directory you created earlier in this step for each Nginx site.

Until now you have installed Nginx and created two virtual hosts. The next step is to configure Nginx to proxy requests meant for domains hosted on Apache.

Step 6: Configuring Nginx for Apache’s Virtual Host.

In this step you will create an additional Nginx virtual host with multiple domain names in the server_name directives. Requests for these domain names will be proxied to Apache.

First, ceate a new Nginx virtual host file to forward requests to Apache:

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

Add the following code block. Remember to use the public IP address in proxy_pass:

server {
    listen 80;
    server_name foobar.net www.foobar.net test.io www.test.io;

    location / {
        proxy_pass http://your_server_ip:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Copy and Save the file. Enable this new virtual host by creating a symbolic link:

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

Test the configuration to ensure there are no errors:

sudo nginx -t

Reload Nginx, if there are no errors:

sudo systemctl reload nginx

Open the browser and access the URL http://foobar.net/info.php in your browser. Scroll down to the PHP Variables section and check the values displayed.

The variable SERVER_SOFTWARE should show “Apache” and DOCUMENT_ROOT should show “/var/www.foobar.net”. This confirms that the request was handled by Apache. Nginx adds variables HTTP_X_REAL_IP and HTTP_X_FORWARDED_FOR. They should show the public IP address of the computer you’re using to access the URL.

You have successfully set up Nginx to proxy requests for specific domains to Apache. The next step is to configure Apache to set the REMOTE_ADDR variable.

Step 7: Installing and Configuring mod_rpaf

In this step you will install an mod\_rpaf  Apache module. This module rewrites the values of REMOTE_ADDRHTTPS and HTTP_PORT based on the values provided by a reverse proxy. Without this module, some PHP applications would require code changes to work seamlessly from behind a proxy.

This module is present in Ubuntu’s repository as libapache2-mod-rpaf but is outdated and doesn’t support certain configuration directives. Instead, we recommend you to install it from source.

The first step is to install the packages needed to build the module:

sudo apt install unzip build-essential apache2-dev

Now, download the latest stable release from GitHub:

wget https://github.com/gnif/mod_rpaf/archive/stable.zip

Now, Extract the downloaded file:

unzip stable.zip

The next step is to change into the new directory containing the files:

cd mod_rpaf-stable

Compile and install the module:

make
	
sudo make install

Create a file in the mods-available directory which will load the rpaf module:

sudo nano /etc/apache2/mods-available/rpaf.load

Add the following code to the file to load the module:

LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so

Save the file and exit the editor.

Now, create another file in this directory called rpaf.conf. It will contain the configuration directives for mod_rpaf:

sudo nano /etc/apache2/mods-available/rpaf.conf

Add the following code to configure mod_rpaf.  Specify the IP address of your server.

<IfModule mod_rpaf.c>
        RPAF_Enable             On
        RPAF_Header             X-Real-Ip
        RPAF_ProxyIPs           your_server_ip 
        RPAF_SetHostName        On
        RPAF_SetHTTPS           On
        RPAF_SetPort            On
    </IfModule>

Save rpaf.conf and enable the module:

sudo a2enmod rpaf

This creates symbolic links of the files rpaf.load and rpaf.conf in the mods-enabled directory. Now do a configuration test:

sudo apachectl -t

Reload Apache if there are no errors:

sudo systemctl reload apache2

Now, access the phpinfo() pages http://foobar.net/info.php and http://test.io/info.php in your browser and check the PHP Variables section. The REMOTE_ADDR variable will now show your local computer’s public IP address.

Conclusion

Congratulations! You have successfully installed and configured Nginx as a reverse proxy for Apache webserver.  This article was written with reference to the Digital Ocean “How To Configure Nginx as a Web Server and Reverse Proxy for Apache on One Ubuntu 18.04 Server”. Visit Digital Ocean VPS pricing page to find a hosting package that’s right for you.

We hope this article helps you to clear you doubts. Please drop your queries in the comment section.

Also, if you want us to cover a specific topic, you can drop that into the comment section as well.

Recent Articles

Fix-iPhone Hotspot Not Working

Network related issues are the common problems that we all encounter while using a smartphone. Are you facing a problem using your...

Snapchat streak Made Easy for Beginners with the Best Tips

Snapchat streak won’t help you with all your life problems, but will surely give you a strange sense of accomplishment. Unlike streaks...

Facebook Messenger Alternatives that Keep Your Chat Private

Facebook might be the king of social media ever since its launch 16 years ago, but it is not entirely safe. If...

How to use iOS 14’s new Headphone Audio Customization feature

Apple’s iOS14 comes with several new features. Among them, the most useful feature is it allows to customize iPhone headphone for a...

How to limit third party access to Photos app in iPhone – iOS 14

The new iOS 14 has introduced several new features related to security and privacy. If you are more concerned about your privacy then...

Related Stories

Leave A Reply

Please enter your comment!
Please enter your name here