Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Linux: Powerful Server Administration

You're reading from   Linux: Powerful Server Administration Recipes for CentOS 7, RHEL 7, and Ubuntu Server Administration

Arrow left icon
Product type Course
Published in Apr 2017
Publisher Packt
ISBN-13 9781788293778
Length 995 pages
Edition 1st Edition
Tools
Arrow right icon
Authors (4):
Arrow left icon
Uday Sawant Uday Sawant
Author Profile Icon Uday Sawant
Uday Sawant
William Leemans William Leemans
Author Profile Icon William Leemans
William Leemans
Jonathan Hobson Jonathan Hobson
Author Profile Icon Jonathan Hobson
Jonathan Hobson
Oliver Pelz Oliver Pelz
Author Profile Icon Oliver Pelz
Oliver Pelz
Arrow right icon
View More author details
Toc

Chapter 3. Working with Web Servers

In this chapter, we will cover the following recipes:

  • Installing and configuring the Apache web server
  • Serving dynamic contents with PHP
  • Hosting multiple websites with a virtual domain
  • Securing web traffic with HTTPS
  • Installing Nginx with PHP_FPM
  • Setting Nginx as a reverse proxy
  • Load balancing with Nginx
  • Setting HTTPs on Nginx
  • Benchmarking and performance tuning of Apache
  • Securing the web server
  • Troubleshooting the web server

Introduction

A web server is a tool that publishes documents on a network, generally the Internet. HTTP is called a language of the Internet and web servers, apart from browsers, are native speakers of HTTP. Web servers generally listen on one or multiple ports for requests from clients and accept requests in the form of URLs and HTTP headers. On receiving a request, web servers look for the availability of the requested resource and return the contents to the client. The term web server can refer to one or multiple physical servers or a software package, or both of them working together.

Some well known web servers include the Apache web server, Microsoft IIS, and Nginx. Apache web server is the most popular web server package available across platforms such as Windows and Linux. It is an open source project and freely available for commercial use. Nginx, which is again an open source web server project, started to overcome the problems in a high-load environment. Because of its lightweight resource utilization and ability to scale even on minimal hardware, Nginx quickly became a well known name. Nginx offers a free community edition as well as a paid commercial version with added support and extra features. Lastly, Microsoft IIS is a web server specifically designed for Windows servers. Apache still has the major share in the web server market, with Nginx rapidly taking over with some other notable alternatives such as lighttpd and H2O.

Apache is a modularized web server that can be extended by dynamically loading extra modules as and when required. This provides the flexibility to run a bare minimum web server or a fully featured box with modules to support compression, SSL, redirects, language modules, and more. Apache provides multiple connection processing algorithms called multi-processing modules (MPM). It provides an option to create a separate single threaded process for each new request (mpm_prefork), a multi-threaded process that can handle multiple concurrent requests (mpm_worker), or the latest development of mpm_event, which separates the active and idle connections.

Nginx can be considered the next generation of web servers. Its development started to solve the C10k problem, that is, handling ten thousand connections at a time. Apache, being a process-driven model, has some limitations when handling multiple concurrent connections. Nginx took advantage of the event-driven approach with asynchronous, non-blocking connection handling algorithms. A new connection request is handled by a worker process and placed in an event loop where they are continuously checked for events. The events are processed asynchronously. This approach enables Nginx to run with a much lower memory footprint and lower CPU use. It also eliminates the overload of starting a new process for a new connection. A single worker process started by Nginx can handle thousands of concurrent connections.

Tip

It is possible that some terms used throughout this chapter are unknown to you. It is not possible to explain everything in a Cookbook format. A quick Google search for a term will give you more details on them.

Both Apache and Nginx can be configured to process dynamic contents. Apache provides respective language processors such as mod_php and mod_python to process dynamic contents within the worker process itself. Nginx depends on external processors and uses CGI protocols to communicate with external processors. Apache can also be configured to use an external language processor over CGI, but the choice depends on performance and security considerations.

While both Apache and Nginx provide various similar features, they are not entirely interchangeable. Each one has its own pros and cons. Where Nginx excels at serving static contents, Apache performs much better processing dynamic contents. Many web administrators prefer to use Apache and Nginx together.

Note

Nginx is commonly used as a frontend caching/reverse proxy handling client requests and serving static contents, while Apache is used as a backend server processing dynamic contents.

Nginx handles a large number of connections and passes limited requests of dynamic contents to backend Apache servers. This configuration also allows users to scale horizontally by adding multiple backend servers and setting Nginx as a load balancer.

In this chapter, we will be working with both Apache and Nginx servers. We will learn how to set up Apache with PHP as a language for dynamic contents. We will look at some important configurations of Apache. Later, we will set up Nginx with an optional PHP processor, PHP_FPM, and configure Nginx to work as a reverse proxy and load balancer. We will also look at performance and security configurations for both the servers.

Installing and configuring the Apache web server

In this recipe, we will simply install the Apache web server from the Ubuntu package repository. We will also look at the basic configuration options and set up our first web page.

Getting ready

You will need access to a root account or an account with sudo privileges.

I will be using Apache to refer to the Apache web server. The Apache web server is the most popular project by the Apache Foundation and is generally known as just Apache.

How to do it…

Follow these steps to install and configure the Apache web server:

  1. Install Apache2 from the Ubuntu package repository:
    $ sudo apt-get update
    $ sudo apt-get install apache2
    
  2. Check if Apache2 has installed successfully. The command wget should download the index.html file:
    $ wget 127.0.0.1
    
    How to do it…
  3. You can also open a browser on a local machine and point it to the server IP address. You should see a default It works! page customized for Ubuntu:
    How to do it…
  4. Now, let's proceed with creating our first virtual host. First create a directory structure. Change the directory to /var/www/ and create a new directory for the contents of our site:
    $ cd /var/www
    $ sudo mkdir example.com
    
  5. Change the ownership and group of the directory example.com:
    $ sudo chown ubuntu:www-data example.com
    
  6. Set the file permissions to secure web contents:
    $ sudo chmod 750 example.com
    
  7. Create the required directories under the example.com directory:
    $ cd example.com
    $ mkdir public_html
    
  8. Create a index.html file under the public_html directory:
    $ echo '<b>Hello World ...</b>' > public_html/index.html
    
  9. Next, we need to set up a new virtual host under the Apache configuration.
  10. Copy the default Virtual Host file under /etc/apache2/sites-available and use it as a starting point for our configuration:
    $ cd /etc/apache2/sites-available
    $ sudo cp 000-default.conf example.com.conf
    
  11. Edit example.com.conf to match it with the following example. Change the parameters as per your requirements:
    How to do it…
  12. Save the changes and exit example.com.conf.
  13. If you are using the same port as the default VirtualHost, do not forget to disable the default one:
    $ sudo a2dissite 000-default.conf
    
  14. Finally, enable our new VirtualHost with a2ensite and reload Apache:
    $ sudo a2ensite example.com.conf
    $ sudo service apache2 reload
    
  15. Start your browser and point it to the domain or IP address of your server:
    How to do it…

How it works…

The Apache package for Ubuntu is included in the default package repository. We need a single command to install the Apache web server. Installation creates a structure of configuration files under /etc/apache2 and a sample web page under /var/www/html.

As mentioned in the default It works! page, Apache2 does not use a single configuration file such as httpd.conf in older versions, but rather separates its configuration across multiple configuration files. These files are named after their respective uses. apache2.conf is now a main configuration file and creates a central configuration by including all other files.

conf-available, mods-available, and sites-available contain configuration snippets and other files for global configurations, modules, and virtual hosts respectively. These configurations are selectively activated under their enabled counterparts with symbolic links for each configuration to be enabled.

envvars contains all environment variables and default values for Apache to work.

ports.conf defines the ports Apache should listen on.

The default web page is created under the /var/www/html directory.

In this recipe, we have created our virtual host for the domain name example.com and hosted it under the directory /var/www/example.com. Next, we have to change the owner and default group of this directory to the user, ubuntu and group, www-data. This grants full access to the user ubuntu and allows read and execute access to the group www-data. If you have observed the contents of the envvars file, you may have noticed that the variable APACHE_RUN_GROUP is set to www-data. This means Apache process will be started as the group www-data. By setting a default group, we have allowed Apache process to read the contents of the example.com directory. We have also enabled write access to the logs directory so that Apache processes can log to this directory.

After creating the virtual host configuration and setting the respective options, all we need to do is enable a new virtual host or site. Apache2 provides the respective commands to enable or disable configurations, modules, and sites. a2ensite will be used to enable the site from options available under sites-available. Basically, this will create a symbolic link under the sites-enabled directory to a specified site configuration. Similarly, a2dissite will disable the site by removing the symbolic link from the sites-enabled directory. Similar commands are available to work with configurations and modules.

There's more…

You may want to get rid of the warning that says Could not reliably determine the server's fully qualified domain name. This warning appears because the Apache process could not find the default FQDN for this server. You can set the default FQDN simply by creating a new configuration file and then enabling this new configuration:

  1. Create a new file under the conf-available directory:
    $ sudo vi /etc/apache2/conf-available/fqdn.conf
    
  2. Add a server name variable to this file:
    ServerName  localhost
    
  3. Save the changes and enable this configuration:
    $ sudo a2enconf fqdn
    
  4. Reload the Apache server:
    $ sudo service apache2 reload
    

HTTP version 2 support

If you are looking for HTTP2 support, Apache does provide a separate module for that. Apache version 2.4.17 ships with a module, mod_http2, that implements the latest HTTP version, HTTP2. It is still an experimental implementation and needs to be enabled manually. This version of Apache (2.4.17) is available with Ubuntu Xenial (16.04) in the default package repository. If you are using Ubuntu 14.04, you can use the external repository as follows:

$ sudo add-apt-repository -y ppa:ondrej/apache2

Once the required version of Apache is installed, you can enable mod_http2 as follows:

$ sudo a2enmod http2

Next, edit the specific virtual host file to enable the HTTP2 protocol for a specific site. Note that you need to configure your site to use an SSL/TLS connection:

<VirtualHost *:443>
    Protocols h2 http/1.1
    ...
</VirtualHost>

Finally, restart your Apache server:

$ sudo service apache2 restart

H2O, the new name in web servers, is developed around the HTTP2 protocol. It does support both HTTP 1.1 and a stable implementation of the HTTP2 protocol. You may want to check this out as your local or development server.

See also

You can read more by following the links:

Getting ready

You will need access to a root account or an account with sudo privileges.

I will be using Apache to refer to the Apache web server. The Apache web server is the most popular project by the Apache Foundation and is generally known as just Apache.

How to do it…

Follow these steps to install and configure the Apache web server:

  1. Install Apache2 from the Ubuntu package repository:
    $ sudo apt-get update
    $ sudo apt-get install apache2
    
  2. Check if Apache2 has installed successfully. The command wget should download the index.html file:
    $ wget 127.0.0.1
    
    How to do it…
  3. You can also open a browser on a local machine and point it to the server IP address. You should see a default It works! page customized for Ubuntu:
    How to do it…
  4. Now, let's proceed with creating our first virtual host. First create a directory structure. Change the directory to /var/www/ and create a new directory for the contents of our site:
    $ cd /var/www
    $ sudo mkdir example.com
    
  5. Change the ownership and group of the directory example.com:
    $ sudo chown ubuntu:www-data example.com
    
  6. Set the file permissions to secure web contents:
    $ sudo chmod 750 example.com
    
  7. Create the required directories under the example.com directory:
    $ cd example.com
    $ mkdir public_html
    
  8. Create a index.html file under the public_html directory:
    $ echo '<b>Hello World ...</b>' > public_html/index.html
    
  9. Next, we need to set up a new virtual host under the Apache configuration.
  10. Copy the default Virtual Host file under /etc/apache2/sites-available and use it as a starting point for our configuration:
    $ cd /etc/apache2/sites-available
    $ sudo cp 000-default.conf example.com.conf
    
  11. Edit example.com.conf to match it with the following example. Change the parameters as per your requirements:
    How to do it…
  12. Save the changes and exit example.com.conf.
  13. If you are using the same port as the default VirtualHost, do not forget to disable the default one:
    $ sudo a2dissite 000-default.conf
    
  14. Finally, enable our new VirtualHost with a2ensite and reload Apache:
    $ sudo a2ensite example.com.conf
    $ sudo service apache2 reload
    
  15. Start your browser and point it to the domain or IP address of your server:
    How to do it…

How it works…

The Apache package for Ubuntu is included in the default package repository. We need a single command to install the Apache web server. Installation creates a structure of configuration files under /etc/apache2 and a sample web page under /var/www/html.

As mentioned in the default It works! page, Apache2 does not use a single configuration file such as httpd.conf in older versions, but rather separates its configuration across multiple configuration files. These files are named after their respective uses. apache2.conf is now a main configuration file and creates a central configuration by including all other files.

conf-available, mods-available, and sites-available contain configuration snippets and other files for global configurations, modules, and virtual hosts respectively. These configurations are selectively activated under their enabled counterparts with symbolic links for each configuration to be enabled.

envvars contains all environment variables and default values for Apache to work.

ports.conf defines the ports Apache should listen on.

The default web page is created under the /var/www/html directory.

In this recipe, we have created our virtual host for the domain name example.com and hosted it under the directory /var/www/example.com. Next, we have to change the owner and default group of this directory to the user, ubuntu and group, www-data. This grants full access to the user ubuntu and allows read and execute access to the group www-data. If you have observed the contents of the envvars file, you may have noticed that the variable APACHE_RUN_GROUP is set to www-data. This means Apache process will be started as the group www-data. By setting a default group, we have allowed Apache process to read the contents of the example.com directory. We have also enabled write access to the logs directory so that Apache processes can log to this directory.

After creating the virtual host configuration and setting the respective options, all we need to do is enable a new virtual host or site. Apache2 provides the respective commands to enable or disable configurations, modules, and sites. a2ensite will be used to enable the site from options available under sites-available. Basically, this will create a symbolic link under the sites-enabled directory to a specified site configuration. Similarly, a2dissite will disable the site by removing the symbolic link from the sites-enabled directory. Similar commands are available to work with configurations and modules.

There's more…

You may want to get rid of the warning that says Could not reliably determine the server's fully qualified domain name. This warning appears because the Apache process could not find the default FQDN for this server. You can set the default FQDN simply by creating a new configuration file and then enabling this new configuration:

  1. Create a new file under the conf-available directory:
    $ sudo vi /etc/apache2/conf-available/fqdn.conf
    
  2. Add a server name variable to this file:
    ServerName  localhost
    
  3. Save the changes and enable this configuration:
    $ sudo a2enconf fqdn
    
  4. Reload the Apache server:
    $ sudo service apache2 reload
    

HTTP version 2 support

If you are looking for HTTP2 support, Apache does provide a separate module for that. Apache version 2.4.17 ships with a module, mod_http2, that implements the latest HTTP version, HTTP2. It is still an experimental implementation and needs to be enabled manually. This version of Apache (2.4.17) is available with Ubuntu Xenial (16.04) in the default package repository. If you are using Ubuntu 14.04, you can use the external repository as follows:

$ sudo add-apt-repository -y ppa:ondrej/apache2

Once the required version of Apache is installed, you can enable mod_http2 as follows:

$ sudo a2enmod http2

Next, edit the specific virtual host file to enable the HTTP2 protocol for a specific site. Note that you need to configure your site to use an SSL/TLS connection:

<VirtualHost *:443>
    Protocols h2 http/1.1
    ...
</VirtualHost>

Finally, restart your Apache server:

$ sudo service apache2 restart

H2O, the new name in web servers, is developed around the HTTP2 protocol. It does support both HTTP 1.1 and a stable implementation of the HTTP2 protocol. You may want to check this out as your local or development server.

See also

You can read more by following the links:

How to do it…

Follow these steps to install and configure the Apache web server:

  1. Install Apache2 from the Ubuntu package repository:
    $ sudo apt-get update
    $ sudo apt-get install apache2
    
  2. Check if Apache2 has installed successfully. The command wget should download the index.html file:
    $ wget 127.0.0.1
    
    How to do it…
  3. You can also open a browser on a local machine and point it to the server IP address. You should see a default It works! page customized for Ubuntu:
    How to do it…
  4. Now, let's proceed with creating our first virtual host. First create a directory structure. Change the directory to /var/www/ and create a new directory for the contents of our site:
    $ cd /var/www
    $ sudo mkdir example.com
    
  5. Change the ownership and group of the directory example.com:
    $ sudo chown ubuntu:www-data example.com
    
  6. Set the file permissions to secure web contents:
    $ sudo chmod 750 example.com
    
  7. Create the required directories under the example.com directory:
    $ cd example.com
    $ mkdir public_html
    
  8. Create a index.html file under the public_html directory:
    $ echo '<b>Hello World ...</b>' > public_html/index.html
    
  9. Next, we need to set up a new virtual host under the Apache configuration.
  10. Copy the default Virtual Host file under /etc/apache2/sites-available and use it as a starting point for our configuration:
    $ cd /etc/apache2/sites-available
    $ sudo cp 000-default.conf example.com.conf
    
  11. Edit example.com.conf to match it with the following example. Change the parameters as per your requirements:
    How to do it…
  12. Save the changes and exit example.com.conf.
  13. If you are using the same port as the default VirtualHost, do not forget to disable the default one:
    $ sudo a2dissite 000-default.conf
    
  14. Finally, enable our new VirtualHost with a2ensite and reload Apache:
    $ sudo a2ensite example.com.conf
    $ sudo service apache2 reload
    
  15. Start your browser and point it to the domain or IP address of your server:
    How to do it…

How it works…

The Apache package for Ubuntu is included in the default package repository. We need a single command to install the Apache web server. Installation creates a structure of configuration files under /etc/apache2 and a sample web page under /var/www/html.

As mentioned in the default It works! page, Apache2 does not use a single configuration file such as httpd.conf in older versions, but rather separates its configuration across multiple configuration files. These files are named after their respective uses. apache2.conf is now a main configuration file and creates a central configuration by including all other files.

conf-available, mods-available, and sites-available contain configuration snippets and other files for global configurations, modules, and virtual hosts respectively. These configurations are selectively activated under their enabled counterparts with symbolic links for each configuration to be enabled.

envvars contains all environment variables and default values for Apache to work.

ports.conf defines the ports Apache should listen on.

The default web page is created under the /var/www/html directory.

In this recipe, we have created our virtual host for the domain name example.com and hosted it under the directory /var/www/example.com. Next, we have to change the owner and default group of this directory to the user, ubuntu and group, www-data. This grants full access to the user ubuntu and allows read and execute access to the group www-data. If you have observed the contents of the envvars file, you may have noticed that the variable APACHE_RUN_GROUP is set to www-data. This means Apache process will be started as the group www-data. By setting a default group, we have allowed Apache process to read the contents of the example.com directory. We have also enabled write access to the logs directory so that Apache processes can log to this directory.

After creating the virtual host configuration and setting the respective options, all we need to do is enable a new virtual host or site. Apache2 provides the respective commands to enable or disable configurations, modules, and sites. a2ensite will be used to enable the site from options available under sites-available. Basically, this will create a symbolic link under the sites-enabled directory to a specified site configuration. Similarly, a2dissite will disable the site by removing the symbolic link from the sites-enabled directory. Similar commands are available to work with configurations and modules.

There's more…

You may want to get rid of the warning that says Could not reliably determine the server's fully qualified domain name. This warning appears because the Apache process could not find the default FQDN for this server. You can set the default FQDN simply by creating a new configuration file and then enabling this new configuration:

  1. Create a new file under the conf-available directory:
    $ sudo vi /etc/apache2/conf-available/fqdn.conf
    
  2. Add a server name variable to this file:
    ServerName  localhost
    
  3. Save the changes and enable this configuration:
    $ sudo a2enconf fqdn
    
  4. Reload the Apache server:
    $ sudo service apache2 reload
    

HTTP version 2 support

If you are looking for HTTP2 support, Apache does provide a separate module for that. Apache version 2.4.17 ships with a module, mod_http2, that implements the latest HTTP version, HTTP2. It is still an experimental implementation and needs to be enabled manually. This version of Apache (2.4.17) is available with Ubuntu Xenial (16.04) in the default package repository. If you are using Ubuntu 14.04, you can use the external repository as follows:

$ sudo add-apt-repository -y ppa:ondrej/apache2

Once the required version of Apache is installed, you can enable mod_http2 as follows:

$ sudo a2enmod http2

Next, edit the specific virtual host file to enable the HTTP2 protocol for a specific site. Note that you need to configure your site to use an SSL/TLS connection:

<VirtualHost *:443>
    Protocols h2 http/1.1
    ...
</VirtualHost>

Finally, restart your Apache server:

$ sudo service apache2 restart

H2O, the new name in web servers, is developed around the HTTP2 protocol. It does support both HTTP 1.1 and a stable implementation of the HTTP2 protocol. You may want to check this out as your local or development server.

See also

You can read more by following the links:

How it works…

