NGINX Unit Greets Autumn 2022 with New Features (a Statistics Engine!) and Exciting Plans

NGINX | October 27, 2022

First things first: it’s been quite a while since we shared news from the NGINX Unit team – these tumultuous times have affected everyone, and we’re no exception. This March, two founding members of the Unit team, Valentin Bartenev and Maxim Romanov, decided to move on to other opportunities after putting years of work and tons of creativity into NGINX Unit. Let’s give credit where credit is due: without them, NGINX Unit wouldn’t be where it is now. Kudos, guys.

Still, our resolve stays strong, as does our commitment to bringing NGINX co‑founder Igor Sysoev’s original aspirations for NGINX Unit to fruition. The arrival of the two newest team members, Alejandro Colomar and Andrew Clayton, has boosted the development effort, so now we have quite a few noteworthy items from NGINX Unit versions 1.25 through 1.28 to share with you.

Observability Is a Thing Now

One of Unit’s key aspirations has always been observability, and version 1.28.0 includes the first iteration of one of the most eagerly awaited features: a statistics engine. Its output is exposed at the new /status API endpoint:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Most of the fields here are self‑descriptive: connections (line 2) and requests (line 9) provide instance‑wide data, whereas the applications object (line 13) mirrors /config/applications, covering processes and requests that specifically concern the application.

Lines 3–6 show the four categories of connections tracked by NGINX Unit: accepted, active, idle, and closed. The categories for processes are running, starting, and idle (lines 16–18). These categories reflect the internal representation of connections and processes, so now you know just as much about them as your server does.

Seems terse? That’s pretty much all there is to know for now. Sure, we’re working to expose more useful metrics; however, you already can query this API from your command line to see what’s going on at your server and even plug the output into a dashboard or your choice for a more fanciful approach. Maybe you don’t have a dashboard? Well, some of our plans include providing a built‑in one, so follow us to see how this plays out.

For more details, see Usage Statistics in the NGINX Unit documentation.

More Variables, More Places to Use Them

The list of variables introduced since version 1.24 is quite extensive and includes $body_bytes_sent, $header_referer, $header_user_agent, $remote_addr, $request_line, $request_uri, $status, and $time_local.

Most of these are rather straightforward, but here are some of the more noteworthy:

  • $request_uri contains the path and query from the requested URI with browser encoding preserved
  • The similarly named $request_line stores the entire request, such as GET /docs/help.html HTTP/1.1, and is intended for logging…
  • As is $status which contains the HTTP response status code

Did you notice? We mentioned responses. Yes, we’re moving into that territory as well: the variables in earlier Unit versions focused on incoming requests, but now we have variables that capture the response properties as well, such as $status and $body_bytes_sent.

Regarding new places to use variables, the first to mention is the new customizable access log format. Want to use JSON in NGINX Unit’s log entries? In addition to specifying a simple path string, the access_log option can be an object that also sets the format of log entries:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Thus, you can go beyond the usual log format any way you like.

A second noteworthy use case for variables is the location value of a route action:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Here we’re using $request_uri to relay the request, including the query part, to the same website over HTTPS.

The chroot option now supports variables just as the share option does, which is only logical:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

NGINX Unit now supports dynamic variables too. Request arguments, cookies, and headers are exposed as variables: for instance, the query string Type=car&Color=red results in two argument variables, $arg_Type and $arg_Color. At runtime, these variables expand into dynamic values; if you reference a non‑existent variable, it is considered empty.

For more details, see Variables in the NGINX Unit documentation.

Extensive Support for the X-Forwarded-* Headers

You asked, and we delivered. Starting in version 1.25.0, NGINX Unit has offered some TLS configuration facilities for its listeners, including a degree of X-Forwarded-* awareness; now, you can configure client IP addresses and protocol replacement in the configuration for your listeners:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Note: This new syntax deprecates the previous client_ip syntax, which will be removed in a future release.

For more details, see IP, Protocol Forwarding in the NGINX Unit documentation.

The Revamped share Option

NGINX Unit version 1.11.0 introduced the share routing option for serving static content. It’s comparable to the root directive in NGINX:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Initially, the share option specified the so‑called document root directory. To determine which file to serve, Unit simply appended the URI from the request to this share path. For example, in response to a simple GET request for /some/file.html, Unit served /path/to/dir/some/file.html. Still, we kept bumping into border cases that required finer control over the file path, so we decided to evolve. Starting with version 1.26.0, the share option specifies the entire path to a shared file rather than just the document root.

