NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
Find a file
Andrew Clayton 6a211e2b74 Wasm: Add the core of initial WebAssembly language module support.
This adds the core of runtime WebAssembly[0] support. Future commits
will enable this in the Unit core and expose the configuration.

This introduces a new src/wasm directory for storing this source.

We are initially using Wasmtime[0] as the WebAssembly runtime, however
this has been designed with the ability to use different runtimes in
mind.

src/wasm/nxt_wasm.[ch] is the main interface to Unit.

src/wasm/nxt_rt_wasmtime.c is the Wasmtime runtime support. This is
nicely insulated from any knowledge of internal Unit workings.

Wasmtime is what loads and runs the Wasm modules.

The Wasm modules can export functions Wasmtime can call and Wasmtime can
export functions that the module can call.

We make use of both. The terminology used is that function exports are
what the Wasm module exports and function imports are what the Wasm
runtime exports to the module.

We currently have four function imports (functions exported by the
runtime to be called by the Wasm module).

1) nxt_wasm_get_init_mem_size

This allows Wasm modules to get the size of the initially allocated
shared memory. This is the size allocated at Unit startup and what the
Wasm modules can assume they have access to (in reality this shared
memory will likely be larger).

The amount of memory allocated at startup is NXT_WASM_MEM_SIZE which as
of this commit is 32MiB.

We do actually allocate NXT_WASM_MEM_SIZE + NXT_WASM_PAGE_SIZE at
startup which is an extra 64KiB (the smallest allocation unit), this is
to allow room for the response structure and so module developers can
just assume they have the full 32MiB for their actual response.

2) nxt_wasm_send_headers

This allows WASM modules to send their headers.

3) nxt_wasm_send_response

This allows WASM modules to send their response.

4) nxt_wasm_response_end

This allows WASM modules to inform Unit they have finished sending their
response. This calls nxt_unit_request_done()

Then there are currently up to eight functions that a module can export.
Three of which are required. These function can be named anything. I'll
use the Unit configuration names to refer to them

1) request_handler

The main driving function. This may be called multiple times for a
single HTTP request if the request is larger than the shared memory.

2) malloc_handler

Used to allocate a chunk of memory at language module startup. This
memory is allocated from the WASM modules address space and is what is
sued for communicating between the WASM module (the guest) and Unit (the
host).

3) free_handler

Used to free the memory from above at language module shutdown.

Then there are the following optional handlers

1) module_init_handler

If set, called at language module startup.

2) module_end_handler

If set, called at language module shutdown.

3) request_init_handler

If set, called at the start of request. Called only once per HTTP
request.

4) request_end_handler

If set, called once all of a request has been sent to the WASM module.

5) response_end_handler

If set, called at the end of a request, once the WASM module has sent
all its headers and data.

32bits

We currently support 32bit WASM modules, I.e wasm32-wasi. Newer version
of clang, 13+[2], do seem to have support for wasm64 as a target (which
uses a LP64 model). However it's not entirely clear if the WASI SDK
fully supports[3] this and by extension WASI libc/wasi-sysroot.

64bit support is something than can be explored more thoroughly in the
future.

As such in structures that are used to communicate between the host and
guest we use 32bit ints. Even when a single byte might be enough. This
is to avoid issues with structure layout differences between a 64bit
host and 32bit guest (I.e WASM module) and the need for various bits of
structure padding depending on host architecture. Instead everything is
4-byte aligned.

[0]: <https://webassembly.org/>
[1]: <https://wasmtime.dev/>
[2]: <https://reviews.llvm.org/rG670944fb20b226fc22fa993ab521125f9adbd30a>
[3]: <https://github.com/WebAssembly/wasi-sdk/issues/185>

Reviewed-by: Alejandro Colomar <alx@nginx.com>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
2023-08-17 13:09:14 +01:00
auto HTTP: controlling response headers support. 2023-08-09 14:37:16 +08:00
docs HTTP: controlling response headers support. 2023-08-09 14:37:16 +08:00
go Tests: using modules in Go. 2022-01-10 16:07:31 +03:00
pkg contrib: updated njs to 0.8.0. 2023-07-11 11:40:41 -07:00
src Wasm: Add the core of initial WebAssembly language module support. 2023-08-17 13:09:14 +01:00
test Tests: added tests for response header variables. 2023-07-11 15:51:53 +01:00
tools Tools: setup-unit: ctl: added "edit" subcommand. 2023-06-30 14:35:59 +02:00
.gitattributes Set git diff driver for C source code files. 2022-10-26 01:23:02 +01:00
.gitignore Added .gitignore. 2022-05-03 12:41:36 +02:00
.hgignore Added .hgignore file. 2020-09-18 19:37:56 +01:00
.hgtags Unit 1.30.0 release. 2023-05-10 17:44:20 +01:00
.mailmap Using names in .mailmap. 2023-05-21 01:06:26 +02:00
CHANGES Added version 1.30.0 CHANGES. 2023-05-10 16:53:01 +01:00
CODE_OF_CONDUCT.md Adding the NGINX Code of Conduct to the repo. 2023-03-07 13:05:41 +00:00
configure Auto: mirroring installation structure in build tree. 2023-03-29 00:41:08 +02:00
CONTRIBUTING.md Adding GitHub-styled README and CONTRIBUTING files in Markdown. 2022-05-13 17:13:23 +01:00
LICENSE Added LICENSE and NOTICE files. 2017-09-06 18:26:37 +03:00
NOTICE Updated copyright notice. 2023-05-24 16:27:24 +01:00
README.md Update README.md for Docker Official Image. 2023-08-01 16:06:36 +02:00
SECURITY.txt Added security.txt. 2022-11-24 15:06:54 +00:00
version Version bump. 2023-05-24 16:24:42 +01:00