The Apache package for Ubuntu is included in the default package repository. We need a single command to install the Apache web server. Installation creates a structure of configuration files under /etc/apache2 and a sample web page under /var/www/html.

As mentioned in the default It works! page, Apache2 does not use a single configuration file such as httpd.conf in older versions, but rather separates its configuration across multiple configuration files. These files are named after their respective uses. apache2.conf is now a main configuration file and creates a central configuration by including all other files.

conf-available, mods-available, and sites-available contain configuration snippets and other files for global configurations, modules, and virtual hosts respectively. These configurations are selectively activated under their enabled counterparts with symbolic links for each configuration to be enabled.

envvars contains all environment variables and default values for Apache to work.

ports.conf defines the ports Apache should listen on.

The default web page is created under the /var/www/html directory.

In this recipe, we have created our virtual host for the domain name example.com and hosted it under the directory /var/www/example.com. Next, we have to change the owner and default group of this directory to the user, ubuntu and group, www-data. This grants full access to the user ubuntu and allows read and execute access to the group www-data. If you have observed the contents of the envvars file, you may have noticed that the variable APACHE_RUN_GROUP is set to www-data. This means Apache process will be started as the group www-data. By setting a default group, we have allowed Apache process to read the contents of the example.com directory. We have also enabled write access to the logs directory so that Apache processes can log to this directory.

After creating the virtual host configuration and setting the respective options, all we need to do is enable a new virtual host or site. Apache2 provides the respective commands to enable or disable configurations, modules, and sites. a2ensite will be used to enable the site from options available under sites-available. Basically, this will create a symbolic link under the sites-enabled directory to a specified site configuration. Similarly, a2dissite will disable the site by removing the symbolic link from the sites-enabled directory. Similar commands are available to work with configurations and modules.

There's more…

You may want to get rid of the warning that says Could not reliably determine the server's fully qualified domain name. This warning appears because the Apache process could not find the default FQDN for this server. You can set the default FQDN simply by creating a new configuration file and then enabling this new configuration:

  1. Create a new file under the conf-available directory:
    $ sudo vi /etc/apache2/conf-available/fqdn.conf
    
  2. Add a server name variable to this file:
    ServerName  localhost
    
  3. Save the changes and enable this configuration:
    $ sudo a2enconf fqdn
    
  4. Reload the Apache server:
    $ sudo service apache2 reload
    

HTTP version 2 support

If you are looking for HTTP2 support, Apache does provide a separate module for that. Apache version 2.4.17 ships with a module, mod_http2, that implements the latest HTTP version, HTTP2. It is still an experimental implementation and needs to be enabled manually. This version of Apache (2.4.17) is available with Ubuntu Xenial (16.04) in the default package repository. If you are using Ubuntu 14.04, you can use the external repository as follows:

$ sudo add-apt-repository -y ppa:ondrej/apache2

Once the required version of Apache is installed, you can enable mod_http2 as follows:

$ sudo a2enmod http2

Next, edit the specific virtual host file to enable the HTTP2 protocol for a specific site. Note that you need to configure your site to use an SSL/TLS connection:

<VirtualHost *:443>
    Protocols h2 http/1.1
    ...
</VirtualHost>

Finally, restart your Apache server:

$ sudo service apache2 restart

H2O, the new name in web servers, is developed around the HTTP2 protocol. It does support both HTTP 1.1 and a stable implementation of the HTTP2 protocol. You may want to check this out as your local or development server.

See also

You can read more by following the links:

There's more…

You may want to get rid of the warning that says Could not reliably determine the server's fully qualified domain name. This warning appears because the Apache process could not find the default FQDN for this server. You can set the default FQDN simply by creating a new configuration file and then enabling this new configuration:

  1. Create a new file under the conf-available directory:
    $ sudo vi /etc/apache2/conf-available/fqdn.conf
    
  2. Add a server name variable to this file:
    ServerName  localhost
    
  3. Save the changes and enable this configuration:
    $ sudo a2enconf fqdn
    
  4. Reload the Apache server:
    $ sudo service apache2 reload
    

HTTP version 2 support

If you are looking for HTTP2 support, Apache does provide a separate module for that. Apache version 2.4.17 ships with a module, mod_http2, that implements the latest HTTP version, HTTP2. It is still an experimental implementation and needs to be enabled manually. This version of Apache (2.4.17) is available with Ubuntu Xenial (16.04) in the default package repository. If you are using Ubuntu 14.04, you can use the external repository as follows:

$ sudo add-apt-repository -y ppa:ondrej/apache2

Once the required version of Apache is installed, you can enable mod_http2 as follows:

$ sudo a2enmod http2

Next, edit the specific virtual host file to enable the HTTP2 protocol for a specific site. Note that you need to configure your site to use an SSL/TLS connection:

<VirtualHost *:443>
    Protocols h2 http/1.1
    ...
</VirtualHost>

Finally, restart your Apache server:

$ sudo service apache2 restart

H2O, the new name in web servers, is developed around the HTTP2 protocol. It does support both HTTP 1.1 and a stable implementation of the HTTP2 protocol. You may want to check this out as your local or development server.

See also

You can read more by following the links:

HTTP version 2 support

If you are looking for HTTP2 support, Apache does provide a separate module for that. Apache version 2.4.17 ships with a module, mod_http2, that implements the latest HTTP version, HTTP2. It is still an experimental implementation and needs to be enabled manually. This version of Apache (2.4.17) is available with Ubuntu Xenial (16.04) in the default package repository. If you are using Ubuntu 14.04, you can use the external repository as follows:

$ sudo add-apt-repository -y ppa:ondrej/apache2

Once the required version of Apache is installed, you can enable mod_http2 as follows:

$ sudo a2enmod http2

Next, edit the specific virtual host file to enable the HTTP2 protocol for a specific site. Note that you need to configure your site to use an SSL/TLS connection:

<VirtualHost *:443>
    Protocols h2 http/1.1
    ...
</VirtualHost>

Finally, restart your Apache server:

$ sudo service apache2 restart

H2O, the new name in web servers, is developed around the HTTP2 protocol. It does support both HTTP 1.1 and a stable implementation of the HTTP2 protocol. You may want to check this out as your local or development server.

See also

You can read more by following the links:

See also

You can read more by following the links:

Serving dynamic contents with PHP

In this recipe, we will learn how to install PHP and set it to work alongside the Apache web server. We will install PHP binaries and then the Apache module mod_php to support PHP-based dynamic contents.

Getting ready

You will need access to a root account or an account with sudo privileges.

The Apache web server should be installed and working properly.

How to do it…

Follow these steps to serve dynamic contents with PHP:

  1. Install PHP7 and the Apache module for PHP support:
    $ sudo apt-get update
    $ sudo apt-get install -y php7.0 libapache2-mod-php7.0
    
  2. Check if PHP is properly installed and which version has been installed:
    $ php -v
    
    How to do it…
  3. Create index.php under the public_html directory of our site:
    $ cd /var/www/example.com/public_html
    $ vi index.php
    
  4. Add the following contents to index.php:
    <?php echo phpinfo(); ?>
    
  5. Save and exit the index.php file.
  6. Open example.com.conf from sites-available:
    $ sudo vi /etc/apache2/sites-available/example.com.conf
    
  7. Add the following line under the VirtualHost directive:
    DirectoryIndex index.php index.html
    
    How to do it…
  8. Save the changes and reload Apache:
    $ sudo service apache2 reload
    
  9. Now, access your site with your browser, and you should see a page with information regarding the installed PHP:
    How to do it…

How it works…

Here, we have installed PHP binaries on our server along with the Apache module libapache2-mod-php7.0 to support dynamic content coded in PHP. A module, mod_php, runs inside Apache process and processes PHP scripts from within Apache itself. For mod_php to work, Apache needs to run with the mpm_prefork module. PHP setup completes all these settings and restarts the Apache server:

How it works…

After we have installed PHP and mod_php, we simply need to create a PHP script. We have created index.php with little code to display phpinfo. At this stage, if you have both index.html and index.php under the same directory; by default, index.html will take over and be rendered first. You will need to explicitly specify index.php to access the page as http://127.0.0.1/index.php. We have set a directive, DirectoryIndex, under Apache Virtual Host to set index.php as a default index file.

PHP settings

All PHP settings are listed under its own configuration file, php.ini. PHP comes with two sets of configurations, as follows:

/usr/lib/php/7.0/php.ini-development

The /usr/lib/php/7.0/php.ini-productionDevelopment file is customized for a development environment and enables options like display_errors. For production systems, you can use the configuration file, php.ini-production.

The preceding files can be treated as a reference configuration that ships with the PHP installation. A copy of php.ini-production can be found under /etc/php/7.0. Apache and CLI configurations are separated in respective directories. You can directly edit settings under these files or simply use default files by creating a symbolic link to the development or production file as follows:

$ cd /etc/php/7.0/apache2
$ sudo mv php.ini php.ini.orig
$ sudo ln -s /usr/lib/php/7.0/php.ini-development php.ini

There's more…

Along with PHP, Apache supports various other scripting languages for dynamic content. You can install modules for Perl, Python, Ruby, and other scripting languages.

Add Python support:

$ sudo apt-get install libapache2-mod-python

Add Perl support:

$ sudo apt-get install libapache2-mod-perl2

Add Ruby support:

$ sudo apt-get install libapache2-mod-passenger

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

Getting ready

You will need access to a root account or an account with sudo privileges.

The Apache web server should be installed and working properly.

How to do it…

Follow these steps to serve dynamic contents with PHP:

  1. Install PHP7 and the Apache module for PHP support:
    $ sudo apt-get update
    $ sudo apt-get install -y php7.0 libapache2-mod-php7.0
    
  2. Check if PHP is properly installed and which version has been installed:
    $ php -v
    
    How to do it…
  3. Create index.php under the public_html directory of our site:
    $ cd /var/www/example.com/public_html
    $ vi index.php
    
  4. Add the following contents to index.php:
    <?php echo phpinfo(); ?>
    
  5. Save and exit the index.php file.
  6. Open example.com.conf from sites-available:
    $ sudo vi /etc/apache2/sites-available/example.com.conf
    
  7. Add the following line under the VirtualHost directive:
    DirectoryIndex index.php index.html
    
    How to do it…
  8. Save the changes and reload Apache:
    $ sudo service apache2 reload
    
  9. Now, access your site with your browser, and you should see a page with information regarding the installed PHP:
    How to do it…

How it works…

Here, we have installed PHP binaries on our server along with the Apache module libapache2-mod-php7.0 to support dynamic content coded in PHP. A module, mod_php, runs inside Apache process and processes PHP scripts from within Apache itself. For mod_php to work, Apache needs to run with the mpm_prefork module. PHP setup completes all these settings and restarts the Apache server:

How it works…

After we have installed PHP and mod_php, we simply need to create a PHP script. We have created index.php with little code to display phpinfo. At this stage, if you have both index.html and index.php under the same directory; by default, index.html will take over and be rendered first. You will need to explicitly specify index.php to access the page as http://127.0.0.1/index.php. We have set a directive, DirectoryIndex, under Apache Virtual Host to set index.php as a default index file.

PHP settings

All PHP settings are listed under its own configuration file, php.ini. PHP comes with two sets of configurations, as follows:

/usr/lib/php/7.0/php.ini-development

The /usr/lib/php/7.0/php.ini-productionDevelopment file is customized for a development environment and enables options like display_errors. For production systems, you can use the configuration file, php.ini-production.

The preceding files can be treated as a reference configuration that ships with the PHP installation. A copy of php.ini-production can be found under /etc/php/7.0. Apache and CLI configurations are separated in respective directories. You can directly edit settings under these files or simply use default files by creating a symbolic link to the development or production file as follows:

$ cd /etc/php/7.0/apache2
$ sudo mv php.ini php.ini.orig
$ sudo ln -s /usr/lib/php/7.0/php.ini-development php.ini

There's more…

Along with PHP, Apache supports various other scripting languages for dynamic content. You can install modules for Perl, Python, Ruby, and other scripting languages.

Add Python support:

$ sudo apt-get install libapache2-mod-python

Add Perl support:

$ sudo apt-get install libapache2-mod-perl2

Add Ruby support:

$ sudo apt-get install libapache2-mod-passenger

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

How to do it…

Follow these steps to serve dynamic contents with PHP:

  1. Install PHP7 and the Apache module for PHP support:
    $ sudo apt-get update
    $ sudo apt-get install -y php7.0 libapache2-mod-php7.0
    
  2. Check if PHP is properly installed and which version has been installed:
    $ php -v
    
    How to do it…
  3. Create index.php under the public_html directory of our site:
    $ cd /var/www/example.com/public_html
    $ vi index.php
    
  4. Add the following contents to index.php:
    <?php echo phpinfo(); ?>
    
  5. Save and exit the index.php file.
  6. Open example.com.conf from sites-available:
    $ sudo vi /etc/apache2/sites-available/example.com.conf
    
  7. Add the following line under the VirtualHost directive:
    DirectoryIndex index.php index.html
    
    How to do it…
  8. Save the changes and reload Apache:
    $ sudo service apache2 reload
    
  9. Now, access your site with your browser, and you should see a page with information regarding the installed PHP:
    How to do it…

How it works…

Here, we have installed PHP binaries on our server along with the Apache module libapache2-mod-php7.0 to support dynamic content coded in PHP. A module, mod_php, runs inside Apache process and processes PHP scripts from within Apache itself. For mod_php to work, Apache needs to run with the mpm_prefork module. PHP setup completes all these settings and restarts the Apache server:

How it works…

After we have installed PHP and mod_php, we simply need to create a PHP script. We have created index.php with little code to display phpinfo. At this stage, if you have both index.html and index.php under the same directory; by default, index.html will take over and be rendered first. You will need to explicitly specify index.php to access the page as http://127.0.0.1/index.php. We have set a directive, DirectoryIndex, under Apache Virtual Host to set index.php as a default index file.

PHP settings

All PHP settings are listed under its own configuration file, php.ini. PHP comes with two sets of configurations, as follows:

/usr/lib/php/7.0/php.ini-development

The /usr/lib/php/7.0/php.ini-productionDevelopment file is customized for a development environment and enables options like display_errors. For production systems, you can use the configuration file, php.ini-production.

The preceding files can be treated as a reference configuration that ships with the PHP installation. A copy of php.ini-production can be found under /etc/php/7.0. Apache and CLI configurations are separated in respective directories. You can directly edit settings under these files or simply use default files by creating a symbolic link to the development or production file as follows:

$ cd /etc/php/7.0/apache2
$ sudo mv php.ini php.ini.orig
$ sudo ln -s /usr/lib/php/7.0/php.ini-development php.ini

There's more…

Along with PHP, Apache supports various other scripting languages for dynamic content. You can install modules for Perl, Python, Ruby, and other scripting languages.

Add Python support:

$ sudo apt-get install libapache2-mod-python

Add Perl support:

$ sudo apt-get install libapache2-mod-perl2

Add Ruby support:

$ sudo apt-get install libapache2-mod-passenger

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

How it works…

Here, we have installed PHP binaries on our server along with the Apache module libapache2-mod-php7.0 to support dynamic content coded in PHP. A module, mod_php, runs inside Apache process and processes PHP scripts from within Apache itself. For mod_php to work, Apache needs to run with the mpm_prefork module. PHP setup completes all these settings and restarts the Apache server:

How it works…

After we have installed PHP and mod_php, we simply need to create a PHP script. We have created index.php with little code to display phpinfo. At this stage, if you have both index.html and index.php under the same directory; by default, index.html will take over and be rendered first. You will need to explicitly specify index.php to access the page as http://127.0.0.1/index.php. We have set a directive, DirectoryIndex, under Apache Virtual Host to set index.php as a default index file.

PHP settings

All PHP settings are listed under its own configuration file, php.ini. PHP comes with two sets of configurations, as follows:

/usr/lib/php/7.0/php.ini-development

The /usr/lib/php/7.0/php.ini-productionDevelopment file is customized for a development environment and enables options like display_errors. For production systems, you can use the configuration file, php.ini-production.

The preceding files can be treated as a reference configuration that ships with the PHP installation. A copy of php.ini-production can be found under /etc/php/7.0. Apache and CLI configurations are separated in respective directories. You can directly edit settings under these files or simply use default files by creating a symbolic link to the development or production file as follows:

$ cd /etc/php/7.0/apache2
$ sudo mv php.ini php.ini.orig
$ sudo ln -s /usr/lib/php/7.0/php.ini-development php.ini

There's more…

Along with PHP, Apache supports various other scripting languages for dynamic content. You can install modules for Perl, Python, Ruby, and other scripting languages.

Add Python support:

$ sudo apt-get install libapache2-mod-python

Add Perl support:

$ sudo apt-get install libapache2-mod-perl2

Add Ruby support:

$ sudo apt-get install libapache2-mod-passenger

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

PHP settings

All PHP settings are listed under its own configuration file, php.ini. PHP comes with two sets of configurations, as follows:

/usr/lib/php/7.0/php.ini-development

The /usr/lib/php/7.0/php.ini-productionDevelopment file is customized for a development environment and enables options like display_errors. For production systems, you can use the configuration file, php.ini-production.

The preceding files can be treated as a reference configuration that ships with the PHP installation. A copy of php.ini-production can be found under /etc/php/7.0. Apache and CLI configurations are separated in respective directories. You can directly edit settings under these files or simply use default files by creating a symbolic link to the development or production file as follows:

$ cd /etc/php/7.0/apache2
$ sudo mv php.ini php.ini.orig
$ sudo ln -s /usr/lib/php/7.0/php.ini-development php.ini
There's more…

Along with PHP, Apache supports various other scripting languages for dynamic content. You can install modules for Perl, Python, Ruby, and other scripting languages.

Add Python support:

$ sudo apt-get install libapache2-mod-python

Add Perl support:

$ sudo apt-get install libapache2-mod-perl2

Add Ruby support:

$ sudo apt-get install libapache2-mod-passenger

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

There's more…

Along with PHP, Apache supports various other scripting languages for dynamic content. You can install modules for Perl, Python, Ruby, and other scripting languages.

Add Python support:

$ sudo apt-get install libapache2-mod-python

Add Perl support:

$ sudo apt-get install libapache2-mod-perl2

Add Ruby support:

$ sudo apt-get install libapache2-mod-passenger

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

Installing the LAMP stack

If you are interested in installing the entire LAMP stack, then Ubuntu provides a single command to do so. Use the following command to install Apache, PHP, and MySQL collectively:

$ sudo apt-get install lamp-server^

Notice the caret symbol at the end of the command. If you miss this symbol, apt will return an error saying package not found.

Note

lamp-server is set in the Ubuntu repository as a task to install and configure Apache, PHP, and MySQL collectively. The caret symbol in apt-get command is used to specify the task rather than the package. Alternatively, you can use the tasksel command as $ sudo tasksel install lamp-server. Tasksel is a program used to ease the installation of packages that are commonly used together.

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

Upgrading PHP under Ubuntu 14

As of Ubuntu 14.10, Ubuntu does not provide a package for PHP7 in its repository, but you can use a Debian package repository to upgrade your PHP version. This repository is maintained by Ondřej Surý.

Use the following commands to upgrade to PHP 7:

$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:ondrej/php
$ sudo apt-get update
$ sudo apt-get install php7.0

Check the PHP version after installation completes:

$ php -v

Hosting multiple websites with a virtual domain

Setting multiple domains on a single server is a very commonly asked question. In fact, it is very easy to do this with virtual host. In this recipe, we will set up two domains on a single server and set up a sub-domain as well. We will also look at IP-based virtual hosts.

Getting ready

You will need access to a root account or an account with sudo privileges.

You will need the Apache server installed and working. This recipe describes configuration for Apache version 2.4

You may need a DNS set up if you want to access configured domains over the Internet.

We will set up two domains, namely example1.dom and example2.com, and a sub-domain, dev.example1.com.

How to do it…

Follow these steps to host multiple websites with a virtual domain:

  1. Change the directory to /var/www and create a directory structure for the required domains and sub-domain. Also create a blank index.html for each domain:
    $ cd /var/www
    $ sudo mkdir -p example1.com/public_html
    $ sudo touch example1.com/public_html
    $ sudo cp -R example1.com example2.com
    $ sudo cp -R example1.com dev.example1.com
    
  2. Change the directory ownership and file permissions on the newly created directories:
    $ sudo chown -R ubuntu:www-data example*
    $ sudo chown -R ubuntu:www-data dev.example1.com
    $ chmod 750 -R example*
    $ chmod 750 -R dev.example1.com
    

    Tip

    Note the use of the wildcard syntax (chmod 750 -R example*). You can use a similar syntax with various other commands in Linux and save some repeated typing or copy and paste work.

  3. Edit the index.html file for each domain with the respective text:
    How to do it…
  4. Next, we need to create virtual host configuration for each domain. Change the directory to /etc/apache2/sites-available and copy the default virtual host file 000-default.conf:
    $ cd /etc/apache2/sites-available
    $ sudo cp 000-default.conf example1.com.conf
    
  5. Edit the new virtual host file and set ServerName, DocumentRoot, and other variables to match your environment. The final file should look something like this:
    <VirtualHost *:80>
        ServerName example1.com
        ServerAlias www.example1.com
        DocumentRoot /var/www/example1.com/public_html
        
    ...
    </VirtualHost>
    
  6. Now copy this virtual host file to create example2.com.conf and dev.example1.com.conf and modify the respective settings in each of them. You need to update the serverName, serverAlias, and DocumentRoot parameters.
  7. Here, we are done with the setup and configuration part. Now enable the virtual hosts and reload the Apache server for the settings to take effect:
    $ sudo a2ensite example*
    $ sudo a2ensite dev.example1.com.conf
    $ sudo service apache2 reload
    
  8. You can check all enabled virtual hosts with the following command:
    $ sudo a2query -s
    
  9. Next, to test our setup, we need to configure the hosts' setup on the local system. Open and edit the /etc/hosts file and add host entries. If you have Windows as your local system, you can find the hosts file under %systemroot%\System32\drivers\etc:
    How to do it…
  10. Finally, try to access domains by their names. You should see text entered in the respective index.html files for each domain:
    How to do it…

