Getting Started with NGINX - Part 1: Installation and Basic Setup

Updated by Linode Written by Linode

Contribute on GitHub

Report an Issue | View File | Edit File

Getting Started with NGINX - Part 1: Installation and Basic Setup

This guide is the first of a four-part series. Parts One and Two will walk you through installing NGINX Open Source from the NGINX repositories and making some configuration changes to increase performance and security. Parts Three and Four set up NGINX to serve your site over HTTPS and harden the TLS connection.

Before You Begin

  • You will need root access to the system, or a user account with sudo privilege.
  • Set your system’s hostname.
  • Update your system.

Install NGINX

Stable Versus Mainline

The first decision to make about your installation is whether you want the Stable or Mainline version of NGINX Open Source. Stable is recommended, and will be what this series of guides uses. More on NGINX versions here.

Binary Versus Compiling from Source

There are three primary ways to install NGINX Open Source:

  • A pre-built binary from your Linux distribution’s repositories. This is the easiest installation method because you use your package manager to install the nginx package. However, for distributions which provide binaries (as opposed to build scripts), you’ll be running an older version of NGINX than the current stable or mainline release. Patches can also be slower to land in distro repositories from upstream.

  • A pre-built binary from NGINX Inc.’s repository. This is the installation method used in this series. It’s still an easy installation process which only requires that you add the repository to your system and then install as normal. This method has the benefit of the most vanilla, upstream configuration by default, with quicker updates and newer releases than a Linux distribution’s repository. Compile-time options often differ from those of the NGINX binary in distribution repositories, and you can use nginx -V to see which your binary was built with.

  • Compiling from source. This is the most complicated method of installation but still not impractical when following NGINX’s documentation. Source code is updated frequently with patches and maintained at the newest stable or mainline releases, and building can be easily automated. This is the most customizable installation method because you can include or omit any compiling options and flags you choose. For example, one common reason people compile their own NGINX build is so they can use the server with a newer version of OpenSSL than what their Linux distribution provides.

Installation Instructions

The NGINX admin guide gives clear and accurate instructions for any installation method and NGINX version you choose, so we won’t mirror them here. When your installation completes, return here to continue the series.

Configuration Notes

As use of the NGINX web server has grown, NGINX, Inc. has worked to distance NGINX from configurations and terminology that were used in the past when trying to ease adoption for people already accustomed to Apache.

If you’re familiar with Apache, you’ll know that multiple site configurations (called Virtual Hosts in Apache terminology) are stored at /etc/apache/sites-available/, which symlink to files in /etc/apache/sites-enabled/. However, many guides and blog posts for NGINX recommend this same configuration. As you could expect, this has led to some confusion, and the assumption that NGINX regularly uses the ../sites-available/ and ../sites-enabled/ directories, and the www-data user. It does not.

Sure, it can. The NGINX packages in Debian and Ubuntu repositories have changed their configurations to this for quite a while now, so serving sites whose configuration files are stored in /sites-available/ and symlinked to /sites-enabled/ is certainly a working setup. However it is unnecessary, and the Debian Linux family is the only one which does it. Do not force Apache configurations onto NGINX.

Instead, multiple site configuration files should be stored in /etc/nginx/conf.d/ as example.com.conf, or example.com.disabled. Do not add server blocks directly to /etc/nginx/nginx.conf either, even if your configuration is relatively simple. This file is for configuring the server process, not individual websites.

The NGINX process also runs as the username ngnix in the nginx group, so keep that in mind when adjusting permissions for website directories. For more information, see Creating NGNIX Plus Configuration Files .

Finally, as the NGINX docs point out, the term Virtual Host is an Apache term, even though it’s used in the nginx.conf file supplied from the Debian and Ubuntu repositories, and some of NGINX’s old documentation. A Server Block is the NGINX equivalent, so that is the phrase you’ll see in this series on NGINX.

NGINX Configuration Best Practices

There is a large variety of customizations you can do to NGINX to fit it better to your needs. Many of those will be exclusive to your use case though; what works great for one person may not work at all for another.

This series will provide configurations that are general enough to be useful in just about any production scenario, but which you can build on for your own specialized setup. Everything in the section below is considered a best practice and none are reliant on each other. They’re not essential to the function of your site or server, but they can have unintended and undesirable consequences if disregarded.

Two quick points:

  • Before going further, first preserve the default nginx.conf file so you have something to restore to if your customizations get so convoluted that NGINX breaks.

    cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup-original
    
  • After implementing a change below, reload your configuration with:

    nginx -s reload
    

Use Multiple Worker Processes

Add or edit the following line in /etc/nginx/nginx.conf, in the area just before the http block. This is called the main block, or context, though it’s not marked in nginx.conf like the http block is. The first choice would be to set it to auto, or the amount of CPU cores available to your Linode.

worker_processes auto;

For more information, see the sections on worker processes in the NGINX docs and this NGINX blog post.

Disable Server Tokens

