Today we release NGINX 1.19, the latest version of NGINX Open Source, the most popular web server on the Internet. This release signals the launch of the NGINX 1.19 development branch, following the release of the NGINX 1.18 stable branch last month.
In this blog we discuss the NGINX versioning scheme, look back at what happened during the NGINX 1.17 development cycle, and look forward to what is in store with NGINX 1.19.
NGINX Versioning Explained
At NGINX, we maintain two branches in the NGINX Open Source code repository, named mainline and stable:
- Mainline is the active development branch where the latest features and bug fixes get added. It is denoted by an odd number in the second part of the version number, for example 1.19.0.
- Stable receives fixes for high‑severity bugs, but is not updated with new features. It is denoted by an even number in the second part of the version number, for example 1.18.0.
What It Means to Be “Stable”
For NGINX Open Source, the word “stable” refers to functionality and update frequency, not software quality. The stable branch never receives new functionality during its lifecycle and typically receives just one or two updates, for critical bug fixes.
The stable branch has an annual lifecycle. Every April, we retire the current stable branch, after which no further bug fixes are made. This triggers two events:
- The current mainline branch is forked, to create the next stable branch. The new stable branch inherits all of the bug fixes, features, and other changes that went into the mainline branch during the previous year. Last month, NGINX 1.17.10 was forked to produce NGINX 1.18.0. Note that until the release of the new mainline branch, ”stable” is identical to the current mainline branch, and may include new features that are just days old (that state ends today for the NGINX 1.18 branch).
- The mainline branch gets a “version bump”; that is, the second part of the version number is incremented to the next odd number. Ongoing development continues in the mainline branch, with new releases built from the mainline every four to six weeks. Today marks the first release on the NGINX 1.19 mainline with NGINX 1.19.0.
Which Branch Does NGINX Plus Use?
NGINX Plus, the commercial version of NGINX, is maintained in a separate, private code repository. It is always based on the latest version of NGINX mainline, merged with the additional proprietary features and capabilities in NGINX Plus. At the time of writing, the latest version is NGINX Plus R21, based on NGINX 1.17.10.
Which Branch Should I Use?
We generally recommend using the mainline branch. This is where we commit all new features, performance improvements, and enhancements. We actively test and QA the mainline branch, and as the source of NGINX Plus builds it is completely suitable for production use.
If you are concerned about the overhead of monitoring the mainline branch for new features and bug fixes, then using the stable branch means that you only need to review new functionality once a year, and bug fixes on an infrequent basis.
NGINX 1.17 in Review, AKA What’s New in the NGINX 1.18 Stable Branch
The NGINX 1.17 development cycle introduced some new features and enhancements, including enhancements to request rate and connection limiting in ngx_http_limit_req_module and ngx_http_limit_conn_module respectively, adding an authentication‑delaying directive to ngx_http_core_module, introducing variable support for the
grpc_pass directive and variables that capture the server address and port with the PROXY Protocol, and more. Before we look at the most significant enhancements in more detail, here’s NGINX 1.17, by the numbers:
- 10 mainline releases
- 37 bug fixes
- 11 new features
Enhancements to HTTP Request Rate and Connection Limiting
limit_rate_after directives control the bandwidth (rate in bytes per second) at which NGINX responds to requests. In NGINX 1.17.0 and later, the parameter that sets the rate can be a variable, which enables dynamic control based on attributes of the request. For an example, see Dynamic Bandwidth Control.
NGINX 1.17.1 added dry‑run mode for request‑rate limiting, with the
limit_req_dry_run directive. In dry‑run mode, NGINX Plus doesn’t enforce rate limits, but still tracks the rate of excessive requests in the shared memory zone and writes an entry to the error log for every request that exceeds the configured limit. This enables you more easily to determine which rate limit is appropriate for the traffic patterns at your site. For more details, see Testing Rate Limits in Dry‑Run Mode.
To make dry‑run mode even more useful, NGINX 1.17.6 added the
$limit_req_status variable, which can be included in access log entries to capture the effect of rate limiting on request processing – specifically, whether a request:
- Passed (was forwarded to the backend servers without delay) [
- Was delayed [
- Was rejected [
- Was counted as delayed in dry‑run mode [
- Was counted as rejected in dry‑run mode [
- Passed (was forwarded to the backend servers) [
- Was rejected [
- Was counted as rejected in dry‑run mode [
For a sample configuration, see Enhancements to Connection Limiting.
auth_delay directive (added in NGINX 1.17.10) enables delayed processing of unauthorized requests, with status code
(Unauthorized) returned to the client. This prevents timing attacks when processing access requests. Available authentication methods include:
- A password (when using ngx_http_auth_basic_module)
- The result of a subrequest (available in ngx_http_auth_request_module)
- The presence of a JWT (available in ngx_http_auth_jwt_module)
Variables Support for the
Native support for gRPC traffic was added in NGINX 1.13.10, including the
grpc_pass directive, which specifies the servers to which NGINX passes gRPC requests. In NGINX 1.17.8 we added the ability to include domain names in the server identifier, to support searching among upstream server groups. If the domain name isn’t found, NGINX falls back to using a resolver to identify server addresses.
Additional PROXY Protocol Variables
The PROXY Protocol enables a Layer 4 proxy to provide original client information to the next proxy or load balancer handling the request. This is important for use cases where you need to know the client’s IP address – for example, to limit the number of connections for each client (using the
least_conn directive). This data is available in the
$proxy_protocol_addr variable (HTTP | Stream).
When multiple Layer 4 proxies are deployed, it can be important for NGINX to know the IP address and port of the proxy server the client originally connected to. PROXY Protocol metadata includes this information, and NGINX 1.17.6 added the following variables to the HTTP and Stream modules to capture it:
Note: The variables are populated only if you also include the
proxy_protocol parameter to the
listen directive to enable handling of the PROXY Protocol.
Variables Support Added to
proxy_download_rate directives in the Stream module control the rate at which NGINX reads data from a client or proxied server, respectively. In NGINX 1.17.0 and later, the directives accept a variable parameter, enabling you to define condition‑specific rates.
Added Support for the
ioctl(FIONREAD) System Call
In Linux systems the
ioctl() system call provides the number of bytes readable from the host device. NGINX 1.17.5 added
ioctl(FIONREAD) to prevent looping when data is added to the socket buffer faster than NGINX can read and process it. When the kernel doesn’t provide the number of bytes available, we can use
ioctl(FIONREAD) to get this information from a populated buffer.
Specifying a Named Location in the Perl
In NGINX 1.17.2 and later, the
uri parameter to the
internal_redirect function in the NGINX Perl module can be an escaped URI or a named location.
What’s Coming in NGINX 1.19
The first release on the NGINX 1.19 mainline is coming very soon. NGINX 1.19.0 includes support for QUIC (HTTP/3), the next significant update to the transport protocols for communication between clients and websites, applications, and APIs.