How it works…

Multiple domain hosting works with the concept of NamedVirtualHost. We have configured virtual hosts with ServerName and ServerAlias. When a client sends a request with a domain name, it sends a host name in the request headers. This host name is used by Apache to determine the actual virtual host to serve this request. If none of the available virtual hosts match the requested host header, then the default virtual host or the first virtual host will be used to serve the request.

In this example, we have used hosts file to map test domain names with local IP. With the actual domain name, you need to point DNS servers to the IP address of your web server. Generally, all popular hosting providers host their own DNS servers. You need to add these DNS servers to your domain setting with domain registrar. Then, on your hosting side, you need to set respective A records and CNAME records. An A record points to an IP address and the CNAME record is an alias for the A record used for pointing a subdomain to an A record. Your hosting provider should give you details on how to configure domains and subdomains.

In previous versions of Apache server, you might need to enable NameVirtualHost under the configuration file. Find a line similar to #NameVirtualHost 172.20.30.40 and uncomment it by removing the # symbol at the start.

You can also set up IP-based virtual hosts. If you have multiple IP addresses available on your server, you can set the virtual host to listen on a particular IP address. Use the following steps to set up an IP-based virtual host:

  1. Get a list of the available IP addresses:
    $ ifconfig | grep "inet addr"
    ubuntu@ubuntu:~$ ifconfig | grep "inet addr"
    inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
    inet addr:192.168.56.102  Bcast:192.168.56.255  Mask:255.255.255.0
    inet addr:127.0.0.1  Mask:255.0.0.0
    
  2. Edit the virtual host configuration and set it to match the following:
    Listen 80
    <VirtualHost 192.168.56.102>
            DocumentRoot /var/www/example1.com/public_html
            ServerName example1.com
    </VirtualHost>
    

See also

Getting ready

You will need access to a root account or an account with sudo privileges.

You will need the Apache server installed and working. This recipe describes configuration for Apache version 2.4

You may need a DNS set up if you want to access configured domains over the Internet.

We will set up two domains, namely example1.dom and example2.com, and a sub-domain, dev.example1.com.

How to do it…

Follow these steps to host multiple websites with a virtual domain:

  1. Change the directory to /var/www and create a directory structure for the required domains and sub-domain. Also create a blank index.html for each domain:
    $ cd /var/www
    $ sudo mkdir -p example1.com/public_html
    $ sudo touch example1.com/public_html
    $ sudo cp -R example1.com example2.com
    $ sudo cp -R example1.com dev.example1.com
    
  2. Change the directory ownership and file permissions on the newly created directories:
    $ sudo chown -R ubuntu:www-data example*
    $ sudo chown -R ubuntu:www-data dev.example1.com
    $ chmod 750 -R example*
    $ chmod 750 -R dev.example1.com
    

    Tip

    Note the use of the wildcard syntax (chmod 750 -R example*). You can use a similar syntax with various other commands in Linux and save some repeated typing or copy and paste work.

  3. Edit the index.html file for each domain with the respective text:
    How to do it…
  4. Next, we need to create virtual host configuration for each domain. Change the directory to /etc/apache2/sites-available and copy the default virtual host file 000-default.conf:
    $ cd /etc/apache2/sites-available
    $ sudo cp 000-default.conf example1.com.conf
    
  5. Edit the new virtual host file and set ServerName, DocumentRoot, and other variables to match your environment. The final file should look something like this:
    <VirtualHost *:80>
        ServerName example1.com
        ServerAlias www.example1.com
        DocumentRoot /var/www/example1.com/public_html
        
    ...
    </VirtualHost>
    
  6. Now copy this virtual host file to create example2.com.conf and dev.example1.com.conf and modify the respective settings in each of them. You need to update the serverName, serverAlias, and DocumentRoot parameters.
  7. Here, we are done with the setup and configuration part. Now enable the virtual hosts and reload the Apache server for the settings to take effect:
    $ sudo a2ensite example*
    $ sudo a2ensite dev.example1.com.conf
    $ sudo service apache2 reload
    
  8. You can check all enabled virtual hosts with the following command:
    $ sudo a2query -s
    
  9. Next, to test our setup, we need to configure the hosts' setup on the local system. Open and edit the /etc/hosts file and add host entries. If you have Windows as your local system, you can find the hosts file under %systemroot%\System32\drivers\etc:
    How to do it…
  10. Finally, try to access domains by their names. You should see text entered in the respective index.html files for each domain:
    How to do it…

How it works…

Multiple domain hosting works with the concept of NamedVirtualHost. We have configured virtual hosts with ServerName and ServerAlias. When a client sends a request with a domain name, it sends a host name in the request headers. This host name is used by Apache to determine the actual virtual host to serve this request. If none of the available virtual hosts match the requested host header, then the default virtual host or the first virtual host will be used to serve the request.

In this example, we have used hosts file to map test domain names with local IP. With the actual domain name, you need to point DNS servers to the IP address of your web server. Generally, all popular hosting providers host their own DNS servers. You need to add these DNS servers to your domain setting with domain registrar. Then, on your hosting side, you need to set respective A records and CNAME records. An A record points to an IP address and the CNAME record is an alias for the A record used for pointing a subdomain to an A record. Your hosting provider should give you details on how to configure domains and subdomains.

In previous versions of Apache server, you might need to enable NameVirtualHost under the configuration file. Find a line similar to #NameVirtualHost 172.20.30.40 and uncomment it by removing the # symbol at the start.

You can also set up IP-based virtual hosts. If you have multiple IP addresses available on your server, you can set the virtual host to listen on a particular IP address. Use the following steps to set up an IP-based virtual host:

  1. Get a list of the available IP addresses:
    $ ifconfig | grep "inet addr"
    ubuntu@ubuntu:~$ ifconfig | grep "inet addr"
    inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
    inet addr:192.168.56.102  Bcast:192.168.56.255  Mask:255.255.255.0
    inet addr:127.0.0.1  Mask:255.0.0.0
    
  2. Edit the virtual host configuration and set it to match the following:
    Listen 80
    <VirtualHost 192.168.56.102>
            DocumentRoot /var/www/example1.com/public_html
            ServerName example1.com
    </VirtualHost>
    

See also

How to do it…

Follow these steps to host multiple websites with a virtual domain:

  1. Change the directory to /var/www and create a directory structure for the required domains and sub-domain. Also create a blank index.html for each domain:
    $ cd /var/www
    $ sudo mkdir -p example1.com/public_html
    $ sudo touch example1.com/public_html
    $ sudo cp -R example1.com example2.com
    $ sudo cp -R example1.com dev.example1.com
    
  2. Change the directory ownership and file permissions on the newly created directories:
    $ sudo chown -R ubuntu:www-data example*
    $ sudo chown -R ubuntu:www-data dev.example1.com
    $ chmod 750 -R example*
    $ chmod 750 -R dev.example1.com
    

    Tip

    Note the use of the wildcard syntax (chmod 750 -R example*). You can use a similar syntax with various other commands in Linux and save some repeated typing or copy and paste work.

  3. Edit the index.html file for each domain with the respective text:
    How to do it…
  4. Next, we need to create virtual host configuration for each domain. Change the directory to /etc/apache2/sites-available and copy the default virtual host file 000-default.conf:
    $ cd /etc/apache2/sites-available
    $ sudo cp 000-default.conf example1.com.conf
    
  5. Edit the new virtual host file and set ServerName, DocumentRoot, and other variables to match your environment. The final file should look something like this:
    <VirtualHost *:80>
        ServerName example1.com
        ServerAlias www.example1.com
        DocumentRoot /var/www/example1.com/public_html
        
    ...
    </VirtualHost>
    
  6. Now copy this virtual host file to create example2.com.conf and dev.example1.com.conf and modify the respective settings in each of them. You need to update the serverName, serverAlias, and DocumentRoot parameters.
  7. Here, we are done with the setup and configuration part. Now enable the virtual hosts and reload the Apache server for the settings to take effect:
    $ sudo a2ensite example*
    $ sudo a2ensite dev.example1.com.conf
    $ sudo service apache2 reload
    
  8. You can check all enabled virtual hosts with the following command:
    $ sudo a2query -s
    
  9. Next, to test our setup, we need to configure the hosts' setup on the local system. Open and edit the /etc/hosts file and add host entries. If you have Windows as your local system, you can find the hosts file under %systemroot%\System32\drivers\etc:
    How to do it…
  10. Finally, try to access domains by their names. You should see text entered in the respective index.html files for each domain:
    How to do it…

How it works…

Multiple domain hosting works with the concept of NamedVirtualHost. We have configured virtual hosts with ServerName and ServerAlias. When a client sends a request with a domain name, it sends a host name in the request headers. This host name is used by Apache to determine the actual virtual host to serve this request. If none of the available virtual hosts match the requested host header, then the default virtual host or the first virtual host will be used to serve the request.

In this example, we have used hosts file to map test domain names with local IP. With the actual domain name, you need to point DNS servers to the IP address of your web server. Generally, all popular hosting providers host their own DNS servers. You need to add these DNS servers to your domain setting with domain registrar. Then, on your hosting side, you need to set respective A records and CNAME records. An A record points to an IP address and the CNAME record is an alias for the A record used for pointing a subdomain to an A record. Your hosting provider should give you details on how to configure domains and subdomains.

In previous versions of Apache server, you might need to enable NameVirtualHost under the configuration file. Find a line similar to #NameVirtualHost 172.20.30.40 and uncomment it by removing the # symbol at the start.

You can also set up IP-based virtual hosts. If you have multiple IP addresses available on your server, you can set the virtual host to listen on a particular IP address. Use the following steps to set up an IP-based virtual host:

  1. Get a list of the available IP addresses:
    $ ifconfig | grep "inet addr"
    ubuntu@ubuntu:~$ ifconfig | grep "inet addr"
    inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
    inet addr:192.168.56.102  Bcast:192.168.56.255  Mask:255.255.255.0
    inet addr:127.0.0.1  Mask:255.0.0.0
    
  2. Edit the virtual host configuration and set it to match the following:
    Listen 80
    <VirtualHost 192.168.56.102>
            DocumentRoot /var/www/example1.com/public_html
            ServerName example1.com
    </VirtualHost>
    

See also

How it works…

Multiple domain hosting works with the concept of NamedVirtualHost. We have configured virtual hosts with ServerName and ServerAlias. When a client sends a request with a domain name, it sends a host name in the request headers. This host name is used by Apache to determine the actual virtual host to serve this request. If none of the available virtual hosts match the requested host header, then the default virtual host or the first virtual host will be used to serve the request.

In this example, we have used hosts file to map test domain names with local IP. With the actual domain name, you need to point DNS servers to the IP address of your web server. Generally, all popular hosting providers host their own DNS servers. You need to add these DNS servers to your domain setting with domain registrar. Then, on your hosting side, you need to set respective A records and CNAME records. An A record points to an IP address and the CNAME record is an alias for the A record used for pointing a subdomain to an A record. Your hosting provider should give you details on how to configure domains and subdomains.

In previous versions of Apache server, you might need to enable NameVirtualHost under the configuration file. Find a line similar to #NameVirtualHost 172.20.30.40 and uncomment it by removing the # symbol at the start.

You can also set up IP-based virtual hosts. If you have multiple IP addresses available on your server, you can set the virtual host to listen on a particular IP address. Use the following steps to set up an IP-based virtual host:

  1. Get a list of the available IP addresses:
    $ ifconfig | grep "inet addr"
    ubuntu@ubuntu:~$ ifconfig | grep "inet addr"
    inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
    inet addr:192.168.56.102  Bcast:192.168.56.255  Mask:255.255.255.0
    inet addr:127.0.0.1  Mask:255.0.0.0
    
  2. Edit the virtual host configuration and set it to match the following:
    Listen 80
    <VirtualHost 192.168.56.102>
            DocumentRoot /var/www/example1.com/public_html
            ServerName example1.com
    </VirtualHost>
    

See also

See also

Securing web traffic with HTTPS

HTTP is a non-secure protocol commonly used to communicate over the Web. The traffic is transferred in plain text form and can be captured and interpreted by a third-party attacker. Transport Layer Security and Secure Socket Layer protocols (TLS/SSL) can be used to secure the traffic between client and server. These protocols encapsulate normal traffic in an encrypted and secure wrapper. It also validates the identity of the client and server with SSL keys, certificates, and certification authorities.

When HTTP is combined with TLS or SSL, it is abbreviated as HTTPS or HTTP secure. Port 443 is used as a standard port for secured HTTP communication. Nearly all leading web servers provide inbuilt support for enabling HTTPS. Apache has a module called mod_ssl that enables the use of HTTPS.

To set up your servers with SSL/TLS encrypted traffic, you will need an SSL certificate and a key pair that can be used to encrypt traffic. Generally, the certificate and keys are obtained from a trusted signing authority. They charge you some fees to verify your ownership of the web property and allocate the required signed certificates. You can also generate self-signed certificates for internal use. Few certification authorities provide a free SSL certificate. Recently, Mozilla has started a free and automated certificate authority named Let's Encrypt. At the time of writing, the service is in public beta and has started allocating certificates. Let's Encrypt offers a client that can be used to obtain certificates and set up automated renewal. You can also find various unofficial clients for Apache and Nginx servers.

In this recipe, we will learn how to create our own self-signed certificate and set up the Apache server to serve contents over a secure channel.

Getting ready

You will need access to a root account or an account with sudo privileges. I assume that you have the Apache server preinstalled. You will also need OpenSSL installed.

Make sure your firewall, if any, allows traffic on port 443. Check Chapter 2, Networking, Securing network with uncomplicated firewall recipe for more details on Uncomplicated Firewall.

How to do it…

Follow these steps to secure web traffic with HTTPS:

  1. First, we will start by creating a self-signed SSL certificate. Create a directory under /etc/apache2 to hold the certificate and key:
    $ sudo mkdir /etc/apache2/ssl
    
  2. Change to the new directory and enter the following command to create a certificate and SSL key:
    $ cd /etc/apache2/ssl
    $ sudo openssl req -x509 -nodes -days 365 \
    -newkey rsa:2048 -keyout ssl.key -out ssl.crt
    
  3. This will prompt you to enter some information about your company and website. Enter the respective details and press Enter for each prompt:
    How to do it…
  4. After you are done with it, you can check the generated certificate and key:
    $ ls -l
    
    How to do it…
  5. Next, we need to configure Apache to use SSL. We will enable SSL for the previously created virtual host.
  6. Open the Virtual Host configuration file, example.com.conf. After removing comments, it should look similar to the following:
    How to do it…
  7. Now, copy the entire <VirtualHost *:80> ... </VirtualHost> tag and paste it at the end of the file.
  8. Under the newly copied contents, change the port from 80 to 443.
  9. Add the following lines below the DocumentRoot line. This will enable SSL and specify the path to the certificate and key:
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/ssl.crt
    SSLCertificateKeyFile /etc/apache2/ssl/ssl.key
    
  10. The final file should look something like this:
    How to do it…
  11. Save the changes, exit example.com.conf, and enable the mod_ssl module on the Apache server:
    $ sudo a2enmod ssl
    
  12. Next, enable the Virtual Host example.com. If it's already enabled, it will return a message saying site example.com already enabled:
    $ sudo a2ensite example.com.conf
    
  13. Reload the Apache server for the changes to take effect:
    $ sudo service apache2 reload
    
  14. Now, open your browser on the client system and point it to your domain name or IP address with HTTPS at the start:
    https://example.com
    
  15. Your browser may return an error saying Invalid Certification Authority. This is fine as we are using a self-signed certificate. Click Advanced and then click Proceed to example.com to open a specified page:
    How to do it…
  16. Once the page is loaded completely, find the padlock icon in the upper right corner of the browser and click on it. The second section with the green lock icon will display the encryption status. Now your communication with the server is encrypted and secure:
    How to do it…

How it works…

We have created a self-signed certificate to secure an HTTP communication. The key will be used to encrypt all communication with clients. Another thing to note is that we have defined a separate Virtual Host entry on port 443. This Virtual Host will be used for all requests that are received over port 443. At the same time, we have allowed non-secured HTTP communication for the same Virtual Host. To disable non-secure communication on port 80, you can simply comment out the original Virtual Host configuration. Alternatively, you can separate both configurations into two files and enable or disable with the a2ensite and a2dissite commands.

Some of the parameters used for generating a key and certificate are as follows:

  • - nodes specifies that we do not want to use a passphrase for a key.
  • - days this specifies the number of days the certificate is valid for. Our certificate is valid for 365 days, that is, a year.
  • - newkey rsa:2048 this option is used to generate a certificate along with a private key. rsa:2048 specifies the 2048 bit long RSA private key.

I have modified the existing Virtual Host entry to demonstrate the minimal configuration required to enable secure HTTP communication. You can always use the default secure Virtual Host configuration available under sites-available/default-ssl.conf. This file provides some additional parameters with respective comments.

The certificate created in this recipe will not be trusted over the Internet but can be used for securing local or internal communication. For production use, it is advisable to get a certificate signed from an external, well known certification authority. This will avoid the initial errors in browsers.

There's more…

To get a signed certificate from an external certification authority, you will need a CSR document.

The following are the steps to generate a CSR:

  1. Generate a key for the CSR:
    $ openssl genrsa -des3 -out server.key 2048
    
  2. You will be asked to enter a passphrase for the key and then verify it. They will be generated with name server.key.
  3. Now, remove the passphrase from the key. We don't want to enter a passphrase each time a key is used:
    $ openssl rsa -in server.key -out server.key.insecure
    $ mv server.key server.key.secure
    $ mv server.key.insecure server.key
    
  4. Next, create the CSR with the following command:
    $ openssl req -new -key server.key -out server.csr
    
  5. A CSR file is created with the name server.csr, and now you can submit this CSR for signing purposes.

See also

Getting ready

You will need access to a root account or an account with sudo privileges. I assume that you have the Apache server preinstalled. You will also need OpenSSL installed.

Make sure your firewall, if any, allows traffic on port 443. Check Chapter 2, Networking, Securing network with uncomplicated firewall recipe for more details on Uncomplicated Firewall.

How to do it…

Follow these steps to secure web traffic with HTTPS:

  1. First, we will start by creating a self-signed SSL certificate. Create a directory under /etc/apache2 to hold the certificate and key:
    $ sudo mkdir /etc/apache2/ssl
    
  2. Change to the new directory and enter the following command to create a certificate and SSL key:
    $ cd /etc/apache2/ssl
    $ sudo openssl req -x509 -nodes -days 365 \
    -newkey rsa:2048 -keyout ssl.key -out ssl.crt
    
  3. This will prompt you to enter some information about your company and website. Enter the respective details and press Enter for each prompt:
    How to do it…
  4. After you are done with it, you can check the generated certificate and key:
    $ ls -l
    
    How to do it…
  5. Next, we need to configure Apache to use SSL. We will enable SSL for the previously created virtual host.
  6. Open the Virtual Host configuration file, example.com.conf. After removing comments, it should look similar to the following:
    How to do it…
  7. Now, copy the entire <VirtualHost *:80> ... </VirtualHost> tag and paste it at the end of the file.
  8. Under the newly copied contents, change the port from 80 to 443.
  9. Add the following lines below the DocumentRoot line. This will enable SSL and specify the path to the certificate and key:
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/ssl.crt
    SSLCertificateKeyFile /etc/apache2/ssl/ssl.key
    
  10. The final file should look something like this:
    How to do it…
  11. Save the changes, exit example.com.conf, and enable the mod_ssl module on the Apache server:
    $ sudo a2enmod ssl
    
  12. Next, enable the Virtual Host example.com. If it's already enabled, it will return a message saying site example.com already enabled:
    $ sudo a2ensite example.com.conf
    
  13. Reload the Apache server for the changes to take effect:
    $ sudo service apache2 reload
    
  14. Now, open your browser on the client system and point it to your domain name or IP address with HTTPS at the start:
    https://example.com
    
  15. Your browser may return an error saying Invalid Certification Authority. This is fine as we are using a self-signed certificate. Click Advanced and then click Proceed to example.com to open a specified page:
    How to do it…
  16. Once the page is loaded completely, find the padlock icon in the upper right corner of the browser and click on it. The second section with the green lock icon will display the encryption status. Now your communication with the server is encrypted and secure:
    How to do it…