NGINX’s version number is visible by default with any connection made to the server, whether by a successful 201 connection by cURL, or a 404 returned to a browser. Disabling server tokens makes it more difficult to determine NGINX’s version, and therefore more difficult for an attacker to execute version-specific attacks.

Server tokens enabled:

NGNINX server tokens enabled

Server tokens disabled:

NGINX server tokens disabled

Add the following line to the http block of /etc/nginx/nginx.conf:

server_tokens off;

Set Your Site’s Root Directory

The directory NGINX serves sites from differs depending on how you installed it. At the time of this writing, NGINX supplied from NGINX Inc.’s repository uses /usr/share/nginx/.

The NGINX docs warn that relying on the default location can result in the loss of site data when upgrading NGINX. You should use /var/www/, /srv/, or some other location that won’t be touched by package or system updates. For more explanation, see Using the default document root and Not using standard document root locations.

This series will use /var/www/example.com/ in its examples. Replace example.com where you see it with the IP address or domain name of your Linode.

  1. The root directory for your site or sites should be added to the corresponding server block of /etc/nginx/conf.d/example.com.conf:

    root /var/www/example.com;
    
  2. Then create that directory:

    mkdir -p /var/www/example.com
    

Serve Content Over IPv4 and IPv6

Default NGINX configurations listen on port 80 and on all IPv4 addresses. Unless you intend your site to be inaccessible over IPv6 (or are unable to provide it for some reason), you should tell NGINX to also listen for incoming IPv6 traffic.

Add a second listen directive for IPv6 to the server block of /etc/nginx/conf.d/example.com.conf:

listen [::]:80;

If your site uses SSL/TLS, you would add:

listen [::]:443 ssl;
Note
You can also specify your Linode’s public IP addresses for NGINX to listen on. For example, the line would then be listen 203.0.113.4:80;.

Static Content Compression

You do not want to universally enable gzip compression because, depending on your site’s content and whether you set session cookies, you risk vulnerability to the CRIME and BREACH exploits.

Compression has been disabled by default in NGINX for years now, so it’s not vulnerable to CRIME out of the box. Modern browsers have also taken steps against these exploits, but web servers can still be configured irresponsibly.

On the other hand, if you leave gzip compression totally disabled, you rule out those vulnerabilities and use fewer CPU cycles, but at the expense of decreasing your site’s performance. There are various server-side mitigations possible and the release of TLS 1.3 will further contribute to that. For now, and unless you know what you’re doing, the best solution is to compress only static site content such as images, HTML, and CSS.

Below is an example of how to do that, and you can view all available mime types with cat /etc/nginx/mime.types. Though gzip directives can go in the http block if you want it to apply to all sites served by NGINX, it’s safer to use it only inside server blocks for individual sites and content types.

gzip          on;
gzip_types    text/html text/plain text/css image/*;

In cases where NGINX is serving multiple websites, some using SSl/TLS and some not, an example would look like below. The gzip directive is added to the HTTP site’s server block, which ensures it remains disabled for the HTTPS site.

/etc/nginx/conf.d/example1.com.conf
1
2
3
4
5
6
server {
    listen         80;
    server_name    example1.com;
    gzip           on;
    gzip_types text/html text/css image/jpg image/jpeg image/png image/svg;
}
/etc/nginx/conf.d/example2.com.conf
1
2
3
4
5
server {
    listen         443 ssl;
    server_name    example2.com;
    gzip           off;
}

There are various other options available to NGINX’s gzip module. See the NGINX docs for more information, and if you prefer to compile your NGINX build, you can include the ngx_http_gzip_static_module which further suits static content compression.

Configuration Recap

To summarize where we are so far:

  • The stable version of NGINX Open Source was installed from the nginx.org repository.

  • One basic website is accessible:

    • The root directory is located at /var/www/example.com/
    • The configuration file is located at /etc/nginx/conf.d/example.com.conf

      /etc/nginx/conf.d/example.com.conf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      
      server {
          listen         80 default_server;
          listen         [::]:80 default_server;
          server_name    example.com www.example.com;
          root           /var/www/example.com;
          index          index.html;
      
          gzip             on;
          gzip_comp_level  3;
          gzip_types       text/plain text/css application/javascript image/*;
      }
  • Changes we want NGINX to apply universally are in the http block of /etc/nginx/nginx.conf. Our additions are at the bottom of the block so we know what was added compared to what’s provided by default.

    nginx.conf now looks like the following example. Note that nginx.conf does not contain any server blocks:

    /etc/nginx/nginx.conf
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    
    
        server_tokens       off;
    }

Part 2: (Slightly More) Advanced Configurations

By now you should have a basic NGINX installation and a some foundational settings to get you started. For slightly more advanced configurations, yet still applicable to anyone hosting a site on a Linode, see Part 2 of this series: (Slightly more) Advanced Configurations for NGINX

Join our Community

Find answers, ask questions, and help others.

comments powered by Disqus

This guide is published under a CC BY-ND 4.0 license.