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:
$ curl --unix-socket /var/run/control.unit.sock http://localhost/status
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:
closed. The categories for processes are
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
Most of these are rather straightforward, but here are some of the more noteworthy:
$request_uricontains the path and query from the requested URI with browser encoding preserved
- The similarly named
$request_linestores the entire request, such as
HTTP/1.1, and is intended for logging…
- As is
$statuswhich 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
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:
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
Here we’re using
$request_uri to relay the request, including the query part, to the same website over HTTPS.
chroot option now supports variables just as the
share option does, which is only logical:
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_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
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:
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.
NGINX Unit version 1.11.0 introduced the
share routing option for serving static content. It’s comparable to the
root directive in NGINX:
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:
Use variables within the path? Cool, not a problem:
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:
as follows, appending the requested URI to the path, but explicitly!
share directive now can accept an array of paths, trying them one by one until it finds a file:
If no file is found, routing passes to a
fallback action; if there’s no
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.
After importing the module in NGINX Unit, you’ll be able to do some neat stuff with the configuration:
Also, we’re aiming to introduce something akin to the ever‑popular NGINX
Our plans don’t stop there, though. How about tying NGINX Unit’s routing to the output from the apps themselves (AKA
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,
OK is returned and the request passes on to
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.