Nginx Web Server Management - Ubuntu as a Server - Ubuntu Unleashed 2017 Edition (2017)

Ubuntu Unleashed 2017 Edition (2017)

Part IV: Ubuntu as a Server

Chapter 25. Nginx Web Server Management


In This Chapter

Image About the Nginx Web Server

Image Installing the Nginx Server

Image Configuring the Nginx Server

Image Virtual Hosting

Image Setting Up PHP

Image Adding and Configuring Modules

Image HTTPS

Image References


This chapter covers the configuration and management of the Nginx web server and includes an overview of some of the major components of the server and discussions of server configuration. In this chapter, you learn how to start, stop, and restart Nginx using the command line. The chapter begins with some introductory information and then shows you how to install, configure, and use Nginx.

About the Nginx Web Server

Pronounced “engine-x,” this is a lightweight and extremely fast web server. It is free and open source. Some well-known websites such as GitHub, Netflix, and WordPress.com use Nginx because it is stable and fast under high-traffic conditions while using fewer resources. It is not as configurable as Apache, but for specific use cases it is an excellent option and is quite easy to set up and use.


News

The W3Techs website, which tracks trends on the web, posted an article in July 2013 titled “Nginx just became the most used web server among the top 1000 websites.” They summarized the article this way: “34.9% of the top 1000 web sites rely on Nginx. That makes it the most trusted web server on high traffic sites, just ahead of Apache.”

Source: http://w3techs.com/blog/entry/nginx_just_became_the_most_used_web_server_among_the_top_1000_websites


The original design of Nginx was created to allow higher numbers of concurrent website requests. Larger websites often have tens of thousands of clients connected simultaneously, each one making HTTP requests that must be responded to. The designers of Nginx heard this problem described as C10K and decided they could write a web server that would be capable of serving at least 10,000 clients simultaneously.


The c10k problem

The canonical website for learning more about this problem is www.kegel.com/c10k.html. The article linked here is from the early 2000s and describes ideas for configuring operating systems and writing code to solve the problem of serving at least 10,000 simultaneous clients from a web server. Today, this problem is even more common, and with the continuing maturity of Nginx, lighttpd, and other web servers, many of the largest, highest traffic sites have switched away from Apache.


Newer versions of the Apache and other modern web servers rely on a concept of threads. Threads are kind of like lightweight processes. This deserves some explanation. A process is a specific instance of a computer program running. The process contains both the machine code (the binary, or the compiled version of the program that the computer processor can understand and obey—this is either precompiled as in C or C++ programs or may be the output of a just-in-time compilation as happens with languages like Python or Perl) as well as the current activity of that program, such as the calculations it is performing or the data it stores in memory on which it is operating. Serving an HTTP page by running a complete process each time would be bad because the server’s resources would be quickly used up if the site was even moderately popular. Process after process would be started and would fight for attention. A thread is the ordered control of a program: First, do this; then, do that; finally, do this other thing. One process may control many threads. This is good for resource management. By using threads instead of processes, a larger number of client requests can be served using less system resources than a process-based server.

Most web servers have traditionally been either process based or thread based. There are also examples of hybrid models, where many multithread processes are used. Process-based servers are great because they are stable and the crash of one process does not affect other processes. However, they cannot handle as many clients because the creation and destruction of all of those processes creates a lot of processor overhead and requires a large amount of memory. Thread-based servers are great because requests can share memory, making them more efficient and thereby able to serve more requests more quickly. However, a crash in one thread could bring the entire server down.

What makes Nginx different is that it uses an event-driven architecture to handle requests. Instead of starting a new process or a new thread for each request, in an event-driven architecture, the flow of the program is controlled by events, some form of message sent from another process or thread. Here, you have a process that runs as a “listener” or “event detector” that waits for a request to come in to the server. When the request arrives, instead of a new process starting, the “listener” sends a message to a different part of the server called an “event handler,” which then performs a task. The simplified outcome of serving web pages this way is that less processor time and less memory are needed. There are some significant difficulties inherent in using this method, not the least of which can be greater code complexity, which can make fixing bugs, adding features, and understanding code as a newcomer (or even a returning veteran of the same codebase, but who has been away from it for a little while) more difficult.

