2021

Unit 1.26.1 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

This is a minor bugfix release that aims to eliminate some annoying regressions revealed after the release of Unit 1.26.0 two weeks ago.

Notably, the shared OPcache implementation in that release required introducing some major architectural changes, but our functional tests didn’t catch some regressions caused by these changes. Still, thanks to our active community, the issues were reported shortly after the release, and now we can provide an updated version. We will also improve our functional testing to avoid such regressions in the future.

The most painful and visible one was that sometimes Unit daemon couldn’t completely exit, leaving some zombie processes. However, the second attempt to stop it always succeeded. Also, some DragonFly BSD kernel interfaces are seemingly broken, preventing the Unit daemon from functioning, so we disabled their use when compiling for DragonFly BSD.

Full Changelog

Changes with Unit 1.26.1                                         02 Dec 2021

- Bugfix: occasionally, the Unit daemon was unable to fully terminate;
  the bug had appeared in 1.26.0.

- Bugfix: a prototype process could crash on an application process
  exit; the bug had appeared in 1.26.0.

- Bugfix: the router process crashed on reconfiguration if "access_log"
  was configured without listeners.

- Bugfix: a segmentation fault occurred in the PHP module if chdir() or
  fastcgi_finish_request() was called in the OPcache preloading script.

- Bugfix: fatal errors on DragonFly BSD; the bug had appeared in
  1.26.0.

To know more about the bunch of changes introduced in Unit 1.26 and the roadmap for 1.27, please see the previous announcement: https://mailman.nginx.org/pipermail/unit/2021-November/000288.html

Thank you again for keeping your finger on the pulse, reporting issues, and submitting feature requests via our GitHub issue tracker.


Unit 1.26.0 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

Please read this letter to the end, as it explains some significant changes in the latest version. But first, I have great news for the PHP users: now the interpreter’s OPcache is shared between the processes of an app.

In previous versions, due to an architecture limitation (which imposed strong isolation, much stronger than was sometimes needed), each PHP process had a separate OPcache memory. As a result, with some workloads (especially involving many dynamic processes), performance could degrade because each new process had to warm up the cache after starting. Also, it required more memory because the bytecode of the same PHP scripts was duplicated in each process. Now, all these flaws are finally gone.

Next, we noticed that more and more users use Unit to serve static files, if only because it’s efficient and easy to configure. Modern apps are all dynamic, yes, but at the same time, almost all apps and websites have static resources like images, scripts, styles, fonts, and media files. It’s very important to supply these resources as fast as possible without any delays to smoothen the overall user experience. We take this aspect seriously and continue improving Unit capabilities as a generic static media web server.

This time, all changes are about configuration flexibility. You may know that NGINX has a number of different directives that control static file serving:

  • root
  • alias
  • try_files

Some of these are mutually exclusive, some can be combined, some work differently depending on the location type. That gives the configuration a lot of flexibility but may look a bit complicated. Users kept asking us to provide the same functionality in Unit, but instead of just repeating these, we thought about how we can improve this experience to make it easier to understand without losing flexibility.

Finally, we came up with a solution. In previous versions, we introduced the share directive, very similar to the root directive in NGINX:

{
    "share": "/path/to/dir/"
}

Basically, it specified the so-called document root directory. To determine a file to serve, Unit appended the URI from the request to this share path. For this request:

GET /some/file.html

The above configuration served /path/to/dir/some/file.html.

In simple times, that’s exactly what you want. Still, there are plenty of cases when a different file needs to be served and the requested URI doesn’t match a path. More, you may want to serve a single file for any requests; the so-called one-page apps often utilize such a scheme.

Starting with Unit 1.26.0, the share option specifies the entire path to a shared file rather than just the document root. And yes, the option supports variables, so you can write:

{
    "share": "/www/data/$uri"
}

This occurs only once, after the version update. If you manage your configurations using some scripts and store them somewhere else, make sure to adjust the “share” values there accordingly.

