Pull to refresh

In simple terms about a simple Nginx Unit

Level of difficultyEasy
Reading time8 min
Views2.1K
Original author: Pavel Zavadski

Contents

  1. Introduction

  2. What is Nginx Unit?

  3. Installation

  4. Configuration

    1. Listeners

    2. Routes

    3. Applications and language modules

    4. Simple application

  5. Log collection

  6. Certificate installation

  7. Possible performance issues

  8. Conclusion

Introduction

Good afternoon. Today I want to tell you about working with Nginx Unit in simple words. Let's talk about what NGINX UNIT is, how to work with it, what problems may arise. I won't drag on, so let's get to the review :)

What is Nginx Unit?

NGINX Unit is a new web server released in 2017 by the developers of the original NGINX, for running web applications. The web server is open source and is available on Github.

NGINX UNIT is dynamic and does not require rebooting the web server to apply configuration files due to the use of REST APIs to interact with it.

On NGINX UNIT you can configure the server to use static files (e.g. run a one-page website or a built React application) or use one of the built-in modules to run applications in Python, PHP, NodeJS, Java and other languages. You can see the full list on the official website.

Those who want to try the web server can follow the article and thus learn how to work with it.

Installation

For the example, we will install Nginx Unit latest version from the official repository on a virtual machine on Ubuntu 22.04. If you are using a different OS, a guide can be found here.

Downloading and saving the Nginx Unit keys

sudo curl --output /usr/share/keyrings/nginx-keyring.gpg https://unit.nginx.org/keys/nginx-keyring.gpg

Adding a repository. It is needed to locate the package on the Nginx Unit servers. To do this, you need to create a file at the path /etc/apt/sources.list.d/unit.list. This can be done by opening the file with one of the editors in Ubuntu (vim, nano and so on). In the example I will use the nano text editor. By executing the command below we will create a new file.

nano /etc/apt/sources.list.d/unit.list
The nano editor that references the /etc/apt/sources.list.d/unit.list file
The nano editor that references the /etc/apt/sources.list.d/unit.list file

Next, paste in there the strings to define the repository. These are different for each version of Ubuntu, so if your version of Ubuntu is different from the example (Ubuntu 22.04), they can be found on the official website at the link.

Repositories for Nginx Unit for Ubuntu 22.04 version
Repositories for Nginx Unit for Ubuntu 22.04 version

Save the file, close it and update the system's package list with the apt update command (The command updates the Linux system's package index or package lists).

apt update

Once the update is complete install Nginx Unit with the apt install <package name> command (The apt install command finds the package in the operating system package index and downloads them along with their dependencies).

apt install unit

You can read about apt (apt-get) here.

After the installation we execute the command to restart the Nginx Unit service in the operating system:

systemctl restart unit

You can check the installation with the command:

unitd --version
Output of the command unitd --version
Output of the command unitd --version

This completes the installation. As you can see, Nginx Unit is installed version 1.30 (the latest version at the time of writing). Also below the version is the configuration command that you may need to build Nginx Unit from source.

Other installation methods

Configuration

Once the Nginx Unit is installed we will use the config key to work with it. This part of the web server API is responsible for configuration and contains: listeners, routes, applications and load balancers.

{
"listeners": {
// ...
},
"routes": [
// ...
],
"applications": {
// ...
},
"upstreams": {
// ...
}
}

To load the configuration we will access the API via socket.

To make it easier to store your results, I recommend creating JSON files. They are easy to store and you won't need to upload the config file all the time. Using the example of JSON files in the example I will update Nginx Unit settings. The file name for the example file will be config.json, and the command to upload and update config.

curl -X PUT --data-binary @config.json --unix-socket  /var/run/control.unit.sock http://localhost/config

Paths to load into config

  • Listeners /config/listeners.

  • Routes /config/routes

  • Applications /config/applications

Listeners

Listeners is the block that is responsible for incoming traffic. The web server can listen for Ip addresses and port. For example 127.0.0.1:8080 for use within the server or *:8080 to receive traffic coming to the server from a client application for example. (On Linux systems you can use abstract sockets. Example unix@abstract_socket)

To get all listeners, execute a socket command to access the API. Example command below:

curl -X GET --unix-socket /var/run/control.unit.sock http://localhost/config/listeners
{ // The object we get in the response
  "*:8080": { // Port 8080 Listener
    "pass": "routes" // Using routing for the listener
  }
}

The command makes a GET request to the socket using the --unix-socket flag which points to a running Nginx Unit. http://localhost/config/listeners .

Routes

To get all the routes, make an API call through the socket command:

curl -X GET --unix-socket /var/run/control.unit.sock http://localhost/config/routes

If the routes are empty, you will get an error as in the screenshot below.

Screenshots of the command execution
Screenshots of the command execution

Routes can be an array of parameters or an array of keys.

An example that performs all actions from the array when the listener accesses routes

{
    "listeners": {
        "*:80": {
            "pass": "routes"
        }
    },

    "routes": [
        {
            "action": {
                "share": "/var/www/example$uri"
            }
        }
    ]
}

Specify keys for the array so that listeners can filter traffic:

{
    "listeners": {
        "*:80": {
            "pass": "routes/http"
        },
        "*:443": {
            "pass": "routes/https",
          "tls": {
              "certificate": "bundle"
          }
        }
    },

    "routes": {
        "http": {
            "action": {
                "share": "/var/www/example$uri"
            }
        },
        "https": {
            "action": {
                "share": "/var/www/example_secure$uri"
            }
        },
    }
}

Applications and language modules

List of supported programming languages for running applications

  • Go

  • JavaScript (Node.js)

  • Java

  • Perl

  • PHP

  • Python

  • Ruby

  • Compiled binaries are also supported. (This will not be covered in this article.)

To get all applications, make an API call via the socket command:

curl -X GET --unix-socket /var/run/control.unit.sock http://localhost/config/applications

PHP application example. It runs 20 processes on port 80 using a PHP module. In order to install it you need to run the command:

apt install unit-php
{
    "listeners": {
        "*:80": {
            "pass": "routes"
        }
    },

    "applications": {
        "blogs": {
            "type": "php",
            "processes": 20,
            "root": "/var/www/blogs/scripts/"
        }
    }
}

This was the simplest example, but every application has additional keys that need to be flexible. You can read more about the applications in the documentation.

Simple application

Let's create an index.html file. To do this, open a text editor

nano /var/www/example/index.html

and paste the lines

<!DOCTYPE html>
<html>
   <head>
      <title>Welcome to NGINX Unit!</title>
      <style>
         body {
         width: 35em;
         margin: 0 auto;
         font-family: Tahoma, Verdana, Arial, sans-serif;
         }
      </style>
   </head>
   <body>
      <h1>Welcome to NGINX Unit!</h1>
      <p>If you see this page, the NGINX Unit web server is successfully
         installed and working.  Further configuration is required.
      </p>
      <p>For online documentation and support, please refer to
         <a href="https://unit.nginx.org/">unit.nginx.org</a>.<br/>
      </p>
      <p><em>Thank you for using NGINX Unit.</em></p>
   </body>
</html>

Create a config.json file and paste the lines below:

{
    "listeners": {
        "*:80": {
            "pass": "routes"
        }
    },

    "routes": [
        {
            "action": {
                "share": "/var/www/example$uri"
            }
        }
    ]
}

Load the configuration file with the command:

curl -X PUT --data-binary @config.json --unix-socket /var/run/control.unit.sock http://localhost/config

Contact the server on port 80 (HTTP) http://<domain name>:80

:80 is not a required parameter, when explicitly inserted it points to port :80 (HTTP)

But since HTTP connection is not secure the next point shows how to connect certificates and activate HTTPS.

Connecting certificates

Uploading TLS certificates to NGINX UNIT is simple, just like the configuration via API. For this purpose, the received certificates, generated for example with certbot, are bundled into one and transferred as a single file:

cat cert.pem ca.pem key.pem > bundle.pem

Bundle.pem - the final file, which is the certificate to be loaded into the NGINX UNIT. After that we make a request to the Unit to which we pass bundle.pem:

curl -X PUT --data-binary @bundle.pem --unix-socket /var/run/control.unit.sock http://localhost/certificates/bundle