NGINX Unit

Universal Web App Server

NGINX Unit Logo

NGINX Unit is a lightweight and versatile open-source server that has two primary capabilities:

  • serves static media assets,
  • runs application code in seven languages.

Unit compresses several layers of the modern application stack into a potent, coherent solution with a focus on performance, low latency, and scalability. It is intended as a universal building block for any web architecture regardless of its complexity, from enterprise-scale deployments to your pet's homepage.

Its native RESTful JSON API enables dynamic updates with zero interruptions and flexible configuration, while its out-of-the-box productivity reliably scales to production-grade workloads. We achieve that with a complex, asynchronous, multithreading architecture comprising multiple processes to ensure security and robustness while getting the most out of today's computing platforms.

Quick Installation

macOS

$ brew install nginx/unit/unit

For details and available language packages, see the docs.

Docker

$ docker pull unit

For a description of image tags, see the docs.

Amazon Linux, Fedora, RedHat

$ wget https://raw.githubusercontent.com/nginx/unit/master/tools/setup-unit && chmod +x setup-unit
# ./setup-unit repo-config && yum install unit
# ./setup-unit welcome

For details and available language packages, see the docs.

Debian, Ubuntu

$ wget https://raw.githubusercontent.com/nginx/unit/master/tools/setup-unit && chmod +x setup-unit
# ./setup-unit repo-config && apt install unit
# ./setup-unit welcome

For details and available language packages, see the docs.

Running a Hello World App

Unit runs apps in a variety of languages. Let's consider a basic example, choosing PHP for no particular reason.

Suppose you saved a PHP script as /www/helloworld/index.php:

<?php echo "Hello, PHP on Unit!"; ?>

To run it on Unit with the unit-php module installed, first set up an application object. Let's store our first config snippet in a file called config.json:

{
    "helloworld": {
        "type": "php",
        "root": "/www/helloworld/"
    }
}

Saving it as a file isn't necessary, but can come in handy with larger objects.

Now, PUT it into the /config/applications section of Unit's control API, usually available by default via a Unix domain socket:

# curl -X PUT --data-binary @config.json --unix-socket  \
       /path/to/control.unit.sock http://localhost/config/applications

{
	"success": "Reconfiguration done."
}

Next, reference the app from a listener object in the /config/listeners section of the API. This time, we pass the config snippet straight from the command line:

# curl -X PUT -d '{"127.0.0.1:8000": {"pass": "applications/helloworld"}}'  \
       --unix-socket /path/to/control.unit.sock http://localhost/config/listeners
{
    "success": "Reconfiguration done."
}

Now Unit accepts requests at the specified IP and port, passing them to the application process. Your app works!

$ curl 127.0.0.1:8080

      Hello, PHP on Unit!

Finally, query the entire /config section of the control API:

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

Unit's output should contain both snippets, neatly organized:

{
    "listeners": {
        "127.0.0.1:8080": {
            "pass": "applications/helloworld"
        }
    },

    "applications": {
        "helloworld": {
            "type": "php",
            "root": "/www/helloworld/"
        }
    }
}

For full details of configuration management, see the docs.

OpenAPI Specification

Our OpenAPI specification aims to simplify configuring and integrating NGINX Unit deployments and provide an authoritative source of knowledge about the control API.

Although the specification is still in the early beta stage, it is a promising step forward for the NGINX Unit community. While working on it, we kindly ask you to experiment and provide feedback to help improve its functionality and usability.

Community

  • The go-to place to start asking questions and share your thoughts is our Slack channel.

  • Our GitHub issues page offers space for a more technical discussion at your own pace.

  • The project map on GitHub sheds some light on our current work and plans for the future.

  • Our official website may provide answers not easily found otherwise.

  • Get involved with the project by contributing! See the contributing guide for details.

  • To reach the team directly, subscribe to the mailing list.

  • For security issues, email us, mentioning NGINX Unit in the subject and following the CVSS v3.1 spec.