To read more about the new share behavior, check the documentation: https://docs.nginx.com/nginx-unit/configuration/#static-files

Full Changelog

Changes with Unit 1.26.0                                         18 Nov 2021

    *) Change: the "share" option now specifies the entire path to the files
       it serves, rather than a document root directory to be prepended to
       the request URI.

    *) Feature: automatic adjustment of existing configurations to the new
       "share" behavior when updating from previous versions.

    *) Feature: variables support in the "share" option.

    *) Feature: multiple paths in the "share" option.

    *) Feature: variables support in the "chroot" option.

    *) Feature: PHP opcache is shared between application processes.

    *) Feature: request routing by the query string.

    *) Bugfix: the router and app processes could crash when the requests
       limit was reached by asynchronous or multithreaded apps.

    *) Bugfix: established WebSocket connections could stop reading frames
       from the client after the corresponding listener had been
       reconfigured.

    *) Bugfix: fixed building with glibc 2.34, notably Fedora 35.

Other major features that we are preparing for the next release include:

  • Basic statistics API for monitoring Unit instances
  • Various variables for different aspects of request and connection data
  • Customization of access log format with variables
  • Custom variables out of regexp captures on various request parameters
  • Simple request rewrite using variables
  • Command-line tool to simplify the use of Unit’s control socket API

To participate, share your ideas, or discuss new features, you’re welcome to visit Unit’s issue tracker on GitHub: https://github.com/nginx/unit/issues


Unit 1.25.0 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

This one is much awaited not only because the last one occurred quite some time ago, but also because it contains some sought-after features that were requested quite often.

Obtaining The Originating Client IP Address

When Unit operates behind a reverse proxy, it receives all incoming connections from a proxy machine address. As a result, the originating IP address of a client cannot be determined from the IP protocol. To overcome this, a special HTTP request header field can be used to carry the client IP address information over one to several proxies. Such header fields are usually called “X-Forwarded-For”, but variations exist as well (“X-Real-IP”, “X-Remote-Addr”, etc..).

Before, Unit could not use information from such header fields otherwise than just pass them on “as is.” With this release, functionality similar to the real-ip nginx module became available. Now, in any listener object, you can specify a client_ip option, configuring trusted proxy addresses and the header field name, to obtain the client IP address:

{
    "listeners": {
        "*:80": {
            "client_ip": {
                "header": "X-Forwarded-For",
                "recursive": true,
                "source": [
                    "10.0.0.0/8",
                    "150.172.238.0/24"
                ]
            }
        }
    }
}

Unit will use the address obtained from this header to the same effect as if a direct connection was made from the client. For instance, it will be reflected in any logs, used for source address matching in routing, and provided to the application via a relevant request environment (e.g. $_SERVER['REMOTE_ADDR'] in PHP).

See more details in the documentation: https://docs.nginx.com/nginx-unit/configuration/#originating-ip-identification

Control API to Restart Application Processes

Unit dynamic configuration is pretty smart and granular. If it detects no changes to an application during reconfiguration, it won’t touch the application’s processes. However, sometimes our users need to restart a specific application, and the only good way to do that was to intentionally introduce a change to the application’s configuration. Usually, a dummy environment option was used for this:

curl -X PUT -d '"$RANDOM"' --unix-socket /var/run/control.unit.sock \
     /config/applications/<name>/environment/gen

While it worked well, the solution can’t be called elegant; it was more like a workaround. But now, Unit has a special section in the control API that allows restarting any configured application with a basic GET request:

curl --unix-socket /var/run/control.unit.sock \
     /control/applications/<name>/restart

See here for the details of app process management in Unit: https://docs.nginx.com/nginx-unit/configuration/#process-management

Full Changelog