Path to load the certificate /certificates/<name of certificate> Here we already use a PUT request to update the list of certificates. The name of certificate that we used during the bundling does not matter, because we specify a new one when we load it. This is what we will use in our config. Here is an example of such a configuration file:

{
  "listeners": {
      "*:443": { // Using port 443 to activate HTTPS
          "pass": "routes",
          "tls": { // Use of the certificate
              "certificate": "bundle" // The name of the certificate you uploaded
          }
      }
  }
}

Deleting a certificate goes the same way as downloading it, but using DELETE instead of PUT in the request

Collecting logs and statistics

Statistics and health check

By making a GET request to the API you can get information about connections, requests, applications.

curl -X GET --unix-socket /var/run/control.unit.sock http://localhost/status
Example request
Example request

And now a little more detail on each of the keys:

Connections (connections) contains 4 parameters:

  • accepted - The number of connections during the lifetime of the current Nginx Unit socket

  • active - Current number of connections

  • idle - Number of idle connections

  • closed - Number of closed connections during the lifetime of the current Nginx Unit socket.

Requests contains a single total key that displays the total number of requests not related to the web server API, over the lifetime of the socket.

Applications contains information about each application. Example wordpress from the official documentation:

{
    "wp": {
        "processes": {
            "running": 14, // Number of running processes
            "starting": 0, // Starting processes
            "idle": 4 // Idle processes
        },

        "requests": { 
            "active": 10 // Similar to queries, but contains information
        }                // on the application only
    }
}

This is all the statistics that Nginx Unit provides, however it is concise and allows you to monitor everything together and for each application separately.

Bonus

Statistics request
Statistics request

As you can see in the image above, we can offload data from the web server in JSON format, which can be useful for analysis. After that, we can configure CRON on the server, to retrieve data at a given interval.

Logs

By standard, Nginx Unit logs are stored in a file at /var/log/unit.log. This file contains data on startup, errors and information about web server operation. Example:

2023/06/07 09:48:34 [notice] 266515#266515 no modules matching: "/usr/lib/unit/modules/*.unit.so" found
2023/06/07 09:48:34 [info] 266514#266514 controller started
2023/06/07 09:48:34 [notice] 266514#266514 process 266515 exited with code 0
2023/06/07 09:48:34 [info] 266517#266517 router started
2023/06/07 09:48:34 [info] 266517#266517 OpenSSL 3.0.2 15 Mar 2022, 30000020
2023/06/07 09:49:34 [notice] 266514#266514 process 266516 exited with code 0
2023/06/07 09:49:34 [notice] 266514#266514 process 266517 exited with code 0
2023/06/07 09:49:34 [info] 266834#266834 discovery started
2023/06/07 09:49:34 [notice] 266834#266834 no modules matching: "/usr/lib/unit/modules/*.unit.so" found
2023/06/07 09:49:34 [info] 266833#266833 controller started
2023/06/07 09:49:34 [notice] 266833#266833 process 266834 exited with code 0

In this example, nginx unit loads language modules at initialisation, then handles routing.

Problems when working with Nginx Unit

  • Lack of necessary modules, or rather the versions you need. For example, version 1.30.0 does not support PHP 7.4, which is still in active use at the time of writing, so you will have to build manually or use docker containers.

  • Using curl with the -d parameter instead of --data-binary. Here the problem is obvious when loading certificates. Linux newbies may accept the example of using the -d flag to load JSON, but when loading certificates they will encounter a problem and will not understand what is going on.

Conclusion

In conclusion, I can say that using NGINX UNIT lowers the threshold of entry for beginners who want to deploy web applications. It is self-explanatory as it operates with JSON and uses REST API. But that doesn't take away from the fact that Unit is a powerful tool that is still evolving and fills the gaps and fixes the problems of its big brother NGINX web server.

Only registered users can participate in poll. Log in, please.
Next articles
100% Creating the second part of the Nginx Unit with deepening2
50% Creating an article about Nginx Unit, but with the reading level of technical people1
50% Article about practical application of Nginx Unit1
50% To talk about something else1
2 users voted. Nobody abstained.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
Rating0
Comments1

Articles