How it works…

We have created a self-signed certificate to secure an HTTP communication. The key will be used to encrypt all communication with clients. Another thing to note is that we have defined a separate Virtual Host entry on port 443. This Virtual Host will be used for all requests that are received over port 443. At the same time, we have allowed non-secured HTTP communication for the same Virtual Host. To disable non-secure communication on port 80, you can simply comment out the original Virtual Host configuration. Alternatively, you can separate both configurations into two files and enable or disable with the a2ensite and a2dissite commands.

Some of the parameters used for generating a key and certificate are as follows:

  • - nodes specifies that we do not want to use a passphrase for a key.
  • - days this specifies the number of days the certificate is valid for. Our certificate is valid for 365 days, that is, a year.
  • - newkey rsa:2048 this option is used to generate a certificate along with a private key. rsa:2048 specifies the 2048 bit long RSA private key.

I have modified the existing Virtual Host entry to demonstrate the minimal configuration required to enable secure HTTP communication. You can always use the default secure Virtual Host configuration available under sites-available/default-ssl.conf. This file provides some additional parameters with respective comments.

The certificate created in this recipe will not be trusted over the Internet but can be used for securing local or internal communication. For production use, it is advisable to get a certificate signed from an external, well known certification authority. This will avoid the initial errors in browsers.

There's more…

To get a signed certificate from an external certification authority, you will need a CSR document.

The following are the steps to generate a CSR:

  1. Generate a key for the CSR:
    $ openssl genrsa -des3 -out server.key 2048
    
  2. You will be asked to enter a passphrase for the key and then verify it. They will be generated with name server.key.
  3. Now, remove the passphrase from the key. We don't want to enter a passphrase each time a key is used:
    $ openssl rsa -in server.key -out server.key.insecure
    $ mv server.key server.key.secure
    $ mv server.key.insecure server.key
    
  4. Next, create the CSR with the following command:
    $ openssl req -new -key server.key -out server.csr
    
  5. A CSR file is created with the name server.csr, and now you can submit this CSR for signing purposes.

See also

How to do it…

Follow these steps to secure web traffic with HTTPS:

  1. First, we will start by creating a self-signed SSL certificate. Create a directory under /etc/apache2 to hold the certificate and key:
    $ sudo mkdir /etc/apache2/ssl
    
  2. Change to the new directory and enter the following command to create a certificate and SSL key:
    $ cd /etc/apache2/ssl
    $ sudo openssl req -x509 -nodes -days 365 \
    -newkey rsa:2048 -keyout ssl.key -out ssl.crt
    
  3. This will prompt you to enter some information about your company and website. Enter the respective details and press Enter for each prompt:
    How to do it…
  4. After you are done with it, you can check the generated certificate and key:
    $ ls -l
    
    How to do it…
  5. Next, we need to configure Apache to use SSL. We will enable SSL for the previously created virtual host.
  6. Open the Virtual Host configuration file, example.com.conf. After removing comments, it should look similar to the following:
    How to do it…
  7. Now, copy the entire <VirtualHost *:80> ... </VirtualHost> tag and paste it at the end of the file.
  8. Under the newly copied contents, change the port from 80 to 443.
  9. Add the following lines below the DocumentRoot line. This will enable SSL and specify the path to the certificate and key:
    SSLEngine on
    SSLCertificateFile /etc/apache2/ssl/ssl.crt
    SSLCertificateKeyFile /etc/apache2/ssl/ssl.key
    
  10. The final file should look something like this:
    How to do it…
  11. Save the changes, exit example.com.conf, and enable the mod_ssl module on the Apache server:
    $ sudo a2enmod ssl
    
  12. Next, enable the Virtual Host example.com. If it's already enabled, it will return a message saying site example.com already enabled:
    $ sudo a2ensite example.com.conf
    
  13. Reload the Apache server for the changes to take effect:
    $ sudo service apache2 reload
    
  14. Now, open your browser on the client system and point it to your domain name or IP address with HTTPS at the start:
    https://example.com
    
  15. Your browser may return an error saying Invalid Certification Authority. This is fine as we are using a self-signed certificate. Click Advanced and then click Proceed to example.com to open a specified page:
    How to do it…
  16. Once the page is loaded completely, find the padlock icon in the upper right corner of the browser and click on it. The second section with the green lock icon will display the encryption status. Now your communication with the server is encrypted and secure:
    How to do it…

How it works…

We have created a self-signed certificate to secure an HTTP communication. The key will be used to encrypt all communication with clients. Another thing to note is that we have defined a separate Virtual Host entry on port 443. This Virtual Host will be used for all requests that are received over port 443. At the same time, we have allowed non-secured HTTP communication for the same Virtual Host. To disable non-secure communication on port 80, you can simply comment out the original Virtual Host configuration. Alternatively, you can separate both configurations into two files and enable or disable with the a2ensite and a2dissite commands.

Some of the parameters used for generating a key and certificate are as follows:

  • - nodes specifies that we do not want to use a passphrase for a key.
  • - days this specifies the number of days the certificate is valid for. Our certificate is valid for 365 days, that is, a year.
  • - newkey rsa:2048 this option is used to generate a certificate along with a private key. rsa:2048 specifies the 2048 bit long RSA private key.

I have modified the existing Virtual Host entry to demonstrate the minimal configuration required to enable secure HTTP communication. You can always use the default secure Virtual Host configuration available under sites-available/default-ssl.conf. This file provides some additional parameters with respective comments.

The certificate created in this recipe will not be trusted over the Internet but can be used for securing local or internal communication. For production use, it is advisable to get a certificate signed from an external, well known certification authority. This will avoid the initial errors in browsers.

There's more…

To get a signed certificate from an external certification authority, you will need a CSR document.

The following are the steps to generate a CSR:

  1. Generate a key for the CSR:
    $ openssl genrsa -des3 -out server.key 2048
    
  2. You will be asked to enter a passphrase for the key and then verify it. They will be generated with name server.key.
  3. Now, remove the passphrase from the key. We don't want to enter a passphrase each time a key is used:
    $ openssl rsa -in server.key -out server.key.insecure
    $ mv server.key server.key.secure
    $ mv server.key.insecure server.key
    
  4. Next, create the CSR with the following command:
    $ openssl req -new -key server.key -out server.csr
    
  5. A CSR file is created with the name server.csr, and now you can submit this CSR for signing purposes.

See also

How it works…

We have created a self-signed certificate to secure an HTTP communication. The key will be used to encrypt all communication with clients. Another thing to note is that we have defined a separate Virtual Host entry on port 443. This Virtual Host will be used for all requests that are received over port 443. At the same time, we have allowed non-secured HTTP communication for the same Virtual Host. To disable non-secure communication on port 80, you can simply comment out the original Virtual Host configuration. Alternatively, you can separate both configurations into two files and enable or disable with the a2ensite and a2dissite commands.

Some of the parameters used for generating a key and certificate are as follows:

  • - nodes specifies that we do not want to use a passphrase for a key.
  • - days this specifies the number of days the certificate is valid for. Our certificate is valid for 365 days, that is, a year.
  • - newkey rsa:2048 this option is used to generate a certificate along with a private key. rsa:2048 specifies the 2048 bit long RSA private key.

I have modified the existing Virtual Host entry to demonstrate the minimal configuration required to enable secure HTTP communication. You can always use the default secure Virtual Host configuration available under sites-available/default-ssl.conf. This file provides some additional parameters with respective comments.

The certificate created in this recipe will not be trusted over the Internet but can be used for securing local or internal communication. For production use, it is advisable to get a certificate signed from an external, well known certification authority. This will avoid the initial errors in browsers.

There's more…

To get a signed certificate from an external certification authority, you will need a CSR document.

The following are the steps to generate a CSR:

  1. Generate a key for the CSR:
    $ openssl genrsa -des3 -out server.key 2048
    
  2. You will be asked to enter a passphrase for the key and then verify it. They will be generated with name server.key.
  3. Now, remove the passphrase from the key. We don't want to enter a passphrase each time a key is used:
    $ openssl rsa -in server.key -out server.key.insecure
    $ mv server.key server.key.secure
    $ mv server.key.insecure server.key
    
  4. Next, create the CSR with the following command:
    $ openssl req -new -key server.key -out server.csr
    
  5. A CSR file is created with the name server.csr, and now you can submit this CSR for signing purposes.

See also

There's more…

To get a signed certificate from an external certification authority, you will need a CSR document.

The following are the steps to generate a CSR:

  1. Generate a key for the CSR:
    $ openssl genrsa -des3 -out server.key 2048
    
  2. You will be asked to enter a passphrase for the key and then verify it. They will be generated with name server.key.
  3. Now, remove the passphrase from the key. We don't want to enter a passphrase each time a key is used:
    $ openssl rsa -in server.key -out server.key.insecure
    $ mv server.key server.key.secure
    $ mv server.key.insecure server.key
    
  4. Next, create the CSR with the following command:
    $ openssl req -new -key server.key -out server.csr
    
  5. A CSR file is created with the name server.csr, and now you can submit this CSR for signing purposes.

See also

See also

Installing Nginx with PHP_FPM

In this recipe, we will learn how to install and set up Nginx as a web server. We will also install PHP to be able to serve dynamic content. We need to install PHP_FPM (FastCGI Process Manager), as Nginx doesn't support the native execution of PHP scripts. We will install the latest stable version available from the Nginx package repository.

Getting ready

You will need access to a root account or an account with sudo privileges.

How to do it…

Follow these steps to install Nginx with PHP_FPM:

  1. Update the apt package repository and install Nginx. As of writing this Ubuntu 16.04 repository contains latest stable release of Nginx with version 1.10.0:
    $ sudo apt-get update
    $ sudo apt-get install nginx
    
  2. Check if Nginx is properly installed and running:
    $ sudo service nginx status
    
  3. Check the installed version of Nginx:
    $ nginx -v
    
  4. You may want to point your browser to the server IP or domain. You should see a default Nginx welcome page:
    How to do it…
  5. Next, proceed with installing PHP_FPM:
    $ sudo apt-get install php7.0-fpm
    
  6. Configure Nginx to use the PHP processor. Nginx sites are listed at /etc/nginx/sites-available. We will modify the default site:
    $ sudo nano /etc/nginx/sites-available/default
    
  7. Find a line stating the priority of the index file and add index.php as a first option:
    index index.php index.html index.htm;
    
  8. Next, add the following two location directives:
    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock
    ;
    }
    
  9. Save the changes and exit the file. It should look similar to this:
    How to do it…
  10. Change the PHP settings to disable PATH_TRANSLATED support. Find an option, cgi.fix_pathinfo, and uncomment it with the value set to 0:
    $ sudo nano /etc/php/7.0/fpm/php.ini
    cgi.fix_pathinfo=0
    
  11. Now, restart PHP_FPM and Nginx for the changes to take effect:
    $ sudo service php7.0-fpm restart
    $ sudo service nginx restart
    
  12. Create an index.php file with some PHP code in it at the path mentioned in the default site configuration:
    $ sudo nano /var/www/html/index.php
    <?php phpinfo(); ?>
    
  13. Open your browser and point it to your server. You should see the result of your PHP script:
    How to do it…

How it works…

Here, we have installed the latest stable version of the Nginx server with PHP_FPM to support dynamic content scripted with PHP. The Ubuntu repository for version 16.04 contains the latest stable release of Nginx, So installing Nginx is as easy as a single command. If you are interested in more recent versions Nginx maintains their own package repository for mainline packages. You just need to add repository, the rest of the installation process is similar to a single apt-get install nginx command.

Note

If you are running the Apache server on the same machine, you may want to change the default port Nginx runs on. You can find these settings under site configurations, located at /etc/nginx/sites-available. Nginx creates default site configuration with the filename set to default. Find the lines that start with listen and change the port from its default, 80, to any port number of your choice.

After installing Nginx, we need to configure it to support dynamic content. Here, we have selected PHP as a dynamic content processor. PHP is a popular scripting language and very commonly used with web servers for dynamic content processing. You can also add support for other modules by installing their respective processors. After installing PHP_FPM, we have configured Nginx to use PHP_FPM and pass all PHP requests to the FPM module on a socket connection.

We have used two location blocks in configuration. The first block search is for static content, such as files and directories, and then if nothing matches, the request is forwarded to index.php, which is in turn forwarded to the FastCGI module for processing. This ensures that Nginx serves all static content without executing PHP, and only requests that are not static files and directories are passed to the FPM module.

The following is a brief description of the parameters used under FastCGI configuration:

  • The parameter try_files configures Nginx to return 404 pages, that is, the page not found error, for any requests that do not match website content. This is limited to static files.
  • With the parameter fastcgi_param, you can forward the script name and query string to the PHP FPM process.
  • One more optional parameter is cgi.fix_pathinfo=0, under the PHP configuration file php.ini. By default, PHP is set to search for the exact script filename and then search for the closest match if the exact name is not found. This may become a security risk by allowing an attacker to execute random scripts with simple guesswork for script names. We have disabled this by setting its value to 0.

Finally, after we restart PHP_FPM and Nginx, our server is ready to process static as well as dynamic content. All static content will be handled by Nginx itself, and requests for URLs that end with .php will be forwarded to PHP_FPM for processing. Nginx may cache the processed result for future use.

There's more…

If you are running Ubuntu 12.10, you may need to install the following dependencies before adding the Nginx repository to the installation sources:

  1. Install python-software-properties and software-properties-common:
    $ sudo apt-get install python-software-properties
    $ sudo apt-get install software-properties-common
    
  2. You may want to remove your Apache installation completely. Use the following commands to remove Apache:
    $ sudo service apache2 stop
    $ sudo apt-get remove --purge apache2 apache2-utils apache2.2-bin apache2-common
    

Nginx maintains their own package repositories for stable and mainline releases. These repositories can be used to get the latest updates of Nginx as and when available. Use the stable repository, - $ sudo add-apt-repository ppa:nginx/stable.

Use the mainline repository - $ sudo add-apt-repository ppa:nginx/development.

See also

Getting ready

You will need access to a root account or an account with sudo privileges.

How to do it…

Follow these steps to install Nginx with PHP_FPM:

  1. Update the apt package repository and install Nginx. As of writing this Ubuntu 16.04 repository contains latest stable release of Nginx with version 1.10.0:
    $ sudo apt-get update
    $ sudo apt-get install nginx
    
  2. Check if Nginx is properly installed and running:
    $ sudo service nginx status
    
  3. Check the installed version of Nginx:
    $ nginx -v
    
  4. You may want to point your browser to the server IP or domain. You should see a default Nginx welcome page:
    How to do it…
  5. Next, proceed with installing PHP_FPM:
    $ sudo apt-get install php7.0-fpm
    
  6. Configure Nginx to use the PHP processor. Nginx sites are listed at /etc/nginx/sites-available. We will modify the default site:
    $ sudo nano /etc/nginx/sites-available/default
    
  7. Find a line stating the priority of the index file and add index.php as a first option:
    index index.php index.html index.htm;
    
  8. Next, add the following two location directives:
    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock
    ;
    }
    
  9. Save the changes and exit the file. It should look similar to this:
    How to do it…
  10. Change the PHP settings to disable PATH_TRANSLATED support. Find an option, cgi.fix_pathinfo, and uncomment it with the value set to 0:
    $ sudo nano /etc/php/7.0/fpm/php.ini
    cgi.fix_pathinfo=0
    
  11. Now, restart PHP_FPM and Nginx for the changes to take effect:
    $ sudo service php7.0-fpm restart
    $ sudo service nginx restart
    
  12. Create an index.php file with some PHP code in it at the path mentioned in the default site configuration:
    $ sudo nano /var/www/html/index.php
    <?php phpinfo(); ?>
    
  13. Open your browser and point it to your server. You should see the result of your PHP script:
    How to do it…

How it works…

Here, we have installed the latest stable version of the Nginx server with PHP_FPM to support dynamic content scripted with PHP. The Ubuntu repository for version 16.04 contains the latest stable release of Nginx, So installing Nginx is as easy as a single command. If you are interested in more recent versions Nginx maintains their own package repository for mainline packages. You just need to add repository, the rest of the installation process is similar to a single apt-get install nginx command.

Note

If you are running the Apache server on the same machine, you may want to change the default port Nginx runs on. You can find these settings under site configurations, located at /etc/nginx/sites-available. Nginx creates default site configuration with the filename set to default. Find the lines that start with listen and change the port from its default, 80, to any port number of your choice.

After installing Nginx, we need to configure it to support dynamic content. Here, we have selected PHP as a dynamic content processor. PHP is a popular scripting language and very commonly used with web servers for dynamic content processing. You can also add support for other modules by installing their respective processors. After installing PHP_FPM, we have configured Nginx to use PHP_FPM and pass all PHP requests to the FPM module on a socket connection.

We have used two location blocks in configuration. The first block search is for static content, such as files and directories, and then if nothing matches, the request is forwarded to index.php, which is in turn forwarded to the FastCGI module for processing. This ensures that Nginx serves all static content without executing PHP, and only requests that are not static files and directories are passed to the FPM module.

The following is a brief description of the parameters used under FastCGI configuration:

  • The parameter try_files configures Nginx to return 404 pages, that is, the page not found error, for any requests that do not match website content. This is limited to static files.
  • With the parameter fastcgi_param, you can forward the script name and query string to the PHP FPM process.
  • One more optional parameter is cgi.fix_pathinfo=0, under the PHP configuration file php.ini. By default, PHP is set to search for the exact script filename and then search for the closest match if the exact name is not found. This may become a security risk by allowing an attacker to execute random scripts with simple guesswork for script names. We have disabled this by setting its value to 0.

Finally, after we restart PHP_FPM and Nginx, our server is ready to process static as well as dynamic content. All static content will be handled by Nginx itself, and requests for URLs that end with .php will be forwarded to PHP_FPM for processing. Nginx may cache the processed result for future use.

There's more…

If you are running Ubuntu 12.10, you may need to install the following dependencies before adding the Nginx repository to the installation sources:

  1. Install python-software-properties and software-properties-common:
    $ sudo apt-get install python-software-properties
    $ sudo apt-get install software-properties-common
    
  2. You may want to remove your Apache installation completely. Use the following commands to remove Apache:
    $ sudo service apache2 stop
    $ sudo apt-get remove --purge apache2 apache2-utils apache2.2-bin apache2-common
    

Nginx maintains their own package repositories for stable and mainline releases. These repositories can be used to get the latest updates of Nginx as and when available. Use the stable repository, - $ sudo add-apt-repository ppa:nginx/stable.

Use the mainline repository - $ sudo add-apt-repository ppa:nginx/development.

See also

How to do it…

Follow these steps to install Nginx with PHP_FPM:

  1. Update the apt package repository and install Nginx. As of writing this Ubuntu 16.04 repository contains latest stable release of Nginx with version 1.10.0:
    $ sudo apt-get update
    $ sudo apt-get install nginx
    
  2. Check if Nginx is properly installed and running:
    $ sudo service nginx status
    
  3. Check the installed version of Nginx:
    $ nginx -v
    
  4. You may want to point your browser to the server IP or domain. You should see a default Nginx welcome page:
    How to do it…
  5. Next, proceed with installing PHP_FPM:
    $ sudo apt-get install php7.0-fpm
    
  6. Configure Nginx to use the PHP processor. Nginx sites are listed at /etc/nginx/sites-available. We will modify the default site:
    $ sudo nano /etc/nginx/sites-available/default
    
  7. Find a line stating the priority of the index file and add index.php as a first option:
    index index.php index.html index.htm;
    
  8. Next, add the following two location directives:
    location / {
        try_files $uri $uri/ /index.php;
    }
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING    $query_string;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock
    ;
    }
    
  9. Save the changes and exit the file. It should look similar to this:
    How to do it…
  10. Change the PHP settings to disable PATH_TRANSLATED support. Find an option, cgi.fix_pathinfo, and uncomment it with the value set to 0:
    $ sudo nano /etc/php/7.0/fpm/php.ini
    cgi.fix_pathinfo=0
    
  11. Now, restart PHP_FPM and Nginx for the changes to take effect:
    $ sudo service php7.0-fpm restart
    $ sudo service nginx restart
    
  12. Create an index.php file with some PHP code in it at the path mentioned in the default site configuration:
    $ sudo nano /var/www/html/index.php
    <?php phpinfo(); ?>
    
  13. Open your browser and point it to your server. You should see the result of your PHP script:
    How to do it…

How it works…

Here, we have installed the latest stable version of the Nginx server with PHP_FPM to support dynamic content scripted with PHP. The Ubuntu repository for version 16.04 contains the latest stable release of Nginx, So installing Nginx is as easy as a single command. If you are interested in more recent versions Nginx maintains their own package repository for mainline packages. You just need to add repository, the rest of the installation process is similar to a single apt-get install nginx command.