Changes with Unit 1.25.0                                         19 Aug 2021

    *) Feature: client IP address replacement from a specified HTTP header
       field.

    *) Feature: TLS sessions cache.

    *) Feature: TLS session tickets.

    *) Feature: application restart control.

    *) Feature: process and thread lifecycle hooks in Ruby.

    *) Bugfix: the router process could crash on TLS connection open when
       multiple listeners with TLS certificates were configured; the bug had
       appeared in 1.23.0.

    *) Bugfix: TLS connections were rejected for configurations with
       multiple certificate bundles in a listener if the client did not use
       SNI.

    *) Bugfix: the router process could crash with frequent multithreaded
       application reconfiguration.

    *) Bugfix: compatibility issues with some Python ASGI apps, notably
       based on the Starlette framework.

    *) Bugfix: a descriptor and memory leak occurred in the router process
       when an app process stopped or crashed.

    *) Bugfix: the controller or router process could crash if the
       configuration contained a full-form IPv6 in a listener address.

    *) Bugfix: the router process crashed when a request was passed to an
       empty "routes" or "upstreams" using a variable "pass" option.

    *) Bugfix: the router process crashed while matching a request to an
       empty array of source or destination address patterns.

In the meantime, there are several other features currently at different stages of development and implementation:

  • Variable support in the static file serving options
  • Custom variables from regexp captures in the “match” object
  • Simple request rewrites using variables
  • More variables to access request and connection information
  • A statistics API
  • Unit CLI utility tool
  • App prototype processes to reduce memory usage, share the PHP opcache, and improve the handling of apps isolation
  • njs integration
  • .NET Core language module prototype

Unit 1.24.0 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

This one is full of shiny new features. But before I dive into the details, let me introduce our new developers without whom this release wouldn’t be so feature-rich. Please, welcome Zhidao Hong (洪志道) and Oisín Canty.

Zhidao has already been contributing to various nginx open-source projects for years as a community member, and I’m very excited to finally have him on board.

Oisín is a university student who’s very interested in Unit; he joined our dev team as an intern and already shown solid coding skills, curiosity, and attention to details, which is so important to our project. Good job!

Now, back to the features. I’d like to highlight the first of our improvements in serving static media assets.

MIME Type Filtering

Now, you can restrict file serving by MIME type:

{
    "share": "/www/data",
    "types": [ "image/*", "video/*" ]
}

The configuration above allows only files with various video and image extensions, but all other requests will return status code 403.

In particular, this goes well with the fallback option that performs another action if the share returns a 40x error:

{
    "share": "/www/data",
    "types": [ "!application/x-httpd-php" ],

    "fallback": {
        "pass": "applications/php"
    }
}

Here, all requests to existing files other than .php will be served as static content while the rest will be passed to a PHP application.

More examples and documentation snippets are available here: https://docs.nginx.com/nginx-unit/configuration/#mime-filtering

Full Changelog

Changes with Unit 1.24.0                                         27 May 2021

    *) Change: PHP added to the default MIME type list.

    *) Feature: arbitrary configuration of TLS connections via OpenSSL
       commands.

    *) Feature: the ability to limit static file serving by MIME types.

    *) Feature: support for chrooting, rejecting symlinks, and rejecting
       mount point traversal on a per-request basis when serving static
       files.

    *) Feature: a loader for automatically overriding the "http" and
       "websocket" modules in Node.js.

    *) Feature: multiple "targets" in Python applications.

    *) Feature: compatibility with Ruby 3.0.

    *) Bugfix: the router process could crash while closing a TLS
       connection.

    *) Bugfix: a segmentation fault might have occurred in the PHP module if
       fastcgi_finish_request() was used with the "auto_globals_jit" option
       enabled.

Unit 1.24.0 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

This one is full of shiny new features. But before I dive into the details, let me introduce our new developers without whom this release wouldn’t be so feature-rich. Please, welcome Zhidao Hong (洪志道) and Oisín Canty.

Zhidao has already been contributing to various nginx open-source projects for years as a community member, and I’m very excited to finally have him on board.

Oisín is a university student who’s very interested in Unit; he joined our dev team as an intern and already shown solid coding skills, curiosity, and attention to details, which is so important to our project. Good job!