Nginx is designed to scale well from one small, low-powered server up to large networks involving many servers.

For configuration, Nginx uses a system of virtual hosts, similar to Apache, using a similar set of configuration files. The differences are semantic and not terribly difficult. You can create URL rewrites in Nginx using a rather different syntax. In addition, there is nothing similar to Apache’s rewrite conditions. Occasional blog posts and web tutorials exist to give some workarounds that will handle some of the more common forms, but if this is something you do often, you might not want to use Nginx.

One missing file that many people use and love in Apache is .htaccess. There is nothing similar in Nginx, so if you need the ability to make changes to rewrites or configurations without restarting the server, you are out of luck. This is probably the primary reason that you don’t see shared hosting offering Nginx.

Finally, another well-documented option is to use both Apache and Nginx together, where Apache handles any and all dynamic requests and Nginx handles all static requests. This is faster and lighter than using Apache alone but comes with the burden of added complexity and the increased potential for problems that brings.

Installing the Nginx Server

You can install Nginx through APT or build it yourself from source code. The Nginx source builds on just about any UNIX-like operating system and on Win32.

If you are about to install a new version of Nginx, shut down the old server. Even if it’s unlikely that the old server will interfere with the installation procedure, shutting it down ensures that there will be no problems. If you do not know how to stop Nginx, see the “Starting and Stopping Nginx” section later in this chapter.

Installing from the Ubuntu Repositories

You can install the nginx package from the Ubuntu software repositories. Updated packages usually contain important bug and security fixes. When an updated version is released, install it as quickly as possible to keep your system secure.

For more information about installing software from the Ubuntu repositories, see Chapter 9, “Managing Software.”

Building the Source Yourself

You can download the source directly from http://wiki.nginx.org/Install.

After you have the tar file, you must open it in a temporary directory, such as /tmp. Opening this tar file creates a directory called nginx_version_number, where version_number is the version you have downloaded (for example, nginx_1.4.4).


Tip

As with many software packages distributed in source code form for Linux and other UNIX-like operating systems, extracting the source code results in a directory that contains a README and an INSTALL file. Be sure to peruse the INSTALL file before attempting to build and install the software.


Using ./configure to Build Nginx

To build Nginx, run the ./configure script in the directory just created. Use this command:

matthew@seymour:~$ ./configure

This generates the makefile that is used to compile the server code.

Next, run make to compile the server code.

matthew@seymour:~$ make

After the compilation is complete, install the server. This may only be done using admin privileges.

Click here to view code image

matthew@seymour:~$ sudo make install


Tip

It is strongly recommended that you use Ubuntu’s version of Nginx until you really know what happens at system startup. No “uninstall” option is available when installing Nginx from source! For the remainder of this chapter, we assume you have installed Nginx this way. If you install from source, you should check the Nginx documentation as there may be differences from what we describe here.


Configuring the Nginx Server

You can now configure the server. Nginx is most commonly run using Virtual Hosts, like what most people do with Apache these days. The process is similar, with mainly syntax differences.

If you install using the package manager, all configuration files for Nginx are located in /etc/nginx. The primary configuration file is /etc/nginx/nginx.conf. Here is an example of that file:

Click here to view code image

user www-data;
worker_processes 1;

# error_log /var/log/nginx/error.log;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

access_log /var/log/nginx/access.log;

sendfile on;

tcp_nopush on;
#tcp_nodelay on;

#keepalive_timeout 0;
keepalive_timeout 65;

gzip on;

