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.