Now, back to the features. I’d like to highlight the first of our improvements in serving static media assets.

MIME Type Filtering

Now, you can restrict file serving by MIME type:

{
    "share": "/www/data",
    "types": [ "image/*", "video/*" ]
}

The configuration above allows only files with various video and image extensions, but all other requests will return status code 403.

In particular, this goes well with the fallback option that performs another action if the share returns a 40x error:

{
    "share": "/www/data",
    "types": [ "!application/x-httpd-php" ],

    "fallback": {
        "pass": "applications/php"
    }
}

Here, all requests to existing files other than .php will be served as static content while the rest will be passed to a PHP application.

More examples and documentation snippets are available here: https://docs.nginx.com/nginx-unit/configuration/#mime-filtering

Full Changelog

Changes with Unit 1.24.0                                         27 May 2021

    *) Change: PHP added to the default MIME type list.

    *) Feature: arbitrary configuration of TLS connections via OpenSSL
       commands.

    *) Feature: the ability to limit static file serving by MIME types.

    *) Feature: support for chrooting, rejecting symlinks, and rejecting
       mount point traversal on a per-request basis when serving static
       files.

    *) Feature: a loader for automatically overriding the "http" and
       "websocket" modules in Node.js.

    *) Feature: multiple "targets" in Python applications.

    *) Feature: compatibility with Ruby 3.0.

    *) Bugfix: the router process could crash while closing a TLS
       connection.

    *) Bugfix: a segmentation fault might have occurred in the PHP module if
       fastcgi_finish_request() was used with the "auto_globals_jit" option
       enabled.

Unit 1.23.0 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

Nowadays, TLS is everywhere, while plain HTTP is almost nonexistent in the global network. We are fully aware of this trend and strive to simplify TLS configuration in Unit as much as possible. Frankly, there’s still much to do, but the introduction of smart SNI certificate selection marks yet another step in this direction.

Perhaps, you already know about Unit’s certificate storage API that uploads certificate bundles to a running instance. Otherwise, if you’re not yet fully informed but still curious, here’s a decent overview: https://docs.nginx.com/nginx-unit/certificates/

Basically, you just upload a certificate chain and a key under some name; after that, you can specify the name (mycert in the example below) with any listening socket to configure it for HTTPS:

{
    "listeners": {
        "*:443": {
            "tls": {
                "certificate": "mycert"
            },
            "pass": "routes"
        }
    }
}

Unit’s API also enables informative introspection of uploaded certificate bundles so you can monitor their validity and benefit from service discovery.

You can also upload any number of certificate bundles to switch between them on the fly without restarting the server. Still, with this release, there are even more options, as you can supply any number of certificate bundle names with a listener socket:

{
    "certificate": [ "mycertA", "mycertB", ... ]
}

For each client, Unit automatically selects a suitable certificate from the list depending on the domain name the client connects to (and therefore supplies via the “Server Name Indication” TLS extension). Thus, you don’t even need to care about matching certificates to server names; Unit handles that for you. As a result, there’s almost no room for a mistake, which spares more time for stuff that matters.

As one can reasonably expect, you can always add more certs, delete them, or edit the cert list on the fly without compromising performance. That’s the Unit way!

Also, plenty of solid bug-fixing work was done by the whole team. See the full change log below:

Full Changelog