include /etc/nginx/sites-enabled/*;
}

The nginx.conf file contains these parts:

Image user—Sets the system user that will be used to run Nginx. This is www-data by default. You can add a group to this setting by inserting a second entry, which in our example would read: user www-data www-data;

Image worker processes—Allows you to set how many processes Nginx may spawn on your server. The default value of 1 is fine for most users, although some recommend setting this as high as 4. You can experiment, but do so carefully.

Image error_log—This is commented out in our example. You can set the location for an error log by removing the # that marks the line as a comment that should not be processed by Nginx, then adjusting the listed directory location, if you don’t want to use the default log location.

Image events and worker_connections—This setting adjusts how many concurrent connections Nginx will allow per process. It may be helpful to think of it this way: worker_connections times worker_processeswill give you the maximum number of clients that may connect to your server concurrently. Memory plays a factor in whether your server can actually serve all the permitted connections you configure, so if you aren’t sure whether your server has enough memory to go higher, leave both settings at their defaults and you should be fine.

Image http—This section contains the base settings for http access:

Image Leave the include and default_type lines alone, unless you enjoy trying to figure out why content is not being displayed or you know you must adjust which types of content are permitted.

Image Feel free to adjust the location of the access_log, which records all attempts to connect to your server, or comment out the line to disable it.

Image sendfile is used when you permit Nginx to ignore the contents of the file it is sending, such as when serving larger files that do not require a multiple request and confirmation system when being served, thereby freeing system resources for items that do require Nginx to watch over. It is recommended that you leave this setting on unless you know why you are turning it off, as it saves resources when serving things like graphics.

Image tcp_nopush sends HTTP response headers in one packet, and this is actually a pretty good thing, but experimenting with it is okay.

Image tcp_nodelay is for use with items that do not require a response, but most general web use does demand responses, so this is often best commented out, although trying it to see if it makes a difference in your circumstance is okay.

Image The keepalive_timeout sets the number of seconds that Nginx will keep a connection open when a request is made. The default is to keep this connection open for over a minute, which seems a bit odd since you have a limited number of connections available and keeping a connection alive prevents another requester from using that slot again until the time-out occurs. Setting this to a low number like 2 or 3 seconds seems to permit more people to connect in a minute than would be able to do so otherwise. If you are serving a website with little traffic, the setting won’t matter. If you have a lot of traffic, a lower number is generally a good idea.

Image gzip allows the use of on-the-fly gzip compression, which can make data transfers a bit faster.

Image include defines files that are located outside of the nginx.conf file that are to be read by Nginx and used for its configuration. You can include multiple files, just create a new line for each. Listed in our example is a directive to include everything listed in a directory that is generally used for Virtual Hosts, as described in the Virtual Hosting section. You could instead place a server variable here and define it (as we will in the Virtual Hosts section), instead of the include, but if you have multiple sites, configuring how Nginx works for each site individually can be useful, especially if you have one site that has a lot of traffic and another that has little.

Whenever you make a change to the nginx.conf file, you must restart Nginx to reload the configuration into Nginx for the changes to take effect, like this:

Click here to view code image

matthew@seymour:~$ sudo service nginx restart

Some prefer to stop and start it, perhaps doing the configuration work in between. This is quite common as Nginx in the past had a habit of not performing restarts perfectly. In my experience, bad resets are rare, however this method prevents any doubt:

Click here to view code image

matthew@seymour:~$ sudo service nginx stop
matthew@seymour:~$ sudo service nginx start

Virtual Hosting

One of the more popular services to provide with a web server is to host a virtual domain. Also known as a virtual host, a virtual domain is a complete website with its own domain name, as if it was a standalone machine, but it’s hosted on the same machine as other websites.

Nginx implements this capability in a simple way: just create a configuration file for your virtual host, name it for that host, and place it in /etc/nginx/sites-enabled. We prefer to place our files in /etc/nginx/sites-available and then create a symlink in sites-enabled, but that is not a requirement. Doing so does allow you to disable one out of several sites by simply deleting the symlink and reloading the configuration or restarting Nginx while preserving the complete configuration for the site, so we recommend you give it a try.

You can place the actual files for your website wherever you like. The configuration files for Nginx will tell the web server where to find them. We like to create them in the main website creator/maintainer’s directory, but others prefer /var/www and still others opt for a different location. Choose a location you like and make a note of it. You will need it shortly.

Here is an example file for a virtual host, which we will call yourdomain.com. Name the file yourdomain.com and place it in sites-enabled or sites-available, as described above. This file includes comments that will help you fill in your specific details:

Click here to view code image

#this first server module is just a rewrite directive - it is not required, and you
#can make the rewrite go the other way, to force NOT using www
server {
listen 80; #sets the HTTP port from which the website is
served
server_name www.yourdomain.com; #names the server using the www prefix

#if a server request is made without www, this next line will rewrite it
rewrite ^/(.*) http://yourdomain.com/$1 permanent;
}

#this second server module tells Nginx where to find the files when requested
server {
listen 80; #sets the HTTP port from which the website is
served
server_name yourdomain.com; #names the server being configured
location / { #sets the location of the files being served
root /home/<yourusername>/public_html/yourdomain.com/; #top directory for the
site
index index.html;
}
}

Earlier in this section we mentioned that you may place the files for your website wherever you like. The root line in the file just created is where you will place this information. Here we use <yourusername>’s personal home folder, and place within it a directory called public_html specifically created for placing website files. Since our example anticipates serving multiple websites with this one server, it goes further and creates a directory for our example website, yourdomain.com.

At this point, everything should work for simple HTML sites. To add additional domains, repeat these steps for each domain being served.

Setting Up PHP

If you have CGI or other script content, such as a website written in PHP like WordPress or Drupal, you have more work to do. While the ability to serve PHP is available by default in Nginx (it didn’t use to be), it still requires additional setup. This section will add the ability to serve PHP content to our existing Nginx server. As a result, there are some PHP-specific parts to this process. They should be obvious.

First, we need to make sure PHP is installed on the server. There are many ways to do this. For this example, we will use PHP-FPM, which you can learn more about at http://php-fpm.org.

To do this, install the following packages: php5-cli, php5-cgi, psmisc, spawn-fcgi, and php5-fpm.

Edit the file /etc/php5/fpm/pool.d/www.conf to make php-fpm use a unix socket instead of a TCP/IP connection by finding this line:

listen = 127.0.0.1:9000

and replacing it with:

listen = /tmp/php5-fpm.sock

This is where you need to check the requirements of whatever PHP-based application you intend to install and use. Some require other PHP extensions in addition. You may also need a database. We will skip this step as the details differ for each application, but this is when you would likely want to take care of these details, although you can probably make them up later. If all you want to do is serve PHP scripts that you have written or run them on your server, you are probably fine not worrying about this and moving on.

Next, you need to edit either /etc/nginx/nginx.conf or the file for your virtual host, like /etc/nginx/sites-enabled/yourdomain.com from our earlier example, to include information that Nginx needs to know how to deal with PHP content. Editing either will work, the difference is that editing the virtual host file will only affect that website while editing nginx.conf will affect everything on your server.

Here is an example of an edited server module in one of these files. Note what is moved and what is added from the previous example:

Click here to view code image

server {
listen 80; #sets the HTTP port from which the website is
served
server_name www.yourdomain.com; #names the server using the www prefix

#if a server request is made without www, this next line will rewrite it
rewrite ^/(.*) http://yourdomain.com/$1 permanent;
}

#this second server module tells Nginx where to find the files when requested
server {
listen 80; #sets the HTTP port from which the website is
served
server_name yourdomain.com; #names the server being configured
root /home/<yourusername>/public_html/yourdomain.com/; #top directory for the
site
index index.html index.php;
client_max_body_size 1G;
fastcgi_buffers 64 4K;
location / { #sets the location of the files being served
try_files $uri =404;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/tmp/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}

Restart Nginx and you are all set. See http://wiki.nginx.org/PHPFcgiExample for more details.

Adding and Configuring Modules

This topic is bigger than can or should be covered in this book, where we only intend to introduce and help you acquire a basic competence with a wide range of technologies and features available in/with/for Ubuntu. In this chapter, we have only set up a basic server. This will serve the needs of most people, but there are tons of other settings available for you to use and many other configuration options for core modules and even optional modules you can add to your server.

Adding additional modules is something that must be done when Nginx is compiled, so if you need something that is not included by default in the package from the Ubuntu repositories, you will have to read the official documentation, download Nginx from the website, and compile it yourself. The best way to start is to immerse yourself in the official module documentation at http://nginx.org/en/docs/.

To configure an enabled module, whether a default module or an optional one, start at the same documentation, find the module you want to configure in the list, and click its entry to learn about the various options. Even the Core module that we configured in our nginx.conf example has a ton of extra options. You may not need any of them, but you may find something useful.

HTTPS

Nginx comes with the ability to encrypt communications using openssl. What this means is that your website can be accessed using https:// instead of just http:// and all communications to and from the site will be encrypted.

For HTTPS to work, a certificate and a key are required. You should either generate a self-signed certificate and key (adequate for internal use or for personal sites) or buy a certificate from a certified CA authority (necessary if you want anyone to trust your site for commercial ventures).

To generate a key for the certificate, use this command:

Click here to view code image

matthew@seymour:~$ openssl genrsa -des3 -out server.key 2048

This will generate a basic key using Triple-DES and 2048-bit encryption. See the man page for openssl for more information about possible settings.

To generate a Certificate Signing Request (CSR), use this command:

Click here to view code image

matthew@seymour:~$ openssl req -new -key server.key -out server.csr

You will be asked for some information to complete the request.

To generate a self-signed certificate, use this command:

Click here to view code image

matthew@seymour:~$ openssl x509 -req -days 365 -in server.csr -signkey server.key
-out server.crt

This will create a certificate that is valid for 365 days. Certificates, even from vendors, have expiration dates. Certificates should be renewed regularly to make your site visitors feel comfortable that they are dealing with who they think they are dealing with.

To copy the certificate to its proper location, use this command:

Click here to view code image

matthew@seymour:~$ cp server.crt /etc/nginx/ssl/

To copy the key to its proper location, use this command:

Click here to view code image

matthew@seymour:~$ cp server.key /etc/nginx/ssl/

Next, we must modify our Nginx configuration to use the server certificate and key files. This is done in the server module of the config file. Here is our earlier example, with the additions we need in bold.

Click here to view code image

server {
listen 80; #sets the HTTP port from which the website is served

listen 443 ssl;

server_name www.yourdomain.com; #names the server using the www prefix

ssl_certificate /etc/nginx/ssl/server.crt
ssl_certificate /etc/nginx/ssl/server.key

#if a server request is made without www, this next line will rewrite it
rewrite ^/(.*) http://yourdomain.com/$1 permanent;
}

You can now access web pages on your server using https://. This is adequate for testing and internal use, but not for anything else.

The best thing to do, if you are going to host a professional site, is to use a certified CA authority. Every CA has their preferred method, so you should read their requirements before you start. The basic process is usually like this:

1. Create a private and public encryption key pair.

2. Create a certificate based on the public key.

3. Create a certificate request with information about your server and the company hosting it.

4. Send your certificate request and public key along with proof of your company’s identity and payment to the CA.

5. They verify the request and your identity and send back a certificate like the self-signed one we created, but signed by the CA.

6. You install that certificate on your server and configure Apache2 to use it.

The CA-signed certificate provides advantages. First, browsers are built with data about most CA authorities and will automatically recognize a signature from one of them on your certificate most of the time. A self-signed certificate will cause the browser to display a rather scary looking (to a non-technical person) warning and require the user to bypass it before viewing your site. In addition, when the CA issues the signed certificate they are guaranteeing the identity of the organization providing the web pages.

To learn more about certificates and keys, including installation of keys and certificates you pay for, see http://tldp.org/HOWTO/SSL-Certificates-HOWTO/index.html.

References

Image http://nginx.org/en/docs/—The Nginx wiki website where you can find extensive documentation and information about Nginx, including installation instructions, downloads, and tips for configuration and use.