Note

If you are running the Apache server on the same machine, you may want to change the default port Nginx runs on. You can find these settings under site configurations, located at /etc/nginx/sites-available. Nginx creates default site configuration with the filename set to default. Find the lines that start with listen and change the port from its default, 80, to any port number of your choice.

After installing Nginx, we need to configure it to support dynamic content. Here, we have selected PHP as a dynamic content processor. PHP is a popular scripting language and very commonly used with web servers for dynamic content processing. You can also add support for other modules by installing their respective processors. After installing PHP_FPM, we have configured Nginx to use PHP_FPM and pass all PHP requests to the FPM module on a socket connection.

We have used two location blocks in configuration. The first block search is for static content, such as files and directories, and then if nothing matches, the request is forwarded to index.php, which is in turn forwarded to the FastCGI module for processing. This ensures that Nginx serves all static content without executing PHP, and only requests that are not static files and directories are passed to the FPM module.

The following is a brief description of the parameters used under FastCGI configuration:

  • The parameter try_files configures Nginx to return 404 pages, that is, the page not found error, for any requests that do not match website content. This is limited to static files.
  • With the parameter fastcgi_param, you can forward the script name and query string to the PHP FPM process.
  • One more optional parameter is cgi.fix_pathinfo=0, under the PHP configuration file php.ini. By default, PHP is set to search for the exact script filename and then search for the closest match if the exact name is not found. This may become a security risk by allowing an attacker to execute random scripts with simple guesswork for script names. We have disabled this by setting its value to 0.

Finally, after we restart PHP_FPM and Nginx, our server is ready to process static as well as dynamic content. All static content will be handled by Nginx itself, and requests for URLs that end with .php will be forwarded to PHP_FPM for processing. Nginx may cache the processed result for future use.

There's more…

If you are running Ubuntu 12.10, you may need to install the following dependencies before adding the Nginx repository to the installation sources:

  1. Install python-software-properties and software-properties-common:
    $ sudo apt-get install python-software-properties
    $ sudo apt-get install software-properties-common
    
  2. You may want to remove your Apache installation completely. Use the following commands to remove Apache:
    $ sudo service apache2 stop
    $ sudo apt-get remove --purge apache2 apache2-utils apache2.2-bin apache2-common
    

Nginx maintains their own package repositories for stable and mainline releases. These repositories can be used to get the latest updates of Nginx as and when available. Use the stable repository, - $ sudo add-apt-repository ppa:nginx/stable.

Use the mainline repository - $ sudo add-apt-repository ppa:nginx/development.

See also

How it works…

Here, we have installed the latest stable version of the Nginx server with PHP_FPM to support dynamic content scripted with PHP. The Ubuntu repository for version 16.04 contains the latest stable release of Nginx, So installing Nginx is as easy as a single command. If you are interested in more recent versions Nginx maintains their own package repository for mainline packages. You just need to add repository, the rest of the installation process is similar to a single apt-get install nginx command.

Note

If you are running the Apache server on the same machine, you may want to change the default port Nginx runs on. You can find these settings under site configurations, located at /etc/nginx/sites-available. Nginx creates default site configuration with the filename set to default. Find the lines that start with listen and change the port from its default, 80, to any port number of your choice.

After installing Nginx, we need to configure it to support dynamic content. Here, we have selected PHP as a dynamic content processor. PHP is a popular scripting language and very commonly used with web servers for dynamic content processing. You can also add support for other modules by installing their respective processors. After installing PHP_FPM, we have configured Nginx to use PHP_FPM and pass all PHP requests to the FPM module on a socket connection.

We have used two location blocks in configuration. The first block search is for static content, such as files and directories, and then if nothing matches, the request is forwarded to index.php, which is in turn forwarded to the FastCGI module for processing. This ensures that Nginx serves all static content without executing PHP, and only requests that are not static files and directories are passed to the FPM module.

The following is a brief description of the parameters used under FastCGI configuration:

  • The parameter try_files configures Nginx to return 404 pages, that is, the page not found error, for any requests that do not match website content. This is limited to static files.
  • With the parameter fastcgi_param, you can forward the script name and query string to the PHP FPM process.
  • One more optional parameter is cgi.fix_pathinfo=0, under the PHP configuration file php.ini. By default, PHP is set to search for the exact script filename and then search for the closest match if the exact name is not found. This may become a security risk by allowing an attacker to execute random scripts with simple guesswork for script names. We have disabled this by setting its value to 0.

Finally, after we restart PHP_FPM and Nginx, our server is ready to process static as well as dynamic content. All static content will be handled by Nginx itself, and requests for URLs that end with .php will be forwarded to PHP_FPM for processing. Nginx may cache the processed result for future use.

There's more…

If you are running Ubuntu 12.10, you may need to install the following dependencies before adding the Nginx repository to the installation sources:

  1. Install python-software-properties and software-properties-common:
    $ sudo apt-get install python-software-properties
    $ sudo apt-get install software-properties-common
    
  2. You may want to remove your Apache installation completely. Use the following commands to remove Apache:
    $ sudo service apache2 stop
    $ sudo apt-get remove --purge apache2 apache2-utils apache2.2-bin apache2-common
    

Nginx maintains their own package repositories for stable and mainline releases. These repositories can be used to get the latest updates of Nginx as and when available. Use the stable repository, - $ sudo add-apt-repository ppa:nginx/stable.

Use the mainline repository - $ sudo add-apt-repository ppa:nginx/development.

See also

There's more…

If you are running Ubuntu 12.10, you may need to install the following dependencies before adding the Nginx repository to the installation sources:

  1. Install python-software-properties and software-properties-common:
    $ sudo apt-get install python-software-properties
    $ sudo apt-get install software-properties-common
    
  2. You may want to remove your Apache installation completely. Use the following commands to remove Apache:
    $ sudo service apache2 stop
    $ sudo apt-get remove --purge apache2 apache2-utils apache2.2-bin apache2-common
    

Nginx maintains their own package repositories for stable and mainline releases. These repositories can be used to get the latest updates of Nginx as and when available. Use the stable repository, - $ sudo add-apt-repository ppa:nginx/stable.

Use the mainline repository - $ sudo add-apt-repository ppa:nginx/development.

See also

See also

Setting Nginx as a reverse proxy

Apache and Nginx are two popular open source web servers. Both are very powerful, but at the same time have their own disadvantages as well. Apache is not good at handling high load environments with multiple concurrent requests and Nginx does not have inbuilt support for dynamic content processing. Many administrators overcome these problems by using both Apache and Nginx together. Nginx handles all incoming requests and only passes requests for dynamic content to Apache. Additionally, Nginx can provide a catching option which enables the server to respond to a request with results from a similar previous request. This helps to reduce the overall response time and minimize the load sent to Apache.

In this recipe, we will learn how to set up a web server configured with a reverse proxy. We will use Nginx as a reverse proxy, which will serve all static content and pass the requests for dynamic content to Apache.

Getting ready

You will need access to a root account or an account with sudo privileges.

I assume that Apache is installed and running with a virtual host, example.com.

How to do it…

Follow these steps to set Nginx as a reverse proxy:

  1. Install Nginx with the following command:
    $ sudo apt-get update
    $ sudo apt-get install nginx
    
  2. Create a new site configuration under /etc/nginx/sites-available and add the following content to it:
    $ sudo nano /etc/nginx/sites-available/reverse_proxy
    server {
      listen 80;
    
      root /var/www/example.com;
      
    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 ~* \.(js|css|jpg|jpeg|png|svg|html|htm)$ {
        expires      30d;
      }
    
      location ~ /\.ht {
        deny all;
      }
    }
    
  3. Enable this new configuration by creating a symbolic link under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/reverse_proxy \
    /etc/nginx/sites-enabled/reverse_proxy
    
  4. Optionally, disable the default site by removing the symbolic link from sites-enabled:
    $ sudo rm /etc/nginx/sites-enabled/default
    
  5. Next, we need to change the Apache settings to listen on port 8080. This will leave port 80 to be used by Nginx:
    $ sudo nano /etc/apache2/ports.conf
    listen 127.0.0.1:8080
    
  6. Also change NameVirtualHost, if you are using it:
    NameVirtualHost 127.0.0.1:8080
    
  7. Change the virtual hosts settings to listen on port 8080:
    $ sudo nano /etc/apache2/sites-available/example.com
    <VirtualHost 127.0.0.1:8080>
      ServerName example.com
      ServerAdmin webmaster@example.com
      DocumentRoot /var/www/example.com/public_html
    </VirtualHost>
    
  8. Save the changes and restart Apache for the changes to take effect:
    $ sudo service apache2 restart
    
  9. Now, restart Nginx:
    $ sudo service nginx restart
    
  10. Check for open ports with the following command:
    $ sudo netstat -pltn
    
    How to do it…
  11. Open your browser and point it to the IP address of your server. It should load the page configured under the Apache virtual host, example.com.

How it works…

With the proxy_pass parameter, we have simply asked Nginx to pass all requests for PHP scripts to Apache on 127.0.0.1 on port 8080. Then, we set Apache to listen on the loopback IP and port 8080, which will receive requests forwarded by Nginx and process them with an internal PHP processor. All non-PHP content will still be served by Nginx from the /var/www directory. The try_files $uri $uri/ /index.php; option sets Nginx to search for the file with a specified name and then look for the folder; lastly, if both file and folder are not found, send the request to index.php, which will then be processed by Apache.

Other options used with proxy pass ensures that Apache and PHP scripts receive the actual hostname and IP of the client and not of the Nginx server. You can use an additional module named libapache2-mod-rpaf on Apache. This module provides an option to set a proxy IP address and rename the parameters sent by the proxy server. You can install the module with the following command:

$ sudo apt-get install libapache2-mod-rpaf

The configuration file for this module is available at /etc/apache2/mods-available/rpaf.conf.

You can find various other proxy options and their respective explanations in the Nginx documentation at http://nginx.org/en/docs/http/ngx_http_proxy_module.html

Finally, with Nginx set as a frontend, Apache will not have to interact directly with HTTP clients. You may want to disable some of the Apache modules that will not be used in this setup:

$ sudo a2dismod deflate cgi negotiation autoindex

As always, do not forget to reload Apache after any changes.

There's more…

Nginx can be set to cache the response received from the backend server and thereby minimize repeated requests on backend servers, as well as the response time. Nginx can cache the content in local files and serve new requests from the cache. The cache can be invalidated or even disabled based on the request received. To enable caching, add the following settings to the Nginx site configuration:

  proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=backend-cache:8m max_size=50m;
 proxy_cache_key "$scheme$request_method$host$request_uri$args";
  server {
     ## add other settings heres
    location / {
      proxy_pass 127.0.0.1:8080;
      proxy_cache backend-cache;
      proxy_cache_bypass $http_cache_control;
      add_header X-Proxy-Cache $upstream_cache_status;
      proxy_cache_valid  200 302  10m;
      proxy_cache_valid  404      1m;
    }
  }

You may need to create the proxy path directory /data/nginx/cache and set the appropriate file permissions. Set the directory ownership to www-data and restrict permissions to 700. You can use any location for cache data and not necessarily /data/nginx/cache.

This configuration sets the cache validity of 10 minutes, which is quite a lengthy period. This will work if you have static content that rarely changes. Instead, if you are serving dynamic content that is frequently updated, then you can take advantage of microcaching by setting the cache validity to a very small period of a few seconds. Add the following parameters to further improve your caching configuration for microcaching:

  • proxy_cache_lock on: Queues additional requests while the cache is being updated
  • proxy_cache_use_stale updating: Uses stale data while the cache is being updated

HAProxy and Varnish

HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.

Getting ready

You will need access to a root account or an account with sudo privileges.

I assume that Apache is installed and running with a virtual host, example.com.

How to do it…

Follow these steps to set Nginx as a reverse proxy:

  1. Install Nginx with the following command:
    $ sudo apt-get update
    $ sudo apt-get install nginx
    
  2. Create a new site configuration under /etc/nginx/sites-available and add the following content to it:
    $ sudo nano /etc/nginx/sites-available/reverse_proxy
    server {
      listen 80;
    
      root /var/www/example.com;
      
    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 ~* \.(js|css|jpg|jpeg|png|svg|html|htm)$ {
        expires      30d;
      }
    
      location ~ /\.ht {
        deny all;
      }
    }
    
  3. Enable this new configuration by creating a symbolic link under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/reverse_proxy \
    /etc/nginx/sites-enabled/reverse_proxy
    
  4. Optionally, disable the default site by removing the symbolic link from sites-enabled:
    $ sudo rm /etc/nginx/sites-enabled/default
    
  5. Next, we need to change the Apache settings to listen on port 8080. This will leave port 80 to be used by Nginx:
    $ sudo nano /etc/apache2/ports.conf
    listen 127.0.0.1:8080
    
  6. Also change NameVirtualHost, if you are using it:
    NameVirtualHost 127.0.0.1:8080
    
  7. Change the virtual hosts settings to listen on port 8080:
    $ sudo nano /etc/apache2/sites-available/example.com
    <VirtualHost 127.0.0.1:8080>
      ServerName example.com
      ServerAdmin webmaster@example.com
      DocumentRoot /var/www/example.com/public_html
    </VirtualHost>
    
  8. Save the changes and restart Apache for the changes to take effect:
    $ sudo service apache2 restart
    
  9. Now, restart Nginx:
    $ sudo service nginx restart
    
  10. Check for open ports with the following command:
    $ sudo netstat -pltn
    
    How to do it…
  11. Open your browser and point it to the IP address of your server. It should load the page configured under the Apache virtual host, example.com.

How it works…

With the proxy_pass parameter, we have simply asked Nginx to pass all requests for PHP scripts to Apache on 127.0.0.1 on port 8080. Then, we set Apache to listen on the loopback IP and port 8080, which will receive requests forwarded by Nginx and process them with an internal PHP processor. All non-PHP content will still be served by Nginx from the /var/www directory. The try_files $uri $uri/ /index.php; option sets Nginx to search for the file with a specified name and then look for the folder; lastly, if both file and folder are not found, send the request to index.php, which will then be processed by Apache.

Other options used with proxy pass ensures that Apache and PHP scripts receive the actual hostname and IP of the client and not of the Nginx server. You can use an additional module named libapache2-mod-rpaf on Apache. This module provides an option to set a proxy IP address and rename the parameters sent by the proxy server. You can install the module with the following command:

$ sudo apt-get install libapache2-mod-rpaf

The configuration file for this module is available at /etc/apache2/mods-available/rpaf.conf.

You can find various other proxy options and their respective explanations in the Nginx documentation at http://nginx.org/en/docs/http/ngx_http_proxy_module.html

Finally, with Nginx set as a frontend, Apache will not have to interact directly with HTTP clients. You may want to disable some of the Apache modules that will not be used in this setup:

$ sudo a2dismod deflate cgi negotiation autoindex

As always, do not forget to reload Apache after any changes.

There's more…

Nginx can be set to cache the response received from the backend server and thereby minimize repeated requests on backend servers, as well as the response time. Nginx can cache the content in local files and serve new requests from the cache. The cache can be invalidated or even disabled based on the request received. To enable caching, add the following settings to the Nginx site configuration:

  proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=backend-cache:8m max_size=50m;
 proxy_cache_key "$scheme$request_method$host$request_uri$args";
  server {
     ## add other settings heres
    location / {
      proxy_pass 127.0.0.1:8080;
      proxy_cache backend-cache;
      proxy_cache_bypass $http_cache_control;
      add_header X-Proxy-Cache $upstream_cache_status;
      proxy_cache_valid  200 302  10m;
      proxy_cache_valid  404      1m;
    }
  }

You may need to create the proxy path directory /data/nginx/cache and set the appropriate file permissions. Set the directory ownership to www-data and restrict permissions to 700. You can use any location for cache data and not necessarily /data/nginx/cache.

This configuration sets the cache validity of 10 minutes, which is quite a lengthy period. This will work if you have static content that rarely changes. Instead, if you are serving dynamic content that is frequently updated, then you can take advantage of microcaching by setting the cache validity to a very small period of a few seconds. Add the following parameters to further improve your caching configuration for microcaching:

  • proxy_cache_lock on: Queues additional requests while the cache is being updated
  • proxy_cache_use_stale updating: Uses stale data while the cache is being updated

HAProxy and Varnish

HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.

How to do it…

Follow these steps to set Nginx as a reverse proxy:

  1. Install Nginx with the following command:
    $ sudo apt-get update
    $ sudo apt-get install nginx
    
  2. Create a new site configuration under /etc/nginx/sites-available and add the following content to it:
    $ sudo nano /etc/nginx/sites-available/reverse_proxy
    server {
      listen 80;
    
      root /var/www/example.com;
      
    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 ~* \.(js|css|jpg|jpeg|png|svg|html|htm)$ {
        expires      30d;
      }
    
      location ~ /\.ht {
        deny all;
      }
    }
    
  3. Enable this new configuration by creating a symbolic link under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/reverse_proxy \
    /etc/nginx/sites-enabled/reverse_proxy
    
  4. Optionally, disable the default site by removing the symbolic link from sites-enabled:
    $ sudo rm /etc/nginx/sites-enabled/default
    
  5. Next, we need to change the Apache settings to listen on port 8080. This will leave port 80 to be used by Nginx:
    $ sudo nano /etc/apache2/ports.conf
    listen 127.0.0.1:8080
    
  6. Also change NameVirtualHost, if you are using it:
    NameVirtualHost 127.0.0.1:8080
    
  7. Change the virtual hosts settings to listen on port 8080:
    $ sudo nano /etc/apache2/sites-available/example.com
    <VirtualHost 127.0.0.1:8080>
      ServerName example.com
      ServerAdmin webmaster@example.com
      DocumentRoot /var/www/example.com/public_html
    </VirtualHost>
    
  8. Save the changes and restart Apache for the changes to take effect:
    $ sudo service apache2 restart
    
  9. Now, restart Nginx:
    $ sudo service nginx restart
    
  10. Check for open ports with the following command:
    $ sudo netstat -pltn
    
    How to do it…
  11. Open your browser and point it to the IP address of your server. It should load the page configured under the Apache virtual host, example.com.

How it works…

With the proxy_pass parameter, we have simply asked Nginx to pass all requests for PHP scripts to Apache on 127.0.0.1 on port 8080. Then, we set Apache to listen on the loopback IP and port 8080, which will receive requests forwarded by Nginx and process them with an internal PHP processor. All non-PHP content will still be served by Nginx from the /var/www directory. The try_files $uri $uri/ /index.php; option sets Nginx to search for the file with a specified name and then look for the folder; lastly, if both file and folder are not found, send the request to index.php, which will then be processed by Apache.

Other options used with proxy pass ensures that Apache and PHP scripts receive the actual hostname and IP of the client and not of the Nginx server. You can use an additional module named libapache2-mod-rpaf on Apache. This module provides an option to set a proxy IP address and rename the parameters sent by the proxy server. You can install the module with the following command:

$ sudo apt-get install libapache2-mod-rpaf

The configuration file for this module is available at /etc/apache2/mods-available/rpaf.conf.

You can find various other proxy options and their respective explanations in the Nginx documentation at http://nginx.org/en/docs/http/ngx_http_proxy_module.html

Finally, with Nginx set as a frontend, Apache will not have to interact directly with HTTP clients. You may want to disable some of the Apache modules that will not be used in this setup:

$ sudo a2dismod deflate cgi negotiation autoindex

As always, do not forget to reload Apache after any changes.

There's more…

Nginx can be set to cache the response received from the backend server and thereby minimize repeated requests on backend servers, as well as the response time. Nginx can cache the content in local files and serve new requests from the cache. The cache can be invalidated or even disabled based on the request received. To enable caching, add the following settings to the Nginx site configuration:

  proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=backend-cache:8m max_size=50m;
 proxy_cache_key "$scheme$request_method$host$request_uri$args";
  server {
     ## add other settings heres
    location / {
      proxy_pass 127.0.0.1:8080;
      proxy_cache backend-cache;
      proxy_cache_bypass $http_cache_control;
      add_header X-Proxy-Cache $upstream_cache_status;
      proxy_cache_valid  200 302  10m;
      proxy_cache_valid  404      1m;
    }
  }

You may need to create the proxy path directory /data/nginx/cache and set the appropriate file permissions. Set the directory ownership to www-data and restrict permissions to 700. You can use any location for cache data and not necessarily /data/nginx/cache.

This configuration sets the cache validity of 10 minutes, which is quite a lengthy period. This will work if you have static content that rarely changes. Instead, if you are serving dynamic content that is frequently updated, then you can take advantage of microcaching by setting the cache validity to a very small period of a few seconds. Add the following parameters to further improve your caching configuration for microcaching:

  • proxy_cache_lock on: Queues additional requests while the cache is being updated
  • proxy_cache_use_stale updating: Uses stale data while the cache is being updated

HAProxy and Varnish

HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.

How it works…