Changes with Unit 1.23.0                                         25 Mar 2021

    *) Feature: support for multiple certificate bundles on a listener via
       the Server Name Indication (SNI) TLS extension.

    *) Feature: "--mandir" ./configure option to specify the directory for
       man page installation.

    *) Bugfix: the router process could crash on premature TLS connection
       close; the bug had appeared in 1.17.0.

    *) Bugfix: a connection leak occurred on premature TLS connection close;
       the bug had appeared in 1.6.

    *) Bugfix: a descriptor and memory leak occurred in the router process
       when processing small WebSocket frames from a client; the bug had
       appeared in 1.19.0.

    *) Bugfix: a descriptor leak occurred in the router process when
       removing or reconfiguring an application; the bug had appeared in
       1.19.0.

    *) Bugfix: persistent storage of certificates might've not worked with
       some filesystems in Linux, and all uploaded certificate bundles were
       forgotten after restart.

    *) Bugfix: the controller process could crash while requesting
       information about a certificate with a non-DNS SAN entry.

    *) Bugfix: the controller process could crash on manipulations with a
       certificate containing a SAN and no standard name attributes in
       subject or issuer.

    *) Bugfix: the Ruby module didn't respect the user locale for defaults
       in the Encoding class.

    *) Bugfix: the PHP 5 module failed to build with thread safety enabled;
       the bug had appeared in 1.22.0.

Unit 1.22.0 Released

Hi,

I’m glad to announce a new release of NGINX Unit.

This is our first release of 2021, and it focuses on improving stability. There’s an extensive list of bugfixes, although many occur in rare conditions that have so far been observed only in our test environments. These bugs were caught due to improvements in our continuous functional testing; our QA, Andrei Zeliankou, is always looking to increase the testing coverage and use new techniques to spot various race conditions and leaks, thus improving the quality of each release. This very important work never ends.

IMPORTANT: Changes to Official Linux Packages

Starting with this release, the user and group accounts that run non-privileged Unit processes are changed in our Linux packages:

  • in previous packages: nobody:nobody
  • in 1.22.0 and later: unit:unit

These settings are used to serve static files and run applications if user or group options are not explicitly specified in the app configuration.

Please take a note of the change and update your configuration appropriately before upgrading an existing Unit installation with our official packages: https://docs.nginx.com/nginx-unit/installation/#official-packages

The rationale for this change in our packages was that using nobody by default was very inconvenient while serving static files. You can always override these settings with the --user and --group daemon options in your startup scripts. See here for more details: https://docs.nginx.com/nginx-unit/howto/source/#startup-and-shutdown

IMPORTANT 2: Changes to official Docker images

Another notable change is also related to our official distributions; in this case, it affects our Docker images. Many asked us to provide the most up-to-date versions of language modules in our Docker images, but there was no maintainable way of doing this while still relying on the Debian base image we used before.

Starting with 1.22.0, we stop maintaining images with language modules that use the old Debian base; instead, now we rely on official Docker images for latest language versions: https://docs.nginx.com/nginx-unit/installation/#docker-images

Our images are available at both Docker Hub and Amazon ECR Public Gallery; you can also download them at our website.

Full Changelog

Changes with Unit 1.22.0                                         04 Feb 2021

    *) Feature: the ServerRequest and ServerResponse objects of Node.js
       module are now compliant with Stream API.

    *) Feature: support for specifying multiple directories in the "path"
       option of Python apps.

    *) Bugfix: a memory leak occurred in the router process when serving
       files larger than 128K; the bug had appeared in 1.13.0.

    *) Bugfix: apps could stop processing new requests under high load; the
       bug had appeared in 1.19.0.

    *) Bugfix: app processes could terminate unexpectedly under high load;
       the bug had appeared in 1.19.0.

    *) Bugfix: invalid HTTP responses were generated for some unusual status
       codes.

    *) Bugfix: the PHP_AUTH_USER, PHP_AUTH_PW, and PHP_AUTH_DIGEST server
       variables were missing in the PHP module.

    *) Bugfix: the router process could crash with multithreaded apps under
       high load.

    *) Bugfix: Ruby apps with multithreading configured could crash on start
       under load.

    *) Bugfix: mount points weren't unmounted when the "mount" namespace
       isolation was used; the bug had appeared in 1.21.0.

    *) Bugfix: the router process could crash while removing or
       reconfiguring an app that used WebSocket.

    *) Bugfix: a memory leak occurring in the router process when removing
       or reconfiguring an application; the bug had appeared in 1.19.0.

Last modified February 11, 2025