2020
Unit 1.21.0 Released
Hi,
I’m glad to announce a new release of NGINX Unit.
Our two previous releases were thoroughly packed with new features and capabilities, but Unit 1.21.0 isn’t an exception either. This is our third big release in a row, with only six weeks since the previous one!
Perhaps, the most notable feature of this release is the support for multithreaded request handling in application processes. Now, you can fine-tune the number of threads used for request handling in each application process; this improves scaling and optimizes memory usage.
As a result, your apps can use a combination of multiple processes and multiple threads per each process for truly dynamic scaling; the feature is available for any Java, Python, Perl, or Ruby apps out of the box without any need to update their code.
Moreover, if you make use of ASGI support in Unit (introduced in the previous release), each thread of each process of your application can run asynchronously.
To configure the number of threads per process, use the threads
option
of the application object: https://docs.nginx.com/nginx-unit/configuration/#applications
Yet another cool feature is the long-awaited support for regular expressions. In Unit, they enable granular request filtering and routing via our compound matching rules; now, with PCRE syntax available, your request matching capabilities are limited only by your imagination. For details and examples, see our documentation: https://docs.nginx.com/nginx-unit/configuration/#routes
Full Changelog
Changes with Unit 1.21.0 19 Nov 2020
*) Change: procfs is mounted by default for all languages when "rootfs"
isolation is used.
*) Change: any characters valid according to RFC 7230 are now allowed in
HTTP header field names.
*) Change: HTTP header fields with underscores ("_") are now discarded
from requests by default.
*) Feature: optional multithreaded request processing for Java, Python,
Perl, and Ruby apps.
*) Feature: regular expressions in route matching patterns.
*) Feature: compatibility with Python 3.9.
*) Feature: the Python module now supports ASGI 2.0 legacy applications.
*) Feature: the "protocol" option in Python applications aids choice
between ASGI and WSGI.
*) Feature: the fastcgi_finish_request() PHP function that finalizes
request processing and continues code execution without holding onto
the client connection.
*) Feature: the "discard_unsafe_fields" HTTP option that enables
discarding request header fields with irregular (but still valid)
characters in the field name.
*) Feature: the "procfs" and "tmpfs" automount isolation options to
disable automatic mounting of eponymous filesystems.
*) Bugfix: the router process could crash when running Go applications
under high load; the bug had appeared in 1.19.0.
*) Bugfix: some language dependencies could remain mounted after using
"rootfs" isolation.
*) Bugfix: various compatibility issues in Java applications.
*) Bugfix: the Java module built with the musl C library couldn't run
applications that use "rootfs" isolation.
Also, packages for Ubuntu 20.10 “Groovy” are available in our repositories: https://docs.nginx.com/nginx-unit/installation/#ubuntu-2010
Thanks to Sergey Osokin, the FreeBSD port of Unit now provides an almost exhaustive set of language modules: https://www.freshports.org/www/unit/
We encourage you to follow our roadmap on GitHub, where your ideas and requests are always more than welcome: https://github.com/orgs/nginx/projects/1
Unit 1.20.0 Released
Hi,
I’m glad to announce a new release of NGINX Unit.
It is yet another big release, featuring ASGI support for Python and a long list of other improvements and bug fixes.
ASGI 3.0 is a modern standardized interface that enables writing natively asynchronous web applications making use of the async/await feature available in latest versions of Python. Now, Unit fully supports it along with WSGI. Even more, Unit automatically detects the interface your Python app is using (ASGI or WSGI); the configuration experience remains the same, though. Also, our take on ASGI relies on Unit’s native high-performance capabilities to implement WebSockets.
To learn more about the new feature, check out the documentation: https://docs.nginx.com/nginx-unit/configuration/#python
In addition, we’ve prepared for you a couple of howtos on configuring popular ASGI-based frameworks with Unit:
Finally, we’ve updated the Django howto to include the ASGI alternative.
Full Changelog
Changes with Unit 1.20.0 08 Oct 2020
*) Change: the PHP module is now initialized before chrooting; this
enables loading all extensions from the host system.
*) Change: AVIF and APNG image formats added to the default MIME type
list.
*) Change: functional tests migrated to the pytest framework.
*) Feature: the Python module now fully supports applications that use
the ASGI 3.0 server interface.
*) Feature: the Python module now has a built-in WebSocket server
implementation for applications, compatible with the HTTP & WebSocket
ASGI Message Format 2.1 specification.
*) Feature: automatic mounting of an isolated "/tmp" file system into
chrooted application environments.
*) Feature: the $host variable contains a normalized "Host" request
value.
*) Feature: the "callable" option sets Python application callable
names.
*) Feature: compatibility with PHP 8 RC 1. Thanks to Remi Collet.
*) Feature: the "automount" option in the "isolation" object allows to
turn off the automatic mounting of language module dependencies.
*) Bugfix: "pass"-ing requests to upstreams from a route was broken; the
bug had appeared in 1.19.0. Thanks to 洪志道 (Hong Zhi Dao) for
discovering and fixing it.
*) Bugfix: the router process could crash during reconfiguration.
*) Bugfix: a memory leak occurring in the router process; the bug had
appeared in 1.18.0.
*) Bugfix: the "!" (non-empty) pattern was matched incorrectly; the bug
had appeared in 1.19.0.
*) Bugfix: fixed building on platforms without sendfile() support,
notably NetBSD; the bug had appeared in 1.16.0.
I would very much like to highlight one of these changes. Perhaps the least noticeable, it is still important for the entire project: our functional tests moved to a more feature-rich pytest framework from the native Python unittest module that we’ve used previously. This change should enable us to write more sophisticated tests, boosting the overall quality of our future releases.
All in all, this is a genuinely solid release, but I’m still more excited about the things yet to come. Yes, even more great features are coming our way very shortly! Right now, we are tinkering with route matching patterns to support regular expressions; working on keepalive connection caching; adding multithreading to application modules; and finally, fabricating the metrics API!
We encourage you to follow our roadmap on GitHub, where your ideas and requests are always more than welcome: https://github.com/orgs/nginx/projects/1
Unit 1.19.0 Released
Hi,
I’m always happy to announce a new release of NGINX Unit, but this one’s BIG. Besides the varied features and bugfixes, some breakthrough improvements were made under the hood.
As you may know, Unit uses an advanced architecture that relies on dedicated processes to serve different roles in request processing. The process that handles client connections is the router. It uses asynchronous threads (one per CPU core) to accept new connections and send or receive data over already established connections in a non-blocking manner. For security and scalability, all applications run as separate processes over which you have a degree of control: https://docs.nginx.com/nginx-unit/configuration/#process-management
To talk to application processes, relay requests for actual processing, and obtain their responses, the router process uses an elaborate mechanism of inter-process communication (IPC) based on shared memory segments. The general idea is to avoid copying data between processes and minimize overhead, potentially achieving almost zero-latency application interaction.
Our first implementation of this protocol used a complex algorithm to distribute requests between processes, heavily utilizing Unix socket pairs to pass synchronization control messages. In practice, this turned out rather sub-optimal due to lots of extra syscalls and overt complexity. Also, the push semantics became a serious limitation that prevented us from efficiently handling asynchronous applications.
Thus, we stepped back a bit at the end of the last year to meticulously reconsider our approach to IPC, and now this tremendous work finally sees the light of day with the release of Unit version 1.19.0. Maintaining the progress achieved while working with shared memory segments, the protocol now is enhanced to bring the number of syscalls almost to zero under heavy load. We have also changed the request distribution semantics. Now, instead of pushing requests to application processes using a complex router process algorithm, we make application processes pull requests out of a shared queue anytime they’re ready. This enables implementing async interfaces in applications in the most effective manner.
Relying on this new approach to IPC, we shall be able to improve the performance of Go and Node.js modules in the upcoming releases, also introducing multithreading and new interfaces, such as ASGI in Python.
We are obsessed over performance and will continue optimizing Unit to make it the best and brightest in every aspect.
As for the other features of the release, there’s an improvement in proxying: now it speaks HTTP/1.1 and accepts chunked responses from backends.
Moreover, request matching rules were also upgraded to enable more complex
wildcard patterns like */some/*/path/*.php*
.
Finally, we have introduced our first configuration variables. They are a small bunch at the moment, but that’s to change. In a while, variables shall be sufficiently diversified and will be available in more and more options.
Full Changelog
Changes with Unit 1.19.0 13 Aug 2020
*) Feature: reworked IPC between the router process and the applications
to lower latencies, increase performance, and improve scalability.
*) Feature: support for an arbitrary number of wildcards in route
matching patterns.
*) Feature: chunked transfer encoding in proxy responses.
*) Feature: basic variables support in the "pass" option.
*) Feature: compatibility with PHP 8 Beta 1. Thanks to Remi Collet.
*) Bugfix: the router process could crash while passing requests to an
application under high load.
*) Bugfix: a number of language modules failed to build on some systems;
the bug had appeared in 1.18.0.
*) Bugfix: time in error log messages from PHP applications could lag.
*) Bugfix: reconfiguration requests could hang if an application had
failed to start; the bug had appeared in 1.18.0.
*) Bugfix: memory leak during reconfiguration.
*) Bugfix: the daemon didn't start without language modules; the bug had
appeared in 1.18.0.
*) Bugfix: the router process could crash at exit.
*) Bugfix: Node.js applications could crash at exit.
*) Bugfix: the Ruby module could be linked against a wrong library
version.
Also, official packages for Fedora 32 are available now: https://docs.nginx.com/nginx-unit/installation/#fedora
And if you’d like to know more about the features introduced recently in the previous release, see the blog posts:
- NGINX Unit 1.18.0 Adds Filesystem Isolation and Other Enhancements
- Filesystem Isolation in NGINX Unit
:orphan:
Unit 1.18.0 Released
Hi,
I’m glad to announce a new release of NGINX Unit.
This release includes a few internal routing improvements that simplify some
configurations and a new isolation option for chrooting application processes
called rootfs
.
Changes with Unit 1.18.0 28 May 2020
*) Feature: the "rootfs" isolation option for changing root filesystem
for an application.
*) Feature: multiple "targets" in PHP applications.
*) Feature: support for percent encoding in the "uri" and "arguments"
matching options and in the "pass" option.
Also, our official packages for the recently released Ubuntu 20.04 (Focal Fossa) are available now: https://docs.nginx.com/nginx-unit/installation/#ubuntu
At least two of the features in this release deserve special attention.
Changing The Root Filesystem
Security is our top priority, so let’s look closer at the rootfs
option first.
The coolest thing about it is that it’s not just a simple chroot()
system call as some may expect. It’s not a secret that chroot()
is
not intended for security purposes, and there’s plenty of ways for an attacker
to get out of the chrooted directory (just check “man 2 chroot”). That’s why
on modern systems Unit can use pivot_root()
with the mount
namespace isolation enabled, which is way more secure and pretty similar to
putting your application in an individual container.
Also, our goal is to make any security option as easy to use as possible. In this case, Unit automatically tries to mount all the necessary language-specific dependencies inside a new root, so you won’t need to care about them. Currently, this capability works for selected languages only, but the support will be extended in the next releases.
For more information and examples of rootfs
usage, check the
documentation: https://docs.nginx.com/nginx-unit/configuration/#process-isolation
Now to the second feature…
Multiple PHP Application “Targets”
The other major update in this release is called targets
, aiming to
simplify configuration for many PHP applications. Perhaps, it is best
illustrated by an example: WordPress. This is one of many applications that
use two different addressing schemes:
-
Most user requests are handled by
index.php
regardless of the actual request URI. -
Administration interface and some components rely on direct requests to specific
.php
scripts named in the URI.
Earlier, users had to configure two Unit applications to handle this disparity:
{
"wp_index": {
"type": "php",
"user": "wp_user",
"group": "wp_user",
"root": "/path/to/wordpress/",
"script": "index.php"
},
"wp_direct": {
"type": "php",
"user": "wp_user",
"group": "wp_user",
"root": "/path/to/wordpress/"
}
}
The first app directly executes the .php
scripts named by the URI,
whereas the second one passes all requests to index.php
.
Now, you can use targets
instead:
{
"wp": {
"type": "php",
"user": "wp_user",
"group": "wp_user",
"targets": {
"index": {
"root": "/path/to/wordpress/",
"script": "index.php"
},
"direct": {
"root": "/path/to/wordpress/"
}
}
}
}
The complete example is available in our WordPress howto: https://docs.nginx.com/nginx-unit/howto/wordpress/
You can configure as many targets
in one PHP application as you want,
routing requests between them using various sophisticated request matching
rules.
Check our website to know more about the new option: https://docs.nginx.com/nginx-unit/configuration#targets
To learn more about request matching rules: https://docs.nginx.com/nginx-unit/configuration/#matching-conditions
Finally, see here for more howtos: https://docs.nginx.com/nginx-unit/howto/
We have plenty of them, covering many popular web applications and frameworks, but if your favorite one is still missing, let us know by opening a ticket here: https://github.com/nginx/unit-docs/issues
To keep the finger on the pulse, refer to our further plans in the roadmap here: https://github.com/orgs/nginx/projects/1
:orphan:
Unit 1.17.0 Released
Hi,
I’m glad to announce a new release of NGINX Unit.
In addition to improved stability, this release introduces two handy features.
The first one is configured using the return
and location
options of the action object. It can be used to immediately generate a simple
HTTP response with an arbitrary status - for example, to deny access to some
resources:
{
"match": {
"uri": "*/.git/*"
},
"action": {
"return": 403
}
}
Or, you can redirect a client to another resource:
{
"match": {
"host": "example.org"
},
"action": {
"return": 301,
"location": "http://www.example.org"
}
}
See the documentation for a detailed description of routing: https://docs.nginx.com/nginx-unit/configuration/#routes
The second new feature of the release is mostly syntax sugar rather than new functionality. Now, you can specify servers’ weights in an upstream group using fractional numbers.
Say, you have a bunch of servers and want one of them to receive half as many requests as the others for some reason. Previously, the only way to achieve that was to double the weights of all the other servers:
{
"192.168.0.101:8080": {
"weight": 2
},
"192.168.0.102:8080": {
"weight": 2
},
"192.168.0.103:8080": {},
"192.168.0.104:8080": {
"weight": 2
}
}
Using fractional weights, you can perform the update much easier by altering the weight of the server in question:
{
"192.168.0.101:8080": {},
"192.168.0.102:8080": {},
"192.168.0.103:8080": {
"weight": 0.5
},
"192.168.0.104:8080": {}
}
For details of server groups, see here: https://docs.nginx.com/nginx-unit/configuration/#proxying
Changes with Unit 1.17.0 16 Apr 2020
*) Feature: a "return" action with optional "location" for immediate
responses and external redirection.
*) Feature: fractional weights support for upstream servers.
*) Bugfix: accidental 502 "Bad Gateway" errors might have occurred in
applications under high load.
*) Bugfix: memory leak in the router; the bug had appeared in 1.13.0.
*) Bugfix: segmentation fault might have occurred in the router process
when reaching open connections limit.
*) Bugfix: "close() failed (9: Bad file descriptor)" alerts might have
appeared in the log while processing large request bodies; the bug
had appeared in 1.16.0.
*) Bugfix: existing application processes didn't reopen the log file.
*) Bugfix: incompatibility with some Node.js applications.
*) Bugfix: broken build on DragonFly BSD; the bug had appeared in
1.16.0.
Please also see a blog post about the new features of our two previous releases: https://www.nginx.com/blog/nginx-unit-1-16-0-now-available/
To keep the finger on the pulse, refer to our further plans in the roadmap here: https://github.com/orgs/nginx/projects/1
Unit 1.16.0 Released
Hi,
I’m glad to announce a new release of NGINX Unit.
Note:
To all Unit package maintainers: please don’t miss the new--tmp
configure option. It specifies the directory where the Unit daemon stores temporary files (i.e. large request bodies) at runtime.
In this release, we continue improving the functionality related to proxying and static media asset handling.
Now, the new upstreams
object enables creating server groups for
weighted round-robin load balancing:
{
"listeners": {
"*:80": {
"pass": "upstreams/rr-lb"
}
},
"upstreams": {
"rr-lb": {
"servers": {
"192.168.0.100:8080": {},
"192.168.0.101:8080": {
"weight": 2
}
}
}
}
}
See the docs for details: https://docs.nginx.com/nginx-unit/configuration/#configuration-upstreams
So far, it’s rather basic, but many more proxying and load-balancing features are planned for future releases.
By its design, the new fallback
option is somewhat similar to the
try_files
directive in nginx
. It allows proceeding to
another action if a file isn’t available:
{
"share": "/data/www/",
"fallback": {
"pass": "applications/php"
}
}
In the example above, an attempt is made first to serve a request
with a file from the /data/www/
directory. If there’s no such
file, the request is passed to the php
application.
Also, you can chain such fallback actions:
{
"share": "/data/www/",
"fallback": {
"share": "/data/cache/",
"fallback": {
"proxy": "http://127.0.0.1:9000"
}
}
}
More info: https://docs.nginx.com/nginx-unit/configuration/#configuration-fallback
Finally, configurations you upload can use line (//
) and block
(/* */
) comments. Now, Unit doesn’t complain; instead, it strips them
from the JSON payload. This comes in handy if you store your configuration in
a file and edit it manually.
Changes with Unit 1.16.0 12 Mar 2020
*) Feature: basic load-balancing support with round-robin.
*) Feature: a "fallback" option that performs an alternative action if a
request can't be served from the "share" directory.
*) Feature: reduced memory consumption by dumping large request bodies
to disk.
*) Feature: stripping UTF-8 BOM and JavaScript-style comments from
uploaded JSON.
*) Bugfix: negative address matching in router might work improperly in
combination with non-negative patterns.
*) Bugfix: Java Spring applications failed to run; the bug had appeared
in 1.10.0.
*) Bugfix: PHP 7.4 was broken if it was built with thread safety
enabled.
*) Bugfix: compatibility issues with some Python applications.
To keep the finger on the pulse, see our further plans in the roadmap here: https://github.com/orgs/nginx/projects/1
Also, good news for macOS users! Now, there’s a Homebrew tap for Unit: https://docs.nginx.com/nginx-unit/installation/#homebrew
Unit 1.15.0 Released
Hi,
I’m glad to announce a new release of NGINX Unit.
This is mostly a bugfix release that eliminates a few nasty issues. Also, it addresses incompatibilities caused by a minor API change in the recently released major version of Ruby.
Changes with Unit 1.15.0 06 Feb 2020
*) Change: extensions of dynamically requested PHP scripts were
restricted to ".php".
*) Feature: compatibility with Ruby 2.7.
*) Bugfix: segmentation fault might have occurred in the router process
with multiple application processes under load; the bug had appeared
in 1.14.0.
*) Bugfix: receiving request body over TLS connection might have
stalled.
More features are planned for the next release that is expected in the
beginning of March. Among them are basic load balancing in the proxy module
and try_files
-like functionality for more sophisticated request
routing.