OsGate.org Logo

Set up a web server usgin nginx - nginx web server network

Networks Networks

Date 16.05.2011

Visits 19754

"Nginx is a web server that is growing very rapidly in these last years due to its lightweight and its reliability. This web server can covers different roles in your network, for example you can use it as proxy or reverse proxy. In this article we will cover the web server section."

Nginx

Nginx is an high-performance and lightweight multipurpose server for the web.

It can be used for various types of installation:

  • Web server (HTTP)
  • Secure web server (HTTPS)
  • Proxy
  • Reverse Proxy
  • Email server (IMAP/POP3)

In this article we will cover the web server (HTTP and HTTPS) part.

Nginx installation

For example, if you are using a debian based distribution follow these steps to install nginx:

apt-get update
apt-get install nginx

For other distributions, use the packages manager provided with it.

If you want to compile nginx from source:

  1. Download the latest version of nginx from here: http://www.nginx.org/en/download.html
  2. Unzip it: tar xvf tar xvf nginx-1.0.2.tar.gz 
  3. Change the directory: cd nginx-1.0.2
  4. Start the configure: ./configure
  5. If there aren't errors start the compilation: make
  6. If there aren't errors install the program (root needed): make install

 Web server

After the installation start nginx:

Debian based: /etc/init.d/nginx start

If you can't start nginx check you have the root permissions.

And we can see that our web server is up and running:

root@debian:/etc/nginx# ps aux | grep nginx
root      2929  0.0  0.1   5000   704 ?        Ss   09:07   0:00 nginx: master process /usr/sbin/nginx
www-data  2930  0.0  0.4   5296  2192 ?        S    09:07   0:00 nginx: worker process
root      3087  0.0  0.1   3300   744 pts/0    S+   09:32   0:00 grep nginx


As you can see there are mainly two processes, the "master" process, wich is the main process and it's owned by "root". The other process is the one called "worker" and it's owned by an unprivileged users. In our case the web server user is called "www-data".

root@debian:/etc/nginx# netstat -na | grep 80
tcp        0      0 0.0.0.0:80              0.0.0.0:*            LISTEN    
tcp6       0      0 :::80                   :::*                    LISTEN     

With the default configuration, nginx will listen on both IPv4 and IPv6.

Now if you type the IP of your server in a browser you will see a welcome message like these:

In our case using lynx we obtain this message:

                                                                                      It works!

   This is the default web page for this server.

   The web server software is running but no content has been added, yet.


 If you don't see this message, probably the root document directory of the web server is empty. We will see this later.

 Configuration

You can find the configuration files in the "/etc/niginx" directory:

root@debian:/etc/nginx# ls -l
total 48
drwxr-xr-x 2 root root 4096 Jul 29  2010 conf.d
-rw-r--r-- 1 root root  909 Nov 26  2009 fastcgi_params
-rw-r--r-- 1 root root 2837 Nov 26  2009 koi-utf
-rw-r--r-- 1 root root 2223 Nov 26  2009 koi-win
-rw-r--r-- 1 root root 3042 May  6  2010 mime.types
-rw-r--r-- 1 root root 1019 Nov 26  2009 nginx.conf
drwxr-xr-x 2 root root 4096 May 16 09:05 sites-available
drwxr-xr-x 2 root root 4096 May 16 09:05 sites-enabled
-rw-r--r-- 1 root root 3610 Nov 26  2009 win-utf

We can see that there are some files and directories. We will begin with by configuring the main deamon, editing nginx.conf.

 nginx.conf

This is the main configuration file for the nginx daemon. By default it looks like this one:

root@debian:/etc/nginx# cat nginx.conf 
user www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;

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

    sendfile        on;

    keepalive_timeout  65;
    tcp_nodelay        on;

    gzip  on;
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Here the explanation line by line:

nginx.conf directives
Directive Explanation
user www-data; This is the user who will execute the worker processes. It safer to execute the workers without root privileges, so check that you have the user by looking for the /etc/shadow file. If you don't have the user, you can create it using useradd.
worker_processes  1;

This set the number of worker_processes to run when we start nginx. This value must be set by considering the number of clients you will serve because the worker processes will be eleborate your request. The maximal number of clients allowed will be defined by worker_processes * worker_connections.

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

The path where the errors are collected.
pid        /var/run/nginx.pid; The path where the file with the current/active process id of nginx will be stored.

events

This directive can accept sub-directives. Here we can use, for example, worker_connections for specify the number of connection to this server. Another useful directive can be debug_connection. This let us to collect log for the client that belong to a specified network or ip.