With the proxy_pass parameter, we have simply asked Nginx to pass all requests for PHP scripts to Apache on 127.0.0.1 on port 8080. Then, we set Apache to listen on the loopback IP and port 8080, which will receive requests forwarded by Nginx and process them with an internal PHP processor. All non-PHP content will still be served by Nginx from the /var/www directory. The try_files $uri $uri/ /index.php; option sets Nginx to search for the file with a specified name and then look for the folder; lastly, if both file and folder are not found, send the request to index.php, which will then be processed by Apache.

Other options used with proxy pass ensures that Apache and PHP scripts receive the actual hostname and IP of the client and not of the Nginx server. You can use an additional module named libapache2-mod-rpaf on Apache. This module provides an option to set a proxy IP address and rename the parameters sent by the proxy server. You can install the module with the following command:

$ sudo apt-get install libapache2-mod-rpaf

The configuration file for this module is available at /etc/apache2/mods-available/rpaf.conf.

You can find various other proxy options and their respective explanations in the Nginx documentation at http://nginx.org/en/docs/http/ngx_http_proxy_module.html

Finally, with Nginx set as a frontend, Apache will not have to interact directly with HTTP clients. You may want to disable some of the Apache modules that will not be used in this setup:

$ sudo a2dismod deflate cgi negotiation autoindex

As always, do not forget to reload Apache after any changes.

There's more…

Nginx can be set to cache the response received from the backend server and thereby minimize repeated requests on backend servers, as well as the response time. Nginx can cache the content in local files and serve new requests from the cache. The cache can be invalidated or even disabled based on the request received. To enable caching, add the following settings to the Nginx site configuration:

  proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=backend-cache:8m max_size=50m;
 proxy_cache_key "$scheme$request_method$host$request_uri$args";
  server {
     ## add other settings heres
    location / {
      proxy_pass 127.0.0.1:8080;
      proxy_cache backend-cache;
      proxy_cache_bypass $http_cache_control;
      add_header X-Proxy-Cache $upstream_cache_status;
      proxy_cache_valid  200 302  10m;
      proxy_cache_valid  404      1m;
    }
  }

You may need to create the proxy path directory /data/nginx/cache and set the appropriate file permissions. Set the directory ownership to www-data and restrict permissions to 700. You can use any location for cache data and not necessarily /data/nginx/cache.

This configuration sets the cache validity of 10 minutes, which is quite a lengthy period. This will work if you have static content that rarely changes. Instead, if you are serving dynamic content that is frequently updated, then you can take advantage of microcaching by setting the cache validity to a very small period of a few seconds. Add the following parameters to further improve your caching configuration for microcaching:

  • proxy_cache_lock on: Queues additional requests while the cache is being updated
  • proxy_cache_use_stale updating: Uses stale data while the cache is being updated

HAProxy and Varnish

HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.

There's more…

Nginx can be set to cache the response received from the backend server and thereby minimize repeated requests on backend servers, as well as the response time. Nginx can cache the content in local files and serve new requests from the cache. The cache can be invalidated or even disabled based on the request received. To enable caching, add the following settings to the Nginx site configuration:

  proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=backend-cache:8m max_size=50m;
 proxy_cache_key "$scheme$request_method$host$request_uri$args";
  server {
     ## add other settings heres
    location / {
      proxy_pass 127.0.0.1:8080;
      proxy_cache backend-cache;
      proxy_cache_bypass $http_cache_control;
      add_header X-Proxy-Cache $upstream_cache_status;
      proxy_cache_valid  200 302  10m;
      proxy_cache_valid  404      1m;
    }
  }

You may need to create the proxy path directory /data/nginx/cache and set the appropriate file permissions. Set the directory ownership to www-data and restrict permissions to 700. You can use any location for cache data and not necessarily /data/nginx/cache.

This configuration sets the cache validity of 10 minutes, which is quite a lengthy period. This will work if you have static content that rarely changes. Instead, if you are serving dynamic content that is frequently updated, then you can take advantage of microcaching by setting the cache validity to a very small period of a few seconds. Add the following parameters to further improve your caching configuration for microcaching:

  • proxy_cache_lock on: Queues additional requests while the cache is being updated
  • proxy_cache_use_stale updating: Uses stale data while the cache is being updated

HAProxy and Varnish

HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.

HAProxy and Varnish

HAProxy and Varnish are other popular options for the reverse proxy and the caching proxy, respectively. Both of them can offer improved performance when compared with Nginx. HAProxy can also be used as a Layer 4 and Layer 7 load balancer. We covered HAProxy in Chapter 2, Networking, in the Load Balancing with HAProxy recipe.

Load balancing with Nginx

When an application becomes popular and the number of requests increases beyond the capacity of a single server, we need to scale horizontally. We can always increase the capacity (vertical scaling) of a server by adding more memory and processing power, but a single server cannot scale beyond a certain limit. While adding separate servers or replicas of the application server, we need a mechanism which directs the traffic between these replicas. The hardware or software tool used for this purpose is known as a load balancer. Load balancers work as transparent mechanisms between the application server and client by distributing the requests between available instances. This is a commonly used technique for optimizing resource utilization and ensuring fault tolerant applications.

Nginx can be configured to work as an efficient Layer 7 as well as Layer 4 load balancer. Layer 7 is application layer of HTTP traffic. With Layer 4 support, Nginx can be used to load balance database servers or even XMPP traffic. With version 1.9.0, Nginx has enabled support for Layer 4 load balancing in their open source offerings.

In this recipe, we will learn how to set up Nginx as a load balancer.

Getting ready

You will need access to a root account or an account with sudo privileges.

You will need a minimum of three servers, as follows:

  • An Nginx server, which will be set as a load balancer
  • Two or more application servers with a similar code base set up on all

How to do it…

Follow these steps to set load balancing with Nginx:

  1. I assume that you already have Nginx installed. If not, you can refer to the Installing Nginx with PHP_FPM recipe of this chapter.
  2. Now, create a new configuration file under /etc/nginx/sites-available. Let's call it load_balancer:
    $ sudo nano /etc/nginx/sites-available/load_balancer
    
  3. Add the following lines to this load_balancer file. This is the minimum configuration required to get started with load balancing:
    upstream backend {
      
    server srv1.example.com;
      server srv2.example.com;
      server 192.168.1.12:8080;
      # other servers if any
    }
    server {
      listen 80;
      location / {
        proxy_pass http://backend;
      }
    }
    
  4. Enable this configuration by creating a symlink to load_balancer under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/load_balancer /etc/nginx/sites-enabled/load_balancer
    
  5. You may want to disable all other sites. Simply remove the respective links under sites-enabled.
  6. Check the configuration for syntax errors:
    $ sudo nginx -t
    
    How to do it…
  7. Now, reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  8. Yes, you are ready to use a load balancer. Open your favorite browser and point it to the IP of your Nginx server. You should see the contents of example.com or whatever domain you have used.

How it works…

We have created a very basic configuration for a load balancer. With this configuration, Nginx takes the traffic on port 80 and distributes it between srv1.example.com and srv2.example.com. With an upstream directive, we have defined a pool of servers that will actually process the requests. The upstream directive must be defined in a HTTP context. Once the upstream directive is defined, it will be available for all site configurations.

Note

All configuration files defined under sites-available are combined in the main configuration file, /etc/nginx/nginx.conf, under the HTTP directive. This enables us to set other directives in site-specific configurations without specifying the HTTP block.

When defining servers under an upstream directive, you can also use the IP address and port of the application server. This is an ideal configuration, especially when both the load balancer and the application servers are on the same private network, and this will help minimize the communication overhead between Nginx and backend servers.

Next, under the server block, we have configured Nginx to proxy_pass all requests to our backend pool.

While setting backend servers, we have not explicitly specified any load balancing algorithm. Nginx provides various load balancing algorithms that define the server that will receive a particular request. By default, Nginx uses a round-robin algorithm and passes requests to each available server in sequential order. Other available options are as follows:

  • least_connection: This passes the request to the host with the fewest active connections.
  • least_time: Nginx chooses the host with the lowest latency. This option is available with Nginx plus.
  • ip_hash: A hash of clients' IP addresses, and is used to determined the host to send the request to. This method guarantees that requests with the same IP address are served by the same host, unless the selected host is down.

Hash uses a user defined key to generate a hash value and then uses the hash to determine the processing host.

There's more…

Nginx provides various other load balancing features, such as weighted load balancing, active and passive health checks, backup servers, and session persistence. With the latest commits to the open source version, it now supports TCP load balancing as well. These settings can be updated at runtime with the help of HTTP APIs. The following are a few examples of different load balancing configurations:

  • Set server weights:
    upstream app-servers {
        server srv1.example.com weight 3;
        server srv2.example.com;
    }
    
  • Health checkups and backup servers:
    upstream app-servers {
        server srv1.example.com max_fails 3 fail_timeout 10;
        server srv2.example.com fail_timeout 50;
        192.168.1.12:8080 backup;
    }
    
  • Session persistence with cookies:
    upstream app-servers {
        server srv1.example.com;
        server srv2.example.com;
        sticky cookie srv_id expires=1h domain=.example.com path=/;
    }
    

Check the Nginx load balancing guide for various other load balancing options and their respective details.

See also

Getting ready

You will need access to a root account or an account with sudo privileges.

You will need a minimum of three servers, as follows:

  • An Nginx server, which will be set as a load balancer
  • Two or more application servers with a similar code base set up on all

How to do it…

Follow these steps to set load balancing with Nginx:

  1. I assume that you already have Nginx installed. If not, you can refer to the Installing Nginx with PHP_FPM recipe of this chapter.
  2. Now, create a new configuration file under /etc/nginx/sites-available. Let's call it load_balancer:
    $ sudo nano /etc/nginx/sites-available/load_balancer
    
  3. Add the following lines to this load_balancer file. This is the minimum configuration required to get started with load balancing:
    upstream backend {
      
    server srv1.example.com;
      server srv2.example.com;
      server 192.168.1.12:8080;
      # other servers if any
    }
    server {
      listen 80;
      location / {
        proxy_pass http://backend;
      }
    }
    
  4. Enable this configuration by creating a symlink to load_balancer under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/load_balancer /etc/nginx/sites-enabled/load_balancer
    
  5. You may want to disable all other sites. Simply remove the respective links under sites-enabled.
  6. Check the configuration for syntax errors:
    $ sudo nginx -t
    
    How to do it…
  7. Now, reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  8. Yes, you are ready to use a load balancer. Open your favorite browser and point it to the IP of your Nginx server. You should see the contents of example.com or whatever domain you have used.

How it works…

We have created a very basic configuration for a load balancer. With this configuration, Nginx takes the traffic on port 80 and distributes it between srv1.example.com and srv2.example.com. With an upstream directive, we have defined a pool of servers that will actually process the requests. The upstream directive must be defined in a HTTP context. Once the upstream directive is defined, it will be available for all site configurations.

Note

All configuration files defined under sites-available are combined in the main configuration file, /etc/nginx/nginx.conf, under the HTTP directive. This enables us to set other directives in site-specific configurations without specifying the HTTP block.

When defining servers under an upstream directive, you can also use the IP address and port of the application server. This is an ideal configuration, especially when both the load balancer and the application servers are on the same private network, and this will help minimize the communication overhead between Nginx and backend servers.

Next, under the server block, we have configured Nginx to proxy_pass all requests to our backend pool.

While setting backend servers, we have not explicitly specified any load balancing algorithm. Nginx provides various load balancing algorithms that define the server that will receive a particular request. By default, Nginx uses a round-robin algorithm and passes requests to each available server in sequential order. Other available options are as follows:

  • least_connection: This passes the request to the host with the fewest active connections.
  • least_time: Nginx chooses the host with the lowest latency. This option is available with Nginx plus.
  • ip_hash: A hash of clients' IP addresses, and is used to determined the host to send the request to. This method guarantees that requests with the same IP address are served by the same host, unless the selected host is down.

Hash uses a user defined key to generate a hash value and then uses the hash to determine the processing host.

There's more…

Nginx provides various other load balancing features, such as weighted load balancing, active and passive health checks, backup servers, and session persistence. With the latest commits to the open source version, it now supports TCP load balancing as well. These settings can be updated at runtime with the help of HTTP APIs. The following are a few examples of different load balancing configurations:

  • Set server weights:
    upstream app-servers {
        server srv1.example.com weight 3;
        server srv2.example.com;
    }
    
  • Health checkups and backup servers:
    upstream app-servers {
        server srv1.example.com max_fails 3 fail_timeout 10;
        server srv2.example.com fail_timeout 50;
        192.168.1.12:8080 backup;
    }
    
  • Session persistence with cookies:
    upstream app-servers {
        server srv1.example.com;
        server srv2.example.com;
        sticky cookie srv_id expires=1h domain=.example.com path=/;
    }
    

Check the Nginx load balancing guide for various other load balancing options and their respective details.

See also

How to do it…

Follow these steps to set load balancing with Nginx:

  1. I assume that you already have Nginx installed. If not, you can refer to the Installing Nginx with PHP_FPM recipe of this chapter.
  2. Now, create a new configuration file under /etc/nginx/sites-available. Let's call it load_balancer:
    $ sudo nano /etc/nginx/sites-available/load_balancer
    
  3. Add the following lines to this load_balancer file. This is the minimum configuration required to get started with load balancing:
    upstream backend {
      
    server srv1.example.com;
      server srv2.example.com;
      server 192.168.1.12:8080;
      # other servers if any
    }
    server {
      listen 80;
      location / {
        proxy_pass http://backend;
      }
    }
    
  4. Enable this configuration by creating a symlink to load_balancer under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/load_balancer /etc/nginx/sites-enabled/load_balancer
    
  5. You may want to disable all other sites. Simply remove the respective links under sites-enabled.
  6. Check the configuration for syntax errors:
    $ sudo nginx -t
    
    How to do it…
  7. Now, reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  8. Yes, you are ready to use a load balancer. Open your favorite browser and point it to the IP of your Nginx server. You should see the contents of example.com or whatever domain you have used.

How it works…

We have created a very basic configuration for a load balancer. With this configuration, Nginx takes the traffic on port 80 and distributes it between srv1.example.com and srv2.example.com. With an upstream directive, we have defined a pool of servers that will actually process the requests. The upstream directive must be defined in a HTTP context. Once the upstream directive is defined, it will be available for all site configurations.

Note

All configuration files defined under sites-available are combined in the main configuration file, /etc/nginx/nginx.conf, under the HTTP directive. This enables us to set other directives in site-specific configurations without specifying the HTTP block.

When defining servers under an upstream directive, you can also use the IP address and port of the application server. This is an ideal configuration, especially when both the load balancer and the application servers are on the same private network, and this will help minimize the communication overhead between Nginx and backend servers.

Next, under the server block, we have configured Nginx to proxy_pass all requests to our backend pool.

While setting backend servers, we have not explicitly specified any load balancing algorithm. Nginx provides various load balancing algorithms that define the server that will receive a particular request. By default, Nginx uses a round-robin algorithm and passes requests to each available server in sequential order. Other available options are as follows:

  • least_connection: This passes the request to the host with the fewest active connections.
  • least_time: Nginx chooses the host with the lowest latency. This option is available with Nginx plus.
  • ip_hash: A hash of clients' IP addresses, and is used to determined the host to send the request to. This method guarantees that requests with the same IP address are served by the same host, unless the selected host is down.

Hash uses a user defined key to generate a hash value and then uses the hash to determine the processing host.

There's more…

Nginx provides various other load balancing features, such as weighted load balancing, active and passive health checks, backup servers, and session persistence. With the latest commits to the open source version, it now supports TCP load balancing as well. These settings can be updated at runtime with the help of HTTP APIs. The following are a few examples of different load balancing configurations:

  • Set server weights:
    upstream app-servers {
        server srv1.example.com weight 3;
        server srv2.example.com;
    }
    
  • Health checkups and backup servers:
    upstream app-servers {
        server srv1.example.com max_fails 3 fail_timeout 10;
        server srv2.example.com fail_timeout 50;
        192.168.1.12:8080 backup;
    }
    
  • Session persistence with cookies:
    upstream app-servers {
        server srv1.example.com;
        server srv2.example.com;
        sticky cookie srv_id expires=1h domain=.example.com path=/;
    }
    

Check the Nginx load balancing guide for various other load balancing options and their respective details.

See also

How it works…

We have created a very basic configuration for a load balancer. With this configuration, Nginx takes the traffic on port 80 and distributes it between srv1.example.com and srv2.example.com. With an upstream directive, we have defined a pool of servers that will actually process the requests. The upstream directive must be defined in a HTTP context. Once the upstream directive is defined, it will be available for all site configurations.

Note

All configuration files defined under sites-available are combined in the main configuration file, /etc/nginx/nginx.conf, under the HTTP directive. This enables us to set other directives in site-specific configurations without specifying the HTTP block.

When defining servers under an upstream directive, you can also use the IP address and port of the application server. This is an ideal configuration, especially when both the load balancer and the application servers are on the same private network, and this will help minimize the communication overhead between Nginx and backend servers.

Next, under the server block, we have configured Nginx to proxy_pass all requests to our backend pool.

While setting backend servers, we have not explicitly specified any load balancing algorithm. Nginx provides various load balancing algorithms that define the server that will receive a particular request. By default, Nginx uses a round-robin algorithm and passes requests to each available server in sequential order. Other available options are as follows:

  • least_connection: This passes the request to the host with the fewest active connections.
  • least_time: Nginx chooses the host with the lowest latency. This option is available with Nginx plus.
  • ip_hash: A hash of clients' IP addresses, and is used to determined the host to send the request to. This method guarantees that requests with the same IP address are served by the same host, unless the selected host is down.

Hash uses a user defined key to generate a hash value and then uses the hash to determine the processing host.

There's more…

Nginx provides various other load balancing features, such as weighted load balancing, active and passive health checks, backup servers, and session persistence. With the latest commits to the open source version, it now supports TCP load balancing as well. These settings can be updated at runtime with the help of HTTP APIs. The following are a few examples of different load balancing configurations:

  • Set server weights:
    upstream app-servers {
        server srv1.example.com weight 3;
        server srv2.example.com;
    }
    
  • Health checkups and backup servers:
    upstream app-servers {
        server srv1.example.com max_fails 3 fail_timeout 10;
        server srv2.example.com fail_timeout 50;
        192.168.1.12:8080 backup;
    }
    
  • Session persistence with cookies:
    upstream app-servers {
        server srv1.example.com;
        server srv2.example.com;
        sticky cookie srv_id expires=1h domain=.example.com path=/;
    }
    

Check the Nginx load balancing guide for various other load balancing options and their respective details.

See also

There's more…

Nginx provides various other load balancing features, such as weighted load balancing, active and passive health checks, backup servers, and session persistence. With the latest commits to the open source version, it now supports TCP load balancing as well. These settings can be updated at runtime with the help of HTTP APIs. The following are a few examples of different load balancing configurations:

  • Set server weights:
    upstream app-servers {
        server srv1.example.com weight 3;
        server srv2.example.com;
    }
    
  • Health checkups and backup servers:
    upstream app-servers {
        server srv1.example.com max_fails 3 fail_timeout 10;
        server srv2.example.com fail_timeout 50;
        192.168.1.12:8080 backup;
    }
    
  • Session persistence with cookies:
    upstream app-servers {
        server srv1.example.com;
        server srv2.example.com;
        sticky cookie srv_id expires=1h domain=.example.com path=/;
    }
    

Check the Nginx load balancing guide for various other load balancing options and their respective details.

See also

See also

Setting HTTPs on Nginx

In this recipe, we will learn how to enable HTTPs communication on the Nginx server.

Getting ready

You will need access to a root account or an account with sudo privileges.

How to do it…

Follow these steps to set HTTPs on Nginx:

  1. Obtain a certificate and the related keys from a certification authority or create a self-signed certificate. To create a self-signed certificate, refer to the Securing web traffic with HTTPS recipe in this chapter.
  2. Create a directory to hold all certificate and keys:
    $ sudo mkdir -p /etc/nginx/ssl/example.com
    
  3. Move the certificate and keys to the preceding directory. Choose any secure method, such as SCP, SFTP, or any other.
  4. Create a virtual host entry or edit it if you already have one:
    $ sudo nano /etc/nginx/sites-available/example.com
    
  5. Match your virtual host configuration with the following:
    server {
      listen 80;
      server_name example.com www.example.com;
      return 301 https://$host$request_uri;
    }
    server {
      listen 443 ssl;
      server_name example.com www.example.com;
    
      
    root /var/www/example.com/public_html;
      index index.php index.html index.htm;
    
      ssl on;
      ssl_certificate     /etc/nginx/ssl/example.com/server.crt;
      ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
      # if you have received ca-certs.pem from Certification Authority
      #ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
    
      ssl_session_cache shared:SSL:10m;
      ssl_session_timeout 5m;
      keepalive_timeout   70;
    
      
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
      ssl_prefer_server_ciphers on;
      ssl_protocols  TLSv1.2 TLSv1.1 TLSv1;
      add_header Strict-Transport-Security "max-age=31536000";
    
      location / {
        try_files $uri $uri/ /index.php;
      }
    
      location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
      
    }
    }
    
  6. Enable this configuration by creating a symbolic link to it under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
    
  7. Check the configuration for syntax errors:
    $ sudo nginx -t
    
  8. Reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  9. Open your browser and access the site with domain or IP with HTTPS.

