Nginx Basics – Part 0: Configuration Files

Nginx Basics Part 0 - Configuration Files

Nginx is one the most useful pieces of software when it comes to the web. It has quickly grown from a simple web server to a fully-featured load balancer, reverse proxy server, and a key component in technologies like Kubernetes as an ingress point. Developers, DevOps and sysadmins all come across its installations in some capacity or the other. So let's dig into what are the various nuts and bolts of a typical Nginx installation. We will focus only on the essential parts of configurations -- The Basics.

TL;DR

A. For Debian and Ubuntu like systems the main configuration files can be found at:

  • /etc/nginx/nginx.conf  where all the main configuration lives. You need not edit this.
  • Directory /etc/nginx/sites-enabled/ with a default file already there for reference

Any custom configuration you wish to add can be added in the directory /etc/nginx/sites-available and you can then create a symlink of that file to the directory /etc/nginx/sites-enabled:

$ sudo ln -s /etc/nginx/sites-available/my-configuration.conf /etc/nginx/sites-enabled
$ sudo systemctl reload nginx

That's the Debian way of doing things. You can also add configurations to /etc/nginx/conf.d/

B. On CentOS, Fedora and RedHat systems:

  • All the default configuration is crammed inside /etc/nginx/nginx.conf
  • For most use cases, the custom configuration will go to /etc/nginx/conf.d with file names ending in .conf 

Setup

To get started you will need the following:

  1. Root access to a VPS with a Public IPv4 address. If you don't already have one, you can get one from SSDNodes.
  2. Ubuntu 20.04 LTS is used as the base operating system. Although, we will discuss the difference between Nginx on different distributions too.

The Default Nginx Setup

Let's install, enable and start Nginx:

$ sudo apt install nginx -y;
$ sudo systemctl enable --now nginx;

By default Nginx will start a simple HTTP server, and serve this default web page:

Nginx Default Webpage

You can view the webpage, by simply typing in the Public IP address of your VPS  in a web browser. The actual webpage might be different for RedHat like distros and Ubuntu, but ultimately it will be a simple html file that Nginx is configured to serve. Which brings us to the next part -- Configuration.

Configuration Files

All the configuration for Nginx lives in the directory /etc/nginx with the /etc/nginx/nginx.conf file at the heart. This is where things get interesting. For the purposes of this blog post, we will ignore various miscellaneous file like in /etc/nginx koi-win, koi-utf, mime.types proxy_params and the rest. For this post, the basics, the files that matter us are:

  1. nginx.conf: The main configuration file of Nginx server
  2. conf.d: The directory where user specific configurations are stored.
  3. site-available and sites-enabled: The directory where user specific configurations are stored for Ubuntu and Debian like systems.

Default nginx.conf

Removing all the comments, for Ubuntu 20.04 the default configuration comes with the following:

nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;

events {
    worker_connections 768;
}

http {

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

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

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;
    gzip on;

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

sites-enabled/default

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;
    server_name _;

    location / {
        try_files $uri $uri/ =404;
    }
}

This is all there is to the man configuration. Each single line ending with a semi-colon is called a directive, in a bit more formal terms:

  1. A Simple Directive consists of the name of that directive name followed by a list of parameters, seperated by spaces, and ends with a semicolon (;).
    For example, the line:
    user www-data;

    Signifies that the Nginx worker process will start as the Unix user www-data and you can modify it to run as any other user that you want it to work as.
    Similarly, other directives like ssl_protocols is followed by a list of TLS protocols that Nginx supports. If you want to remove older versions like TLSv1, simply remove them from the list of parameters and reload nginx by running the command systemctl reload nginx and TLSv1 will no longer be supported. However, I don't recommend fiddling with any of the defaults, unless you really know what you are doing. If you wish to go beyond the basics, the official documentation is always a great place to go.

  2. A Block Directive
    A block directive is made up of the directive name, followed by a pair of curly braces ({}) within which there are multiple single directives. The http block is a really important example for this one, and it is something you will be dealing with a lot. When you are within a block, that block is also called context. So, for example, the lines:
    include /etc/nginx/sites-enabled/*;
    include /etc/nginx/conf.d/*.conf;
    

    Are the directives within the http context. All the user specific configuration that lives in /etc/sites-enabled and /etc/conf.d are brought into the http context, because of the above two lines in nginx.conf.

Difference between RedHat-like systems and Debian like systems:

Debian and Ubuntu

Nginx configuration files are quite modular to begin with. You won't find yourself in need of changing the main configuration file unless you are really fine-tuning something. On Debian and Ubuntu, like systems, this modularity is taken a bit further. All your configuration files live like simple text files in the folder /etc/nginx/sites-available/ and if you want to "enable" a certain configuration you will do so by creating a symlink (a shortcut) of that file to the folder /etc/nginx/sites-enabled:

$ sudo ln -s /etc/nginx/sites-available/my-config /etc/nginx/sites-enabled/my-config

This lets users experiment freely with different configurations. If you need to remove a particular configuration, just remove the symlink from the sites-enabled directory and reload nginx. In fact, even the default file that was shown in the previous section is a symlink and the actual file lives in the sites-available.

There is also conf.d file that allows you to add configurations in a way that works across all distributions. The only difference is that you have to name your files with a .conf extension as specified in the nginx.conf

CentOS, RedHat and Fedora systems

In case of CentOS, RHEL and other similar systems, Nginx gets its user specific configuration mostly from the conf.d subdirectory as decribed by this line in the file nginx.conf in the http context:

include /etc/nginx/conf.d/*.conf;

Configuring a simple static site server

To finish off our tour of Nginx configuration, let's write a configuration that will serve a static website from the directory /var/www/my-web.

Let's create a simple website page:

$ sudo mkdir -p /var/www/my-web
$ cd /var/www/my-web
$ vim index.html

Put the follow contents in the index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Page Title</title>
</head>
<body>
    <h1>This is a Heading</h1>
    <p>This is a paragraph.</p>
</body>
</html>

This isn't much, but it will serve well as an example. You can, of course create a complete static site using software like Hugo.

Next we can add a configuration, instead of going through site-available folders and then creating symlinks, I will just write the server definition in conf.d folder. It will work on all platforms and it is simpler to manage:

$ vim /etc/nginx/conf.d/my-web.conf
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/my-web;
    index index.html index.htm index.nginx-debian.html;
    server_name _;

    location / {
        try_files $uri $uri/ =404;
    }
}

Once the configuration is in place, let's remove the old configuration and reload:

$ sudo rm /etc/sites-enabled/default
$ sudo systemctl reload nginx

If you wish to bring back the original configuration, simply remove my-web.conf file and recreate the symlink for the default config.

Conclusion

If you wish to learn more about Nginx, check out this post detailing how to use it as a reverse proxy endpoint to serve multiple websites. More information about various Nginx directives can be found here.