worker_connections

The value of this directive can be used to compute the total number of clients if used along the worker_processes of the main section.

The number of max_clients is defined as follow: worker_processes * worker_connections.

http This is the beginning of the configuration for the http core module.
include /etc/nginx/mime.types With this file included, nginx will be able to recognizes the files by extension assinging for each file found the correct mime type. Then the mime type will be sent to the clients. It's possible to define our own mime types, for example for a file with the extension .photo we can assing the mime type image/png.
access_log  /var/log/nginx/access.log; This specifies the location for the access log of nginx.
sendfile on; This will enable the usage of the system call sendfile(), in order to obtain better performance rather using read() and write().
keepalive_timeout 65; When using this parameter, you will assing to a keep alive connection a timeout of 65 seconds. This means that the server will end the connections with the client after this time.
tcp_nodelay on; TCP_NODELAY is a TCP option used to turn off the use of Nagle's algorithm. This because the Nagle's algorithm buffers small packet into bigger frame in order to reduce congestion, but there are some cases where it's better if we disable this behaviour. With this option set, the TCP packets will be sended with the TCP_NODELAY flag on.
gzip on; By enabling the gzip compression, our server will be able to send compressed data through gzip.
gzip_disable "MSIE [1-6].(?!.*SV1)"; Some old user agents don't fully support the gzip compression, and the use of this technique, for example with some versions of Internet Explorer 6, will lead to mangled code. This directive will disable the use of gzip on IE6 by using a regular expression.
include /etc/nginx/conf.d/*.conf; The folder that we include here, is the one that contains other configurations, such as the one of the proxy server. You can see that with nginx we can easly manage configuration files due to its modularity.
include /etc/nginx/sites-enabled/*; The "sites-enabled" folder contains the configurations for the virtual hosts.  So when you have to add another virtual hosts to your configuration you can create a file in this folder named for example "vhost.mysite" and then configure it properly. By default in this folder you will find a filed named "default". This contains the default configuration for the HTTPS server and some virtual hosts.

 Virtual hosts

Configuring virtual hosts using nginx is not a difficult task. In the configuration above, the directive "include /etc/nginx/sites-enabled/*;" specifies the virtual hosts folder, so we will place the file for every single virtual host here.

We only need to create a file that will contain the configuration for a single virtual host, in our case we'll call this one "slack.local".

NOTE: that you must have a DNS server in order to point the name "slack.local" to the web server. If you don't have a DNS server and you want only to try nginx on your localhost, you can edit the file "/etc/hosts" and add a line like this "127.0.0.1 slack.local".

For a very basic configuration we'll write these lines of code:

server{
listen 80;
  server_name slack.local;
    access_log  /var/log/nginx/domain2.access.log;
    root /var/www/slack/;
}

In the section "server" we have to write the configuration parameters.

First we have "server_name" that specifies the name that we will type in the browser in order to access to this virtual host.

Secondly we define the "access_log" directory for storing the log of the people that will access the site.

The last line contains the root content directory for this virtual host. In our case we've choosed "/var/www/slack/".

Now we can perform some tests before accessing "slack.local" from our web browser.

If you have configured the system with DNS use "dig" and control if the name "slack.local" is resolved.

bash-4.1# dig slack.local

; <<>> DiG 9.7.3 <<>> slack.local
;; global options: +cmd
;; Got answer:
;; ->>HEADER
;; QUESTION SECTION:
;slack.local.                   IN      A

;; ANSWER SECTION:
slack.local.            604800  IN      A       192.168.1.206

;; AUTHORITY SECTION:
slack.local.            604800  IN      NS      slack.local.

;; Query time: 0 msec
;; SERVER: 192.168.1.206#53(192.168.1.206)
;; WHEN: Fri Jun 17 20:41:56 2011
;; MSG SIZE  rcvd: 59


We can see that "slack.local" is resolved correctly. When we will write "slack.local" in our web browser the web server 192.168.1.206 will handle the request.

Now the final test is to type "slack.local" using our web browser:

         It doesn't work!

   This isn't the default web page for this server.

   The web server software isn't running but some content has been added, yet.
  

This is the page we've set up for our test and as we see we can display it correctly.

If you want to be really sure that the configuration is working, add a second virtual host, create a new index.html for this virtual host, modifiy the dns and finally test if you can reach the two different pages in the browser.

 HTTPS

Our next step will be to set up a virtual host using the secure HTTPS protocol. When using HTTPS, the connections between server and client will be encrypted, and in order to encrypt this communication channel, we need to generate first the SSL certificate.

 Generating the certificate

To begin, we will move to the directory "/etc/nginx/" since we will store here the file for the certificates.

Now we have to generate the private key that we will use later to sign the CSR (Certificate Signing Request).

Type the following command to generate it:

root@debian:/etc/nginx/conf.d# openssl genrsa -des3 -out server.key 2048
Generating RSA private key, 2048 bit long modulus
..............................................................................+++
..............................+++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key

This will generate a 2048 bit long key. You can see that we want to protect the key by using a pass phrase. Using a pass phrase will avoid that anyone can read the key. We use the des3 to encrypt the pass phrase.

NOTE: with the pass phrase enabled you are asked every time you start nginx to enter it. If you want to disable this behaviour run the command above without the "-des3" option. If you do this, the private key will be world readable, so you have to be sure that only the root account or the administrator of the server can read the file.

Now the second step is to generate a CSR (Certificate Signing Request). A CSR is a certificate that must be sent to the CA (Certification Auhtority) along the private key in order to obtain a valid and verifyed SSL certificate. We will obiouvsly jump this step cause we will create a dummy certificate.

Generation of a CSR:

root@debian:/etc/nginx/conf.d# openssl req -new -key server.key -out server.csr 
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CH
State or Province Name (full name) [Some-State]:Ticino
Locality Name (eg, city) []:Lugano
Organization Name (eg, company) [Internet Widgits Pty Ltd]:IT
Organizational Unit Name (eg, section) []:IT
Common Name (eg, YOUR name) []:IT
Email Address []:it@company.domain

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

You are asked for the private key's password and then you have to insert some general information such as the "Organization Name" or the "Country Name".

Now we will create our dummy certificate with the following command:

root@debian:/etc/nginx# openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=CH/ST=Ticino/L=Lugano/O=IT/OU=IT/CN=IT/emailAddress=it@company.domain
Getting Private key
Enter pass phrase for server.key

We've generated a x509 certificate valid for one year (x509 -req -days 365) using the CSR and the private key (-in server.csr -signkey server.key) we've generated before to sign it. Our final certificate is "server.crt".

You can see that you must insert the password of your private key.

Virtual host with SSL

Now we have to configure nginx in order to access to the secure web site from our browser. In the sites-enabled folder we have added the virtual host "ssl.local":

root@debian:/etc/nginx/sites-enabled# cat ssl.local 
server{
        listen 443;

        server_name ssl.local;

        ssl  on;
        ssl_certificate  /etc/nginx/server.crt;
        ssl_certificate_key  /etc/nginx/server.key;
        access_log  /var/log/nginx/ssl.access.log;

        root /var/www/ssl/;
}

 We've added "listen 443" so this virtual host will listen on the 443 (HTTPS) port. Then under "server_name" we've written three directive:

  • ssl on; => we activate ssl for this virtual host
  • ssl_certificate /etc/nginx/server.crt => the path to the certificate
  • ssl_certificate_key /etc/nginx/server.key => the path to the private key

 Final configuration

 nginx.conf

root@debian:/etc/nginx# cat nginx.conf 
user www-data;
worker_processes  1;

error_log  /var/log/nginx/error.log;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
    # multi_accept on;
}

http {
    include       /etc/nginx/mime.types;

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

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;
    tcp_nodelay        on;

    gzip  on;
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

 Certificates

root@debian:/etc/nginx# ls -l server.*
-rw-r--r-- 1 root root 1249 Jun 20 15:40 server.crt
-rw-r--r-- 1 root root 1025 Jun 19 18:36 server.csr
-rw-r--r-- 1 root root 1743 Jun 19 18:12 server.key

 slack.local

root@debian:/etc/nginx/sites-enabled# cat slack.local 
server{
        listen 80;
        server_name slack.local;
        access_log  /var/log/nginx/slack.access.log;
        root /var/www/slack/;
}

 deb.local

root@debian:/etc/nginx/sites-enabled# cat deb.local 
server{
        listen 80;
        server_name deb.local;
        access_log  /var/log/nginx/deb.access.log;
        root /var/www/deb/;
}

 ssl.local

root@debian:/etc/nginx/sites-enabled# cat ssl.local 
server{
        listen 443;

        server_name ssl.local;

        ssl  on;
        ssl_certificate  /etc/nginx/server.crt;
        ssl_certificate_key  /etc/nginx/server.key;
        access_log  /var/log/nginx/ssl.access.log;

        root /var/www/ssl/;
}