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:


: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:

  1. Most user requests are handled by index.php regardless of the actual request URI.

  2. 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.


Last modified February 11, 2025