You want to serve a specific file? Fine:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Use variables within the path? Cool, not a problem:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

But how do you go about imitating the behavior you’re already used to from NGINX and previous Unit versions? You know, the document root thing that we deemed obsolete a few paragraphs ago? We have a solution.

You can now rewrite configurations like this:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

as follows, appending the requested URI to the path, but explicitly!

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Finally, the share directive now can accept an array of paths, trying them one by one until it finds a file:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

If no file is found, routing passes to a fallback action; if there’s no fallback, the 404 (Not Found) status code is returned.

For more details, see Static Files in the NGINX Unit documentation.

Plans: njs, URI Rewrite, Action Chaining, OpenAPI

As you read this, we’re already at work on the next release; here’s a glimpse of what we have up our sleeves.

First, we’re integrating NGINX Unit with the NGINX JavaScript module (njs), another workhorse project under active development at NGINX. In short, this means NGINX Unit will support invoking JavaScript modules. Consider this:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

After importing the module in NGINX Unit, you’ll be able to do some neat stuff with the configuration:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Also, we’re aiming to introduce something akin to the ever‑popular NGINX rewrite directive:

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

Our plans don’t stop there, though. How about tying NGINX Unit’s routing to the output from the apps themselves (AKA action chaining)?

[@portabletext/react] Unknown block type "codeBlock", specify a component for it in the `components.types` prop

The idea here is that the auth_check app authenticates the incoming request and returns a status code to indicate the result. If authentication succeeds, 200 OK is returned and the request passes on to my_app.

Meanwhile, we’re also working on an OpenAPI specification to define once and for all NGINX Unit’s API and its exact capabilities. Wish us luck, for this is a behemoth undertaking.

If that’s still not enough to satisfy your curiosity, refer to our roadmap for a fine‑grained dissection of our plans; it’s interactive, so any input from you, dear reader, is most welcome.


Share

Related Blog Posts

Automating Certificate Management in a Kubernetes Environment
NGINX | 10/05/2022

Automating Certificate Management in a Kubernetes Environment

Simplify cert management by providing unique, automatically renewed and updated certificates to your endpoints.

Secure Your API Gateway with NGINX App Protect WAF
NGINX | 05/26/2022

Secure Your API Gateway with NGINX App Protect WAF

As monoliths move to microservices, applications are developed faster than ever. Speed is necessary to stay competitive and APIs sit at the front of these rapid modernization efforts. But the popularity of APIs for application modernization has significant implications for app security.

How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh
NGINX | 12/09/2021

How Do I Choose? API Gateway vs. Ingress Controller vs. Service Mesh

When you need an API gateway in Kubernetes, how do you choose among API gateway vs. Ingress controller vs. service mesh? We guide you through the decision, with sample scenarios for north-south and east-west API traffic, plus use cases where an API gateway is the right tool.

Deploying NGINX as an API Gateway, Part 2: Protecting Backend Services
NGINX | 01/20/2021

Deploying NGINX as an API Gateway, Part 2: Protecting Backend Services

In the second post in our API gateway series, Liam shows you how to batten down the hatches on your API services. You can use rate limiting, access restrictions, request size limits, and request body validation to frustrate illegitimate or overly burdensome requests.

New Joomla Exploit CVE-2015-8562
NGINX | 12/15/2015

New Joomla Exploit CVE-2015-8562

Read about the new zero day exploit in Joomla and see the NGINX configuration for how to apply a fix in NGINX or NGINX Plus.

Why Do I See “Welcome to nginx!” on My Favorite Website?
NGINX | 01/01/2014

Why Do I See “Welcome to nginx!” on My Favorite Website?

The ‘Welcome to NGINX!’ page is presented when NGINX web server software is installed on a computer but has not finished configuring

Deliver and Secure Every App
F5 application delivery and security solutions are built to ensure that every app and API deployed anywhere is fast, available, and secure. Learn how we can partner to deliver exceptional experiences every time.
Connect With Us
NGINX Unit Greets Autumn 2022 with New Features (a Statistics Engine!) and Exciting Plans | F5