How it works…

When you know some basic configuration parameters, Nginx is quite simple to set up. Here, we have taken a few SSL settings from the default configuration file and added a simple redirection rule to redirect non-HTTPs traffic on port 80 to port 443. The first server block takes care of the redirection.

In addition to specifying the server certificate and keys, we have enabled session resumption by setting the cache to be shared across the Nginx process. We also have a timeout value of 5 minutes.

All other settings are common to the Nginx setup. We have allowed the virtual host to match with example.com, as well as www.example.com. We have set the index to search index.php, followed by index.html and others. With location directives, we have set Nginx to search for files and directories before forwarding the request to a PHP processor. Note that if you create a self-signed certificate, you will notice your browser complaining about invalid certification authority.

Getting ready

You will need access to a root account or an account with sudo privileges.

How to do it…

Follow these steps to set HTTPs on Nginx:

  1. Obtain a certificate and the related keys from a certification authority or create a self-signed certificate. To create a self-signed certificate, refer to the Securing web traffic with HTTPS recipe in this chapter.
  2. Create a directory to hold all certificate and keys:
    $ sudo mkdir -p /etc/nginx/ssl/example.com
    
  3. Move the certificate and keys to the preceding directory. Choose any secure method, such as SCP, SFTP, or any other.
  4. Create a virtual host entry or edit it if you already have one:
    $ sudo nano /etc/nginx/sites-available/example.com
    
  5. Match your virtual host configuration with the following:
    server {
      listen 80;
      server_name example.com www.example.com;
      return 301 https://$host$request_uri;
    }
    server {
      listen 443 ssl;
      server_name example.com www.example.com;
    
      
    root /var/www/example.com/public_html;
      index index.php index.html index.htm;
    
      ssl on;
      ssl_certificate     /etc/nginx/ssl/example.com/server.crt;
      ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
      # if you have received ca-certs.pem from Certification Authority
      #ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
    
      ssl_session_cache shared:SSL:10m;
      ssl_session_timeout 5m;
      keepalive_timeout   70;
    
      
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
      ssl_prefer_server_ciphers on;
      ssl_protocols  TLSv1.2 TLSv1.1 TLSv1;
      add_header Strict-Transport-Security "max-age=31536000";
    
      location / {
        try_files $uri $uri/ /index.php;
      }
    
      location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
      
    }
    }
    
  6. Enable this configuration by creating a symbolic link to it under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
    
  7. Check the configuration for syntax errors:
    $ sudo nginx -t
    
  8. Reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  9. Open your browser and access the site with domain or IP with HTTPS.

How it works…

When you know some basic configuration parameters, Nginx is quite simple to set up. Here, we have taken a few SSL settings from the default configuration file and added a simple redirection rule to redirect non-HTTPs traffic on port 80 to port 443. The first server block takes care of the redirection.

In addition to specifying the server certificate and keys, we have enabled session resumption by setting the cache to be shared across the Nginx process. We also have a timeout value of 5 minutes.

All other settings are common to the Nginx setup. We have allowed the virtual host to match with example.com, as well as www.example.com. We have set the index to search index.php, followed by index.html and others. With location directives, we have set Nginx to search for files and directories before forwarding the request to a PHP processor. Note that if you create a self-signed certificate, you will notice your browser complaining about invalid certification authority.

How to do it…

Follow these steps to set HTTPs on Nginx:

  1. Obtain a certificate and the related keys from a certification authority or create a self-signed certificate. To create a self-signed certificate, refer to the Securing web traffic with HTTPS recipe in this chapter.
  2. Create a directory to hold all certificate and keys:
    $ sudo mkdir -p /etc/nginx/ssl/example.com
    
  3. Move the certificate and keys to the preceding directory. Choose any secure method, such as SCP, SFTP, or any other.
  4. Create a virtual host entry or edit it if you already have one:
    $ sudo nano /etc/nginx/sites-available/example.com
    
  5. Match your virtual host configuration with the following:
    server {
      listen 80;
      server_name example.com www.example.com;
      return 301 https://$host$request_uri;
    }
    server {
      listen 443 ssl;
      server_name example.com www.example.com;
    
      
    root /var/www/example.com/public_html;
      index index.php index.html index.htm;
    
      ssl on;
      ssl_certificate     /etc/nginx/ssl/example.com/server.crt;
      ssl_certificate_key     /etc/nginx/ssl/example.com/server.key;
      # if you have received ca-certs.pem from Certification Authority
      #ssl_trusted_certificate /etc/nginx/ssl/example.com/ca-certs.pem;
    
      ssl_session_cache shared:SSL:10m;
      ssl_session_timeout 5m;
      keepalive_timeout   70;
    
      
    ssl_ciphers "HIGH:!aNULL:!MD5 or HIGH:!aNULL:!MD5:!3DES";
      ssl_prefer_server_ciphers on;
      ssl_protocols  TLSv1.2 TLSv1.1 TLSv1;
      add_header Strict-Transport-Security "max-age=31536000";
    
      location / {
        try_files $uri $uri/ /index.php;
      }
    
      location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
      
    }
    }
    
  6. Enable this configuration by creating a symbolic link to it under sites-enabled:
    $ sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
    
  7. Check the configuration for syntax errors:
    $ sudo nginx -t
    
  8. Reload Nginx for the changes to take effect:
    $ sudo service nginx reload
    
  9. Open your browser and access the site with domain or IP with HTTPS.

How it works…

When you know some basic configuration parameters, Nginx is quite simple to set up. Here, we have taken a few SSL settings from the default configuration file and added a simple redirection rule to redirect non-HTTPs traffic on port 80 to port 443. The first server block takes care of the redirection.

In addition to specifying the server certificate and keys, we have enabled session resumption by setting the cache to be shared across the Nginx process. We also have a timeout value of 5 minutes.

All other settings are common to the Nginx setup. We have allowed the virtual host to match with example.com, as well as www.example.com. We have set the index to search index.php, followed by index.html and others. With location directives, we have set Nginx to search for files and directories before forwarding the request to a PHP processor. Note that if you create a self-signed certificate, you will notice your browser complaining about invalid certification authority.

How it works…

When you know some basic configuration parameters, Nginx is quite simple to set up. Here, we have taken a few SSL settings from the default configuration file and added a simple redirection rule to redirect non-HTTPs traffic on port 80 to port 443. The first server block takes care of the redirection.

In addition to specifying the server certificate and keys, we have enabled session resumption by setting the cache to be shared across the Nginx process. We also have a timeout value of 5 minutes.

All other settings are common to the Nginx setup. We have allowed the virtual host to match with example.com, as well as www.example.com. We have set the index to search index.php, followed by index.html and others. With location directives, we have set Nginx to search for files and directories before forwarding the request to a PHP processor. Note that if you create a self-signed certificate, you will notice your browser complaining about invalid certification authority.

Benchmarking and performance tuning of Apache

In this recipe, we will learn some performance tuning configurations that may help to squeeze out the last bit of performance from the available hardware. Before diving into performance tuning, we need to evaluate our servers and set a benchmark which can be used to measure improvements after any changes. We will be using a well known HTTP benchmarking tool, Apache Bench (ab). Various other benchmarking tools are available and each one has its own feature set. You can choose the one that best suits your needs.

Getting ready

You will need two systems: one with the web server software installed and another to run Apache Bench. You will need root access or access to an account with similar privileges.

You will also need to modify a few network parameters to handle a large network load. You will also need to set a higher open files limit, in limits.conf, on both systems. Check the Tuning TCP Stack recipe in Chapter 2, Networking.

How to do it…

  1. Install the Apache Bench tool. This is available with the package apache2-utils:
    $ sudo apt-get install apache2-utils
    
  2. If you need to, you can check all the available options of the ab tool as follows:
    $ ab -h
    
  3. Now we are ready to generate network load. Execute the following command to start ab:
    $ ab -n 10000 -c 200 -t 2 -k "http://192.168.56.103/index.php"
    

    It will take some time to complete the command depending on the parameters. You should see similar results to the following (partial) output:

    How to do it…

Additionally, you may want to benchmark your server for CPU, memory, and IO performance. Check the Setting performance benchmarks recipe in Chapter 13, Performance Monitoring.

Now that we have a benchmark for server performance with stock installation, we can proceed with performance optimization. The following are some settings that are generally recommended for performance tuning:

  • Apache related settings:
    • Remove/disable any unused modules
    • Enable mod_gzip/mod_deflate
    • Turn HostnameLookups off
    • Use IP address in configuration files
    • Use persistence connection by enabling keepalive, then set keepalive timeout
    • Limit the uses of AllowOverride or completely disable it with AllowOverride none
    • Disable ExtendedStatus; this is useful while testing but not in production
  • Nginx related settings:
    • Set worker_processes to the count of your CPU cores or simply set it to auto
    • Set the number of worker_connections to test multiple values to find the best match for your servers
    • Set the keepalive_requests and keepalive_timeout values; these reduce the overhead of creating new connections
    • Enable idle connections with upstream servers by setting the keepalive value
    • Enable log buffering with buffer and flush parameters to access_log; this will reduce IO requests while logging
    • Reduce the log-level - you can set it to warn the user or display an error while in production
    • Set the sendfile directive to use an efficient sendfile() call from the operating system
    • Enable caching and compression
    • Make sure that you track the performance changes after each set of modifications; this way you will have exact knowledge regarding what worked and what not
    • You should also tune the TCP stack. The details of the TCP stack settings are covered in Chapter 2, Networking.

There's more…

Various other tools are available for benchmarking different features of the web server. The following are some well known tools, as well as a few latest additions:

See also

Getting ready

You will need two systems: one with the web server software installed and another to run Apache Bench. You will need root access or access to an account with similar privileges.

You will also need to modify a few network parameters to handle a large network load. You will also need to set a higher open files limit, in limits.conf, on both systems. Check the Tuning TCP Stack recipe in Chapter 2, Networking.

How to do it…

  1. Install the Apache Bench tool. This is available with the package apache2-utils:
    $ sudo apt-get install apache2-utils
    
  2. If you need to, you can check all the available options of the ab tool as follows:
    $ ab -h
    
  3. Now we are ready to generate network load. Execute the following command to start ab:
    $ ab -n 10000 -c 200 -t 2 -k "http://192.168.56.103/index.php"
    

    It will take some time to complete the command depending on the parameters. You should see similar results to the following (partial) output:

    How to do it…

Additionally, you may want to benchmark your server for CPU, memory, and IO performance. Check the Setting performance benchmarks recipe in Chapter 13, Performance Monitoring.

Now that we have a benchmark for server performance with stock installation, we can proceed with performance optimization. The following are some settings that are generally recommended for performance tuning:

  • Apache related settings:
    • Remove/disable any unused modules
    • Enable mod_gzip/mod_deflate
    • Turn HostnameLookups off
    • Use IP address in configuration files
    • Use persistence connection by enabling keepalive, then set keepalive timeout
    • Limit the uses of AllowOverride or completely disable it with AllowOverride none
    • Disable ExtendedStatus; this is useful while testing but not in production
  • Nginx related settings:
    • Set worker_processes to the count of your CPU cores or simply set it to auto
    • Set the number of worker_connections to test multiple values to find the best match for your servers
    • Set the keepalive_requests and keepalive_timeout values; these reduce the overhead of creating new connections
    • Enable idle connections with upstream servers by setting the keepalive value
    • Enable log buffering with buffer and flush parameters to access_log; this will reduce IO requests while logging
    • Reduce the log-level - you can set it to warn the user or display an error while in production
    • Set the sendfile directive to use an efficient sendfile() call from the operating system
    • Enable caching and compression
    • Make sure that you track the performance changes after each set of modifications; this way you will have exact knowledge regarding what worked and what not
    • You should also tune the TCP stack. The details of the TCP stack settings are covered in Chapter 2, Networking.

There's more…

Various other tools are available for benchmarking different features of the web server. The following are some well known tools, as well as a few latest additions:

See also

How to do it…

  1. Install the Apache Bench tool. This is available with the package apache2-utils:
    $ sudo apt-get install apache2-utils
    
  2. If you need to, you can check all the available options of the ab tool as follows:
    $ ab -h
    
  3. Now we are ready to generate network load. Execute the following command to start ab:
    $ ab -n 10000 -c 200 -t 2 -k "http://192.168.56.103/index.php"
    

    It will take some time to complete the command depending on the parameters. You should see similar results to the following (partial) output:

    How to do it…

Additionally, you may want to benchmark your server for CPU, memory, and IO performance. Check the Setting performance benchmarks recipe in Chapter 13, Performance Monitoring.

Now that we have a benchmark for server performance with stock installation, we can proceed with performance optimization. The following are some settings that are generally recommended for performance tuning:

  • Apache related settings:
    • Remove/disable any unused modules
    • Enable mod_gzip/mod_deflate
    • Turn HostnameLookups off
    • Use IP address in configuration files
    • Use persistence connection by enabling keepalive, then set keepalive timeout
    • Limit the uses of AllowOverride or completely disable it with AllowOverride none
    • Disable ExtendedStatus; this is useful while testing but not in production
  • Nginx related settings:
    • Set worker_processes to the count of your CPU cores or simply set it to auto
    • Set the number of worker_connections to test multiple values to find the best match for your servers
    • Set the keepalive_requests and keepalive_timeout values; these reduce the overhead of creating new connections
    • Enable idle connections with upstream servers by setting the keepalive value
    • Enable log buffering with buffer and flush parameters to access_log; this will reduce IO requests while logging
    • Reduce the log-level - you can set it to warn the user or display an error while in production
    • Set the sendfile directive to use an efficient sendfile() call from the operating system
    • Enable caching and compression
    • Make sure that you track the performance changes after each set of modifications; this way you will have exact knowledge regarding what worked and what not
    • You should also tune the TCP stack. The details of the TCP stack settings are covered in Chapter 2, Networking.

There's more…

Various other tools are available for benchmarking different features of the web server. The following are some well known tools, as well as a few latest additions:

See also

There's more…

Various other tools are available for benchmarking different features of the web server. The following are some well known tools, as well as a few latest additions:

See also

See also

Securing the web server

In this recipe, we will learn some steps for securing web server installation.

Getting ready

You will need access to a root account or an account with sudo privileges.

You may need to have a web server stack installed and running.

How to do it…

Follow these steps to secure the web server:

  1. Disable any unwanted modules. You can check all enabled modules with the following command:
    $ a2query -m
    
  2. Disable modules with the following command:
    $ sudo a2dismod status
    
  3. Hide the web server's identity. For Apache, edit /etc/apache2/conf-available/security.conf and set the following values:
    ServerSignature Off
    ServerTokens Prod
    
  4. You may want to check other options under security.conf.
  5. Next, disable the Apache server status page:
    $ sudo a2dismod status
    
  6. For Nginx, edit /etc/nginx/nginx.conf and uncomment the following line:
    # server_tokens off;
    
  7. In production environments, minimize the detail shown on error pages. You can enable the PHP Suhosin module and strict mode.
  8. Disable directory listing. On Apache, add the following line to the virtual host configuration:
    <Directory /var/www/example.com>
      Options -Indexes
    </Directory>
    
  9. You can also disable directory listing globally by setting Options -Indexes in /etc/apache2/apache2.conf.
  10. Restrict access to the following directories:
    <Directory /var/www/ >
      Order deny,allow   # order of Deny and Allow
      Deny from all   # Deny web root for all
    </Directory>
    
  11. Disable directory level settings and the use of .htaccess. This also helps improve performance:
    <Directory />
      AllowOverride None   # disable use of .htaccess
    </Directory>
    
  12. Disable the following symbolic links:
    <Directory />
      Options -FollowSymLinks
    </Directory>
    
  13. You can also install mod_security and mod_evasive for added security. mod_security acts as a firewall by monitoring traffic in real time, whereas mod_evasive provides protection against Denial of Service attacks by monitoring request data and requester IP.
  14. For Apache, you can install mod_security as a plugin module as follows:
    $ sudo apt-get install libapache2-modsecurity
    $ sudo a2enmod mod-security
    
  15. On Nginx, you need to first compile mod_security and then compile Nginx with mod_security enabled.
  16. Turn of server side includes and CGI scripts:
    <Directory />
      Options -ExecCGI -Includes
    </Directory>
    
  17. Limit request body, headers, request fields, and max concurrent connections; this will help against DOS attacks.
  18. Set the following variables on Apache:
    TimeOut
    KeepAliveTimeout
    RequestReadTimeout
    LimitRequestBody
    LimitRequestFields
    LimitRequestFieldSize
    LimitRequestLine
    MaxRequestWorkers
    
  19. For Nginx, configure the following variables to control buffer overflow attacks:
    client_body_buffer_size
    client_header_buffer_size
    client_max_body_size
    large_client_header_buffers
    
  20. Enable logging and periodically monitor logs for any new or unrecognized events:
    <VirtualHost *:80>
      
    ErrorLog /var/log/httpd/example.com/error_log
      CustomLog /var/log/httpd/example.com/access_log combined
    </VirtualHost>
    
  21. Set up HTTPs and set it to use modern ciphers. You can also disable the use of SSL and enforce TLS.

How it works…

In this recipe, I have listed the various options available to make your web server more secure. It is not necessary to set all these settings. Disabling some of these settings, especially FollowSymlinks and AllowOverride, may not suit your requirements or your environment. You can always choose the settings that apply to your setup.

Various settings listed here are available in their respective configuration files, mostly under /etc/apache2 for the Apache web server and /etc/nginx for the Nginx server.

Also, do not forget to reload or restart your server after setting these options.

You should also set your Ubuntu environment to be more secure. You can find more details on securing Ubuntu in Chapter 2, Networking.

Getting ready

You will need access to a root account or an account with sudo privileges.

You may need to have a web server stack installed and running.

How to do it…

Follow these steps to secure the web server:

  1. Disable any unwanted modules. You can check all enabled modules with the following command:
    $ a2query -m
    
  2. Disable modules with the following command:
    $ sudo a2dismod status
    
  3. Hide the web server's identity. For Apache, edit /etc/apache2/conf-available/security.conf and set the following values:
    ServerSignature Off
    ServerTokens Prod
    
  4. You may want to check other options under security.conf.
  5. Next, disable the Apache server status page:
    $ sudo a2dismod status
    
  6. For Nginx, edit /etc/nginx/nginx.conf and uncomment the following line:
    # server_tokens off;
    
  7. In production environments, minimize the detail shown on error pages. You can enable the PHP Suhosin module and strict mode.
  8. Disable directory listing. On Apache, add the following line to the virtual host configuration:
    <Directory /var/www/example.com>
      Options -Indexes
    </Directory>
    
  9. You can also disable directory listing globally by setting Options -Indexes in /etc/apache2/apache2.conf.
  10. Restrict access to the following directories:
    <Directory /var/www/ >
      Order deny,allow   # order of Deny and Allow
      Deny from all   # Deny web root for all
    </Directory>
    
  11. Disable directory level settings and the use of .htaccess. This also helps improve performance:
    <Directory />
      AllowOverride None   # disable use of .htaccess
    </Directory>
    
  12. Disable the following symbolic links:
    <Directory />
      Options -FollowSymLinks
    </Directory>
    
  13. You can also install mod_security and mod_evasive for added security. mod_security acts as a firewall by monitoring traffic in real time, whereas mod_evasive provides protection against Denial of Service attacks by monitoring request data and requester IP.
  14. For Apache, you can install mod_security as a plugin module as follows:
    $ sudo apt-get install libapache2-modsecurity
    $ sudo a2enmod mod-security
    
  15. On Nginx, you need to first compile mod_security and then compile Nginx with mod_security enabled.
  16. Turn of server side includes and CGI scripts:
    <Directory />
      Options -ExecCGI -Includes
    </Directory>
    
  17. Limit request body, headers, request fields, and max concurrent connections; this will help against DOS attacks.
  18. Set the following variables on Apache:
    TimeOut
    KeepAliveTimeout
    RequestReadTimeout
    LimitRequestBody
    LimitRequestFields
    LimitRequestFieldSize
    LimitRequestLine
    MaxRequestWorkers
    
  19. For Nginx, configure the following variables to control buffer overflow attacks:
    client_body_buffer_size
    client_header_buffer_size
    client_max_body_size
    large_client_header_buffers
    
  20. Enable logging and periodically monitor logs for any new or unrecognized events:
    <VirtualHost *:80>
      
    ErrorLog /var/log/httpd/example.com/error_log
      CustomLog /var/log/httpd/example.com/access_log combined
    </VirtualHost>
    
  21. Set up HTTPs and set it to use modern ciphers. You can also disable the use of SSL and enforce TLS.

How it works…

In this recipe, I have listed the various options available to make your web server more secure. It is not necessary to set all these settings. Disabling some of these settings, especially FollowSymlinks and AllowOverride, may not suit your requirements or your environment. You can always choose the settings that apply to your setup.

