Editor – This post has been updated to use the refactored HTTP request object (
- Validating Request Bodies in “Deploying NGINX Plus as an API Gateway, Part 2: Protecting Backend Services”
- Using Client Certificates to Authenticate MQTT Clients in “NGINX Plus for the IoT: Encrypting and Authenticating MQTT Traffic”
- Generating custom log formats with values not available from regular NGINX variables
- Implementing new load‑balancing algorithms
- Parsing TCP/UDP protocols for application‑level sticky sessions
- Inspecting and modifying the body of HTTP requests and responses (already supported for TCP/UDP traffic)
- Writing authentication handlers for HTTP requests (already supported for TCP/UDP traffic)
- Reading and writing files
The NGINX community has created several programmatic extensions over the years. At the time of writing, Lua is the most popular of these; it’s available as a module for NGINX and a certified third‑party module for NGINX Plus. The Lua module and add‑on libraries provide deep integration with the NGINX core and a rich set of functionality, including a driver for Redis.
Lua is a powerful scripting language. It, however, remains fairly niche in terms of adoption and is not typically found in the “skillset toolbox” of the frontend developer or DevOps engineer.
Runtime environment lives and dies with the request
Non‑blocking code execution
Implement only the language support that we need
Close integration with request‑processing phases
Processing Phase HTTP Module Stream Module
Access– Network connection access control
Pre-read– Read/write body
Filter– Read/write body during proxy
Content– Send response to client
Log / Variables– Evaluated on demand
- Includes the request headers sent by the client
- Includes the response headers returned by the backend
- Uses key‑value pairs for efficient ingestion into and searching with log processing tools such as the ELK Stack (now called Elastic Stack), Graylog, and Splunk
The NGINX configuration for this example is extremely simple.
js_set directive defines a new NGINX variable,
log_format directive defines a new format called kvpairs which writes each log line with the value of
server block defines a simple HTTP reverse proxy that forwards all requests to https://www.example.com. The
access_log directive specifies that all requests will be logged with the kvpairs format.
kvHeaders– A support function that converts the
headersobject to a string of key‑value pairs. Support functions must be declared before the function that calls them.
kvAccessLog– The function referenced by the
js_setdirective on line 2 of header_logging.conf. It receives an object argument (
As can be seen in the
kvAccessLog function, its return value is what is passed to the
js_set is executed when the value of the variable is required. In this example,
$access_log_with_headers is used in the
log_format directive and so
kvAccessLog() is executed at log time. Variables used as part of
in. prefix and response headers with the
$ curl http://127.0.0.1/ $ tail --lines=1 /var/log/nginx/access_headers.log 2017-03-14T14:36:53+00:00 client=127.0.0.1 method=GET uri=/ status=200 in.Host=127.0.0.1 in.User-Agent=curl/7.47.0 in.Accept=*/* out.Cache-Control=max-age=604800 out.Etag=x22359670651+identx22 out.Expires='Tue, 21 Mar 2017 14:36:53 GMT' out.Last-Modified='Fri, 09 Aug 2013 23:54:35 GMT' out.Vary=Accept-Encoding out.X-Cache=HIT
Install the prebuilt package.
For Ubuntu and Debian systems:
$ sudo apt-get install nginx-module-njs
For RedHat, CentOS, and Oracle Linux systems:
$ sudo yum install nginx-module-njs
Enable the module by including a
load_moduledirective for it in the top‑level ("main") context of the nginx.conf configuration file (not in the
load_module modules/ngx_http_js_module.so; load_module modules/ngx_stream_js_module.so;
$ sudo nginx -s reload
If you prefer to compile an NGINX module from source:
- Copy the module binaries (ngx_http_js_module.so, ngx_stream_js_module.so) to the modules subdirectory of the NGINX root (usually /etc/nginx/modules).