NGINX.COM
Web Server Load Balancing with NGINX Plus

Summer’s gone, so it’s time to forfeit the halcyon tranquility and get some working attitude on. The NGINX Unit team has recently presented our first two‑digit version, NGINX Unit 1.10.0; let’s page through the recent developments and shed some light on our plans for the future.

Routing Advancements

In our two latest releases, some major effort went into extending the request routing capabilities that were initially introduced in NGINX Unit 1.8.0. Version 1.9.0 included essential support for arguments, headers, and cookies in matching clauses, whereas NGINX Unit 1.10.0 added scheme‑based routing to the mix. A few examples:

"match": {
    "host": "www.example.com",
    "arguments": {
        "mode": ["mobile", "desktop"],
        "ui": "!full"
    }
}

This condition matches queries like www.example.com/?mode=mobile and www.example.com/?mode=desktop&ui=compact, but not www.example/com/?mode=desktop&ui=full.

"match": {
    "headers": [
        {
            "Accept-Encoding": "*gzip*",
            "User-Agent": "Mozilla/5.0*"
        },

        {
            "User-Agent": "curl*"
        }
    ]
}

This clause matches only requests where the User-Agent header is either Mozilla/5.0 (and gzip compression is also applied) or curl.

"match": {
    "host": "example.com",
    "scheme": "https"
}

This condition matches https://example.com, but not http://example.com.

Pattern matching was also extended to allow wildcards in the middle of the match string:

"match": {
    "host": ["eu-*.example.com", "!eu-5.example.com"]
}

This clause happily matches all eu- subdomains of example.com except eu-5.example.com.

Configuration Updates

The config API received some polishing as well. Most importantly, it now supports non‑idempotent POST semantics. In less fancy terms, this means you can append new items to arrays, which do occur in NGINX Unit configuration. For instance, consider this sample output from a curl query to NGINX Unit’s control socket:

# curl --unix-socket /path/to/control.unit.sock http://localhost/config/

{
    "listeners": {
        "*:8000": {
            "pass": "routes"
        }
    },

    "applications": {
        "blogs": {
            "type": "python",
            "module": "wsgi",
            "path": "/www/blogs/"
        }
    },

    "routes": [	
        {
            "match": {
                "host": [
                    "dev1.example.com",
                    "dev2.example.com"
                ]
            },

            "action": {
                "pass": "applications/blogs"
            }
        }
    ]
}

Let’s decipher the JSON: the configuration includes an application called blogs, a routes section that allows access to the app via two hostnames, and a listener that passes incoming requests through the routing engine. Using the POST method, we append a new hostname to the host array:

# curl -X POST -d '"dev3.example.com"' --unix-socket=/path/to/control.unit.sock \
       http://localhost/config/routes/0/match/host/
{
    "success": "Reconfiguration done."
}

Note that all responses from NGINX Unit are also encoded in JSON. Next, I make a curl query to display just the routes section:

# curl --unix-socket /path/to/control.unit.sock http://localhost/config/routes/

[	
    {
        "match": {
            "host": [
                "dev1.example.com",
                "dev2.example.com",
                "dev3.example.com"
            ]
        },

        "action": {
            "pass": "applications/blogs"
        }
    }
]

As you can see, the POST operation appended its payload to the end of the host array. It’s worth mentioning here that NGINX Unit changes only the sections of the configuration that are affected by the update, calculating the difference between the old config and the new on the fly to minimize overhead. Handy!

In other news, we’ve also done away with a few nasty bugs, making config manipulation more reliable.

Application Languages

Most of the latest changes in language support are for Node.js, including a new built‑in WebSocket server implementation in NGINX Unit 1.10.0. To use it, just specify our module as the parameter to the require function instead of the native websocket module:

var webSocketServer = require('unit-http/websocket').server;

In addition, NGINX Unit 1.10.0 adds some axle grease to improve integration with the latest Node.js versions; a few compatibility bugs were fixed as well.

Another significant update to language support is the PHP module’s new ability to parse request URIs into the PATH_INFO environment variable – something many PHP developers have come to rely on. The change might appear tiny, but it makes it easier to run some major apps like NextCloud, as detailed in the shiny new how‑to we’ve provided for your convenience. Oh, and speaking of…

Documentation

Our documentation has been extended significantly in the last few months with various guides and how‑tos in response to your insightful queries, friendly GitHub rants, and reasonable – but misplaced – assumptions about how some features work.

Some of the major updates include a guide to running NGINX Unit in Docker that is accompanied by a sample Dockerfile for each of the supported languages, an end-to-end guide on language module manipulation, and how‑tos for popular apps and frameworks like Catalyst and Redmine (along with the aforementioned NextCloud). There’s more to come – please check the docs once in a while or post your “gotta see this app run on NGINX Unit” ideas on GitHub.

Conclusion

The journey continues, and NGINX Unit is gaining momentum. Our team is steadily growing with new people bringing new ideas, so follow us for more exciting news (which we already have in the works): see the recent updates in the changelog or monitor our GitHub repository to join the discussions and development.

Finally, a few words about future updates. At this moment, we are working hard to bring to life such long‑promised features as WebSocket support for Java, serving static assets, and proxying. Our team is quite serious about making NGINX Unit a really busy little web engine. Stay tuned!

Interested in becoming a full‑time engineer for NGINX? Check our job board.

NGINX Plus subscribers get support for NGINX Unit at no additional charge. Start a free 30‑day trial of NGINX Plus today.

Hero image

Learn how to deploy, configure, manage, secure, and monitor your Kubernetes Ingress controller with NGINX to deliver apps and APIs on-premises and in the cloud.



About The Author

Artem Konev

Senior Technical Writer

About F5 NGINX

F5, Inc. is the company behind NGINX, the popular open source project. We offer a suite of technologies for developing and delivering modern applications. Together with F5, our combined solution bridges the gap between NetOps and DevOps, with multi-cloud application services that span from code to customer.

Learn more at nginx.com or join the conversation by following @nginx on Twitter.