Various settings listed here are available in their respective configuration files, mostly under /etc/apache2 for the Apache web server and /etc/nginx for the Nginx server.

Also, do not forget to reload or restart your server after setting these options.

You should also set your Ubuntu environment to be more secure. You can find more details on securing Ubuntu in Chapter 2, Networking.

How to do it…

Follow these steps to secure the web server:

  1. Disable any unwanted modules. You can check all enabled modules with the following command:
    $ a2query -m
    
  2. Disable modules with the following command:
    $ sudo a2dismod status
    
  3. Hide the web server's identity. For Apache, edit /etc/apache2/conf-available/security.conf and set the following values:
    ServerSignature Off
    ServerTokens Prod
    
  4. You may want to check other options under security.conf.
  5. Next, disable the Apache server status page:
    $ sudo a2dismod status
    
  6. For Nginx, edit /etc/nginx/nginx.conf and uncomment the following line:
    # server_tokens off;
    
  7. In production environments, minimize the detail shown on error pages. You can enable the PHP Suhosin module and strict mode.
  8. Disable directory listing. On Apache, add the following line to the virtual host configuration:
    <Directory /var/www/example.com>
      Options -Indexes
    </Directory>
    
  9. You can also disable directory listing globally by setting Options -Indexes in /etc/apache2/apache2.conf.
  10. Restrict access to the following directories:
    <Directory /var/www/ >
      Order deny,allow   # order of Deny and Allow
      Deny from all   # Deny web root for all
    </Directory>
    
  11. Disable directory level settings and the use of .htaccess. This also helps improve performance:
    <Directory />
      AllowOverride None   # disable use of .htaccess
    </Directory>
    
  12. Disable the following symbolic links:
    <Directory />
      Options -FollowSymLinks
    </Directory>
    
  13. You can also install mod_security and mod_evasive for added security. mod_security acts as a firewall by monitoring traffic in real time, whereas mod_evasive provides protection against Denial of Service attacks by monitoring request data and requester IP.
  14. For Apache, you can install mod_security as a plugin module as follows:
    $ sudo apt-get install libapache2-modsecurity
    $ sudo a2enmod mod-security
    
  15. On Nginx, you need to first compile mod_security and then compile Nginx with mod_security enabled.
  16. Turn of server side includes and CGI scripts:
    <Directory />
      Options -ExecCGI -Includes
    </Directory>
    
  17. Limit request body, headers, request fields, and max concurrent connections; this will help against DOS attacks.
  18. Set the following variables on Apache:
    TimeOut
    KeepAliveTimeout
    RequestReadTimeout
    LimitRequestBody
    LimitRequestFields
    LimitRequestFieldSize
    LimitRequestLine
    MaxRequestWorkers
    
  19. For Nginx, configure the following variables to control buffer overflow attacks:
    client_body_buffer_size
    client_header_buffer_size
    client_max_body_size
    large_client_header_buffers
    
  20. Enable logging and periodically monitor logs for any new or unrecognized events:
    <VirtualHost *:80>
      
    ErrorLog /var/log/httpd/example.com/error_log
      CustomLog /var/log/httpd/example.com/access_log combined
    </VirtualHost>
    
  21. Set up HTTPs and set it to use modern ciphers. You can also disable the use of SSL and enforce TLS.

How it works…

In this recipe, I have listed the various options available to make your web server more secure. It is not necessary to set all these settings. Disabling some of these settings, especially FollowSymlinks and AllowOverride, may not suit your requirements or your environment. You can always choose the settings that apply to your setup.

Various settings listed here are available in their respective configuration files, mostly under /etc/apache2 for the Apache web server and /etc/nginx for the Nginx server.

Also, do not forget to reload or restart your server after setting these options.

You should also set your Ubuntu environment to be more secure. You can find more details on securing Ubuntu in Chapter 2, Networking.

How it works…

In this recipe, I have listed the various options available to make your web server more secure. It is not necessary to set all these settings. Disabling some of these settings, especially FollowSymlinks and AllowOverride, may not suit your requirements or your environment. You can always choose the settings that apply to your setup.

Various settings listed here are available in their respective configuration files, mostly under /etc/apache2 for the Apache web server and /etc/nginx for the Nginx server.

Also, do not forget to reload or restart your server after setting these options.

You should also set your Ubuntu environment to be more secure. You can find more details on securing Ubuntu in Chapter 2, Networking.

Troubleshooting the web server

In this recipe, we will cover some common issues with Apache and Nginx and list the basic steps for overcoming those issues. The steps mentioned here are general troubleshooting methods; you may need to change them based on your setup and environment.

Getting ready

You may need root level access to your web server system.

How to do it…

Web server problems can be grouped in a few broad categories, such as a server not working, a particular domain or virtual host is not accessible, problems with a specific module configuration, and access denied errors. The following section lists each of these problems and their possible solutions.

Web server not accessible

  1. The first step is to check your local Internet connection. Try to access the server from another system from another network.
  2. Check if the DNS settings point to your web server.
  3. If your network is working properly, then try to ping to the server IP address.
  4. On the web server, check the firewall or any other tool that may block communication.
  5. Open a telnet connection to web server on port 80, or whatever port you have used for web server. If you see output similar to following screenshot, then your web server is working:
    Web server not accessible
  6. Make sure that the web server port is not being used by some other process:
    $ sudo netstat -plutn
    
    Web server not accessible
  7. If required, reload or restart the web server process:
    $ sudo service apache2 reload/restart
    
  8. Check the Apache/Nginx logs listed under the /var/log/ directory and view the entire file in a scrollable format:
    $ less /var/log/apache2/error.log
    
  9. See the continuous stream of logs as they are added to the log file:
    $ tail -f /var/log/nginx/error.log
    
  10. You may want to run Apache with extended log levels. Find the variable LogLevel in /etc/apache2/apache2.conf and set its value to debug:
    $ sudo nano /etc/apache2/apache2.conf
    LogLevel debug
    
  11. Run Apache in debug single process mode:
    $ sudo apache2ctl -X  # debug mode single worker
    

Virtual host not accessible

  1. Make sure you have enabled virtual host configuration:
    ubuntu@ubuntu:~$ a2query -s
    example.com (enabled by site administrator)
    
  2. Check the virtual host configuration for any syntax errors:
    ubuntu@ubuntu:~$ sudo apache2ctl -t
    Syntax OK
    
  3. On Nginx, use the following command:
    ubuntu@ubuntu:~$ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
  4. Check the virtual host's details and other Apache configurations:
    $ sudo apache2ctl -S
    
    Virtual host not accessible
  5. Make sure your virtual host IP and port configuration matches the one defined with NamedVirtualHost.
  6. Check DocumentRoot - does it point to proper files?
    • On Apache:
      <VirtualHost *:80>
          DocumentRoot /var/www/html
      <VirtualHost>
      
    • On Nginx:
      server {
          root /usr/share/nginx/html;
      }
      
  7. Crosscheck your ServerName and ServerAlias variables - do they match your domain name?
    • On Apache, these settings should look similar to this:
      <VirtualHost *:80>
          ServerName example.com
          ServerAlias www.example.com
      </virtualHost>
      
    • On Nginx, the ServerName is defined as this:
      server {
          server_name example.com www.example.com;
      }
      

Access denied or forbidden errors

Check directory permissions for the virtual host root directory. Are they accessible to the web server? Check the web server user and group (commonly www-data) have ready permissions. If required, you can set permissions with chown and chmod commands.

ubuntu@ubuntu:~$ ls -l /var/www/
drwxr-x--- 3 ubuntu www-data 4096 Aug  4 23:00 example.com
drwxr-xr-x 2 ubuntu www-data 4096 Aug  2 23:04 public_html

Secondly, make sure that you have properly set directory permissions in the virtual host configuration. Are they restricting file access?

Use the following commands to set directory permissions in the virtual host configuration:

<Directory /var/www/>
    AllowOverride None
    Order Deny,Allow
    Deny from all
</Directory>

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)

Getting ready

You may need root level access to your web server system.

How to do it…

Web server problems can be grouped in a few broad categories, such as a server not working, a particular domain or virtual host is not accessible, problems with a specific module configuration, and access denied errors. The following section lists each of these problems and their possible solutions.

Web server not accessible

  1. The first step is to check your local Internet connection. Try to access the server from another system from another network.
  2. Check if the DNS settings point to your web server.
  3. If your network is working properly, then try to ping to the server IP address.
  4. On the web server, check the firewall or any other tool that may block communication.
  5. Open a telnet connection to web server on port 80, or whatever port you have used for web server. If you see output similar to following screenshot, then your web server is working:
    Web server not accessible
  6. Make sure that the web server port is not being used by some other process:
    $ sudo netstat -plutn
    
    Web server not accessible
  7. If required, reload or restart the web server process:
    $ sudo service apache2 reload/restart
    
  8. Check the Apache/Nginx logs listed under the /var/log/ directory and view the entire file in a scrollable format:
    $ less /var/log/apache2/error.log
    
  9. See the continuous stream of logs as they are added to the log file:
    $ tail -f /var/log/nginx/error.log
    
  10. You may want to run Apache with extended log levels. Find the variable LogLevel in /etc/apache2/apache2.conf and set its value to debug:
    $ sudo nano /etc/apache2/apache2.conf
    LogLevel debug
    
  11. Run Apache in debug single process mode:
    $ sudo apache2ctl -X  # debug mode single worker
    

Virtual host not accessible

  1. Make sure you have enabled virtual host configuration:
    ubuntu@ubuntu:~$ a2query -s
    example.com (enabled by site administrator)
    
  2. Check the virtual host configuration for any syntax errors:
    ubuntu@ubuntu:~$ sudo apache2ctl -t
    Syntax OK
    
  3. On Nginx, use the following command:
    ubuntu@ubuntu:~$ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
  4. Check the virtual host's details and other Apache configurations:
    $ sudo apache2ctl -S
    
    Virtual host not accessible
  5. Make sure your virtual host IP and port configuration matches the one defined with NamedVirtualHost.
  6. Check DocumentRoot - does it point to proper files?
    • On Apache:
      <VirtualHost *:80>
          DocumentRoot /var/www/html
      <VirtualHost>
      
    • On Nginx:
      server {
          root /usr/share/nginx/html;
      }
      
  7. Crosscheck your ServerName and ServerAlias variables - do they match your domain name?
    • On Apache, these settings should look similar to this:
      <VirtualHost *:80>
          ServerName example.com
          ServerAlias www.example.com
      </virtualHost>
      
    • On Nginx, the ServerName is defined as this:
      server {
          server_name example.com www.example.com;
      }
      

Access denied or forbidden errors

Check directory permissions for the virtual host root directory. Are they accessible to the web server? Check the web server user and group (commonly www-data) have ready permissions. If required, you can set permissions with chown and chmod commands.

ubuntu@ubuntu:~$ ls -l /var/www/
drwxr-x--- 3 ubuntu www-data 4096 Aug  4 23:00 example.com
drwxr-xr-x 2 ubuntu www-data 4096 Aug  2 23:04 public_html

Secondly, make sure that you have properly set directory permissions in the virtual host configuration. Are they restricting file access?

Use the following commands to set directory permissions in the virtual host configuration:

<Directory /var/www/>
    AllowOverride None
    Order Deny,Allow
    Deny from all
</Directory>

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)

How to do it…

Web server problems can be grouped in a few broad categories, such as a server not working, a particular domain or virtual host is not accessible, problems with a specific module configuration, and access denied errors. The following section lists each of these problems and their possible solutions.

Web server not accessible

  1. The first step is to check your local Internet connection. Try to access the server from another system from another network.
  2. Check if the DNS settings point to your web server.
  3. If your network is working properly, then try to ping to the server IP address.
  4. On the web server, check the firewall or any other tool that may block communication.
  5. Open a telnet connection to web server on port 80, or whatever port you have used for web server. If you see output similar to following screenshot, then your web server is working:
    Web server not accessible
  6. Make sure that the web server port is not being used by some other process:
    $ sudo netstat -plutn
    
    Web server not accessible
  7. If required, reload or restart the web server process:
    $ sudo service apache2 reload/restart
    
  8. Check the Apache/Nginx logs listed under the /var/log/ directory and view the entire file in a scrollable format:
    $ less /var/log/apache2/error.log
    
  9. See the continuous stream of logs as they are added to the log file:
    $ tail -f /var/log/nginx/error.log
    
  10. You may want to run Apache with extended log levels. Find the variable LogLevel in /etc/apache2/apache2.conf and set its value to debug:
    $ sudo nano /etc/apache2/apache2.conf
    LogLevel debug
    
  11. Run Apache in debug single process mode:
    $ sudo apache2ctl -X  # debug mode single worker
    

Virtual host not accessible

  1. Make sure you have enabled virtual host configuration:
    ubuntu@ubuntu:~$ a2query -s
    example.com (enabled by site administrator)
    
  2. Check the virtual host configuration for any syntax errors:
    ubuntu@ubuntu:~$ sudo apache2ctl -t
    Syntax OK
    
  3. On Nginx, use the following command:
    ubuntu@ubuntu:~$ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
  4. Check the virtual host's details and other Apache configurations:
    $ sudo apache2ctl -S
    
    Virtual host not accessible
  5. Make sure your virtual host IP and port configuration matches the one defined with NamedVirtualHost.
  6. Check DocumentRoot - does it point to proper files?
    • On Apache:
      <VirtualHost *:80>
          DocumentRoot /var/www/html
      <VirtualHost>
      
    • On Nginx:
      server {
          root /usr/share/nginx/html;
      }
      
  7. Crosscheck your ServerName and ServerAlias variables - do they match your domain name?
    • On Apache, these settings should look similar to this:
      <VirtualHost *:80>
          ServerName example.com
          ServerAlias www.example.com
      </virtualHost>
      
    • On Nginx, the ServerName is defined as this:
      server {
          server_name example.com www.example.com;
      }
      

Access denied or forbidden errors

Check directory permissions for the virtual host root directory. Are they accessible to the web server? Check the web server user and group (commonly www-data) have ready permissions. If required, you can set permissions with chown and chmod commands.

ubuntu@ubuntu:~$ ls -l /var/www/
drwxr-x--- 3 ubuntu www-data 4096 Aug  4 23:00 example.com
drwxr-xr-x 2 ubuntu www-data 4096 Aug  2 23:04 public_html

Secondly, make sure that you have properly set directory permissions in the virtual host configuration. Are they restricting file access?

Use the following commands to set directory permissions in the virtual host configuration:

<Directory /var/www/>
    AllowOverride None
    Order Deny,Allow
    Deny from all
</Directory>

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)

Web server not accessible

  1. The first step is to check your local Internet connection. Try to access the server from another system from another network.
  2. Check if the DNS settings point to your web server.
  3. If your network is working properly, then try to ping to the server IP address.
  4. On the web server, check the firewall or any other tool that may block communication.
  5. Open a telnet connection to web server on port 80, or whatever port you have used for web server. If you see output similar to following screenshot, then your web server is working:
    Web server not accessible
  6. Make sure that the web server port is not being used by some other process:
    $ sudo netstat -plutn
    
    Web server not accessible
  7. If required, reload or restart the web server process:
    $ sudo service apache2 reload/restart
    
  8. Check the Apache/Nginx logs listed under the /var/log/ directory and view the entire file in a scrollable format:
    $ less /var/log/apache2/error.log
    
  9. See the continuous stream of logs as they are added to the log file:
    $ tail -f /var/log/nginx/error.log
    
  10. You may want to run Apache with extended log levels. Find the variable LogLevel in /etc/apache2/apache2.conf and set its value to debug:
    $ sudo nano /etc/apache2/apache2.conf
    LogLevel debug
    
  11. Run Apache in debug single process mode:
    $ sudo apache2ctl -X  # debug mode single worker
    

Virtual host not accessible

  1. Make sure you have enabled virtual host configuration:
    ubuntu@ubuntu:~$ a2query -s
    example.com (enabled by site administrator)
    
  2. Check the virtual host configuration for any syntax errors:
    ubuntu@ubuntu:~$ sudo apache2ctl -t
    Syntax OK
    
  3. On Nginx, use the following command:
    ubuntu@ubuntu:~$ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
  4. Check the virtual host's details and other Apache configurations:
    $ sudo apache2ctl -S
    
    Virtual host not accessible
  5. Make sure your virtual host IP and port configuration matches the one defined with NamedVirtualHost.
  6. Check DocumentRoot - does it point to proper files?
    • On Apache:
      <VirtualHost *:80>
          DocumentRoot /var/www/html
      <VirtualHost>
      
    • On Nginx:
      server {
          root /usr/share/nginx/html;
      }
      
  7. Crosscheck your ServerName and ServerAlias variables - do they match your domain name?
    • On Apache, these settings should look similar to this:
      <VirtualHost *:80>
          ServerName example.com
          ServerAlias www.example.com
      </virtualHost>
      
    • On Nginx, the ServerName is defined as this:
      server {
          server_name example.com www.example.com;
      }
      

Access denied or forbidden errors

Check directory permissions for the virtual host root directory. Are they accessible to the web server? Check the web server user and group (commonly www-data) have ready permissions. If required, you can set permissions with chown and chmod commands.

ubuntu@ubuntu:~$ ls -l /var/www/
drwxr-x--- 3 ubuntu www-data 4096 Aug  4 23:00 example.com
drwxr-xr-x 2 ubuntu www-data 4096 Aug  2 23:04 public_html

Secondly, make sure that you have properly set directory permissions in the virtual host configuration. Are they restricting file access?

Use the following commands to set directory permissions in the virtual host configuration:

<Directory /var/www/>
    AllowOverride None
    Order Deny,Allow
    Deny from all
</Directory>

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)

Virtual host not accessible

  1. Make sure you have enabled virtual host configuration:
    ubuntu@ubuntu:~$ a2query -s
    example.com (enabled by site administrator)
    
  2. Check the virtual host configuration for any syntax errors:
    ubuntu@ubuntu:~$ sudo apache2ctl -t
    Syntax OK
    
  3. On Nginx, use the following command:
    ubuntu@ubuntu:~$ sudo nginx -t
    nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    nginx: configuration file /etc/nginx/nginx.conf test is successful
    
  4. Check the virtual host's details and other Apache configurations:
    $ sudo apache2ctl -S
    
    Virtual host not accessible
  5. Make sure your virtual host IP and port configuration matches the one defined with NamedVirtualHost.
  6. Check DocumentRoot - does it point to proper files?
    • On Apache:
      <VirtualHost *:80>
          DocumentRoot /var/www/html
      <VirtualHost>
      
    • On Nginx:
      server {
          root /usr/share/nginx/html;
      }
      
  7. Crosscheck your ServerName and ServerAlias variables - do they match your domain name?
    • On Apache, these settings should look similar to this:
      <VirtualHost *:80>
          ServerName example.com
          ServerAlias www.example.com
      </virtualHost>
      
    • On Nginx, the ServerName is defined as this:
      server {
          server_name example.com www.example.com;
      }
      

Access denied or forbidden errors

Check directory permissions for the virtual host root directory. Are they accessible to the web server? Check the web server user and group (commonly www-data) have ready permissions. If required, you can set permissions with chown and chmod commands.

ubuntu@ubuntu:~$ ls -l /var/www/
drwxr-x--- 3 ubuntu www-data 4096 Aug  4 23:00 example.com
drwxr-xr-x 2 ubuntu www-data 4096 Aug  2 23:04 public_html

Secondly, make sure that you have properly set directory permissions in the virtual host configuration. Are they restricting file access?

Use the following commands to set directory permissions in the virtual host configuration:

<Directory /var/www/>
    AllowOverride None
    Order Deny,Allow
    Deny from all
</Directory>

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)

Access denied or forbidden errors

Check directory permissions for the virtual host root directory. Are they accessible to the web server? Check the web server user and group (commonly www-data) have ready permissions. If required, you can set permissions with chown and chmod commands.

ubuntu@ubuntu:~$ ls -l /var/www/
drwxr-x--- 3 ubuntu www-data 4096 Aug  4 23:00 example.com
drwxr-xr-x 2 ubuntu www-data 4096 Aug  2 23:04 public_html

Secondly, make sure that you have properly set directory permissions in the virtual host configuration. Are they restricting file access?

Use the following commands to set directory permissions in the virtual host configuration:

<Directory /var/www/>
    AllowOverride None
    Order Deny,Allow
    Deny from all
</Directory>

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)

Apache downloads .php files

Make sure that the mod_php module is installed and enabled:

ubuntu@ubuntu:~$ ls -l /etc/apache2/mods-available | grep php
-rw-r--r-- 1 root root  897 Jul  2 21:26 php7.0.conf
-rw-r--r-- 1 root root   59 Jul  2 21:26 php7.0.load

ubuntu@ubuntu:~$ a2query -m | grep php
php7.0 (enabled by maintainer script)
You have been reading a chapter from
Linux: Powerful Server Administration
Published in: Apr 2017
Publisher: Packt
ISBN-13: 9781788293778
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image