Nginx Unit

CMD_UNIT: Nginx Unit for other handlers

This feature is part of the "DirectAdmin Pro Pack".

Nginx Unit

Nginx Unit, the polyglot app server, is capable of serving static content and functioning as a reverse proxy. There is no need for several different implementations to meet your clients' requests with Nginx Unit. With multiple languanges and multiple versions supported, it can run them all! Nginx Unitopen in new window allows for mid-level processing, after the webserver accepts the requests, but can redirect the request with immense control, before it actually hits the disk.

It has no configuration file. The configuration is managed via a REST API using JSON. Curl commands can be utilized to interact with the API, but this is not required with DirectAdmin as DirectAdmin handles this for you. DirectAdmin configures your applications intelligently using templates for each language/framework, simplifying the process as much as possible.

How to enable Nginx Unit

Build Nginx Unit by running the following commands:

cd /usr/local/directadmin/custombuild
./build set unit yes
./build unit

Usage

At the User level, you should be able to access Advanced Features -> Nginx unit.

Nginx Unit

There are 2 primary actions you will perform in this interface. You will create the application and then create the route. You must first create the path to your application and upload the app, both with the proper permissions and ownerships before you create the application using the path and entry script. Note that the entry script may need to be executable.

In this example, we will create a basic 'Hello World!" Ruby application.

Create the path, the script, fix the ownership, and then make the script executable. In the following, replace USER with the actual user, DOMAIN with the actual domain, and APPDIR with the actual application directory:

mkdir /home/USER/domains/DOMAIN/APPDIR
cd /home/USER/domains/DOMAIN/APPDIR
touch config.ru
chown -R USER.USER /home/USER/domains/DOMAIN/APPDIR
chmod +x /home/USER/domains/DOMAIN/APPDIR/config.ru

Fill the config.ru file with the following:

app = Proc.new do |env|
    ["200", {
        "Content-Type" => "text/plain",
    }, ["Hello, Ruby on Unit!"]]
end

run app

Create An Application

To create the application, click the Create Application button. Fill in all details for your application and create.

Create an Application

Create A Route

After creating the application, you can then create the route. You can click the button Create Route, or you can list the applications in the main Nginx Unit dashboard, then click the plus sign next to the application you're creating the route for, then click the option to create a route.

Create a Route

Most of the details will be filled in for you completely, if not all.

You also have the option to manually edit the JSON if needed.

Edit Route Json

NOTE: Nginx Unit does not have route rewrites yet: https://github.com/nginx/unit/issues/530open in new window

Test the Application

Allow a moment for everything to load before you proceed with testing. Then simply load the domain in the browser!

Browser Test

Troubleshooting

Logs are located at /var/log/unit/unit.log.

Make sure nginx_unit=ON is set in packages, reseller.conf, and user.conf files.

Use the following to test the application:

curl --unix-socket /var/run/unit/control.sock t/

If it appears empty, then run this to rewrite the configs for Nginx Unit:

echo "action=rewrite&value=nginx_unit" >> /usr/local/directadmin/data/task.queue
/usr/local/directadmin/dataskq

If you get a 404 error when loading the application, make sure the routes were created. If you get a 503 error, check the domain's Apache error log for details... it is likely that the application is not being proxied correctly to Nginx Unit.

FILES

Although Nginx Unit doesn't use any configuration files, some are stored locally for DirectAdmin's purposes:

/usr/local/directadmin/data/users/USERNAME/domains/DOMAIN.COM.unit/APP.json
/usr/local/directadmin/data/users/USERNAME/domains/DOMAIN.COM.routes/domain|SUB.domain

These files are used only for local storage, and to re-fill the live unit daemon. The "live" data is stored/managed in the unit deamon.

TEMPLATES

The templates that you can choose from are stored in the following locations:

/usr/local/directadmin/data/templates/unit_apps.json
/usr/local/directadmin/data/templates/unit_routes.json

These 2 templates are just pre-filled values for Users to choose from. Manual editing of raw json is still allowed in the GUI.

Other examples

Templates for all examples are adapted from the following Nginx Unit guide:

https://unit.nginx.org/howto/samples/open in new window

Java JSP Hello World Example

You will need to upload your application to the directory that you wish to host it under, otherwise the Nginx Unit creation page will not allow to to create the application due to a 'index.jsp file doesn't exist' error.

mkdir /home/USER/domains/DOMAIN/APPDIR
cd /home/USER/domains/DOMAIN/APPDIR
vi index.jsp

Populate the file with this code for testing, or use your own:

<%@ page language="java" contentType="text/plain" %>
<%= "Hello, JSP on Unit!" %>

Then fix the permissions and ownership:

chown -R USER.USER /home/USER/domains/DOMAIN/APPDIR
chmod +x /home/USER/domains/DOMAIN/APPDIR/index.jsp

To create an application, login as the user you wish to run the application under and navigate to User level → Advanced Features → Nginx unit → Create application. Application creation is made simple in DirectAdmin via templates. Select the java type and fill in your desired details. You should see a success message after saving and a prompt to create the suggested route. Now, create the route by clicking save on the route creation popup, after confirming the details are correct for your desired application.

Let's test via the CLI to ensure that our application was generated successfully:

curl --unix-socket /var/run/unit/control.sock t/

The application will load just by entering the domain name of the application in the browser as it will be proxied internally to the unix socket for Unit and served via Java. 😃

Java Apache WAR File Example

You will need to upload your application to the directory that you wish to host it under, otherwise the Nginx Unit creation page will not allow to to create the application due to being non-existant:

mkdir /home/USER/domains/DOMAIN/APPDIR
cd /home/USER/domains/DOMAIN/APPDIR

Now, let's download a test WAR file from Apache:

wget https://tomcat.apache.org/tomcat-5.5-doc/appdev/sample/sample.war

A WAR file can be unpackaged with the jar command similarly to as is done with the tar command, but this isn't necessary unless you just want to. Nginx Unit will unpackage it on the fly! A WAR file is essentially just a gzipped file.

chown -R admin.admin /home/USER/domains/DOMAIN/APPDIR

To create an application, login as the user you wish to run the application under and navigate to User level → Advanced Features → Nginx unit → Create application. Application creation is made simple in DirectAdmin via templates. Select the java type and fill in your desired details. You should see a success message after saving and a prompt to create the suggested route. Now, create the route by clicking save on the route creation popup, after confirming the details are correct for your desired application.

Let's test via the CLI to ensure that our application was generated successfully:

curl --unix-socket /var/run/unit/control.sock t/

The application will load just by entering the domain name of the application in the browser as it will be proxied internally to the unix socket for Unit and served via Java. 😃

NodeJS Hello World Example

You will need to upload your application to the directory that you wish to host it under, otherwise the Nginx Unit creation page will not allow to to create the application due to a 'app.js file doesn't exist' error.

mkdir /home/USER/domains/DOMAIN/APPDIR
cd /home/USER/domains/DOMAIN/APPDIR
vi app.js

Populate the file with this code for testing, or use your own:

#!/usr/bin/env node

var http = require('http');
var server = http.createServer(function(request, response) {
    response.writeHead(200, {"Content-Type": "text/html"});
    response.write((process.version));
    response.write("<br >");
    response.end("NodeJS App via Nginx Unit on DirectAdmin");
});

Fix the permissions and ownership:

chown -R USER.USER /home/USER/domains/DOMAIN/APPDIR
chmod +x /home/USER/domains/DOMAIN/APPDIR/app.js
cd /home/USER/domains/DOMAIN/APPDIR

To create an application, login as the user you wish to run the application under and navigate to User level → Advanced Features → Nginx unit → Create application. Application creation is made simple in DirectAdmin via templates. Select the NodeJS type and fill in your desired details. You should see a success message after saving and a prompt to create the suggested route based off of the template. Now, create the route by clicking save on the route creation popup, after confirming the details are correct for your desired application.

Let's test via the CLI to ensure that our application was generated successfully:

curl --unix-socket /var/run/unit/control.sock t/

The application will load just by entering the domain name of the application in the browser as it will be proxied internally to the unix socket for Unit and served via NodeJS. 😃

LetsEncrypt .well-known/acme-challenge/ path exclusions for Domain Validation

If you require a SSL for a domain that is using Nginx Unit, an exception will need to be added to allow paths matching .well-known/acme-challenge to be processed by your webserver instead of Nginx Unit. For example, for Apache this should be included in the configuration:

<Location /.well-known/acme-challenge>
     ProxyPass !
</Location>

This can be added via DirectAdmin's Admin Level -> Custom HTTPd Configurations section by copying and pasting the above code directly into the first big box (not the CUSTOM* boxes below) and then saving.

The method will vary according to your chosen webserver. For Nginx, it should be something like this in the server block:

location ~ /\.well-known/acme-challenge/ {
	    allow all;
	    root /var/www/html;
	    try_files $uri =404;
	    break;
	}

NOTE that this must be placed above all other redirects as to not be affected by them.

Advanced Usage

You can dynamically alter the configuration of the applications outside of DirectAdmin by using curl to interact with the RESTful API that Nginx Unit provides. You can submit json or you can submit a json file to completely alter an application's configuration. Please refer to the Nginx Unit documentation for more information and examples:

https://unit.nginx.org/configuration/open in new windowhttps://unit.nginx.org/howto/samples/open in new windowhttps://unit.nginx.org/howto/open in new windowhttps://www.nginx.com/blog/application-isolation-nginx-unit/open in new window

You can configure Nginx Unti with TLS/SSL, though it shouldn't be required if all requests are being made via SSL/TLS to your webserver, then proxied internally to localhost. The Nginx Unit ports should not be opened in the firewall configuration unless you configure Unit to work with SSL as to prevent any SSL bypass attempts.

How To Enable SSL for Nginx Unit

The default is unit_port_ssl=0 (formerly unit_port_ssl=8091). Since SSL is not needed for a localhost Unix socket connection from the webserver to Unit, the extra overhead was removed by disabling this option by default. It can be enabled if so desired, though:

cd /usr/local/directadmin/
./directadmin set unit_port_ssl 8091
service directadmin restart

Then issue a configuration file rewrite:

echo "action=rewrite&value=nginx_unit" /usr/local/directadmin/data/task.queue

or:

/usr/local/directadmin/custombuild/build rewrite_confs

A certificate listener will then be shown via Unit's configuration if queried via curl:

/certificates/hostname/listeners/*:8091

CMD_UNIT Requests (API Usage)

LIST

Listing all unit apps and routes:

CMD_UNIT?domain=domain.com&json=yes

JSON: returns json, with "applications" array. Each app index is the app name, eg "test", and the json data within that app is the data from the domains/domain.com.unit/$NAME.json.

Note: Numbers are currently shown as string, eg: "timeout": "10" which is set to be fixed such that the container supports actual numbers.

A "routes" array[] list is also returned. Will be either: domain.com and/or: sub.domain.com

where "subdomain" values are allowed routes specific to that subdomain. Routes applied to a domain are not applied to that subdomain.

APPLICATIONS

CREATE APP

Creating an nginx unit app Method: POST CMD_UNIT domain=domain.com action=create name=appname #saved as "domain.com_appname" in unit json={ ... your app ... }

MODIFY

Modify an existing nginx unit app Method: POST domain=domain.com action=modify name=appname json={ ... your app ... }

DELETE

Method: POST CMD_UNIT json=yes domain=domain.com action=select select0=app1 (select1=app2)

DirectAdmin does not check if the app json file currently exists, in case you're attempting to purge a left-over app from curl, which could be out of sync with the files.

ROUTES

LIST ROUTES

Listing all unit apps and routes:

CMD_UNIT?domain=domain.com&json=yes
ROUTE CREATION STEPS

'GET' the items available to create with: CMD_UNIT?domain=es60-64.com&action=route_create&json=yesCMD_UNIT?domain=es60-64.com&action=route_create&subdomain=sub&json=yes will return; da_settings["applications"] as a list of all currently available unit apps. da_settings["actions"] as a list of possible action (pass,proxy,return,share), with a brief description as each value. route[] the json route currently set for this domain or domain+subdomain. If nothing yet, it will be [].

CREATE ROUTE

CMD_UNIT method: POST action=set_route domain=domain.com (subdomain=sub :optional is saving for a subdomain) routes=[ the json list of matches/actions for this route ]

The "routes" data must be assembled json, as defined here: https://unit.nginx.org/configuration/#routesopen in new window

e.g.,

routes=
[
	{
		"match": 
		{
			"uri": "/v2_site/*"
		},
		"action": 
		{
			"pass": "applications/test.com_php"
		}
	},
	{
		"match": 
		{
			"uri": "/directadmin.com"
		},
		"action": 
		{
			"return": 301,
			"location": "https://directadmin.com"
		}
	},
	{
		"action": 
		{
			"proxy": "http://1.2.3.4:9000"
		}
	}
]

The DirectAdmin back-end recursively parses and validates all aspects of the json to prevent cross-user/domain app calls or shared paths not belonging to this User.

DELETE ROUTES

CMD_UNIT method: POST json=yes action=select_routes domain=domain.com (even if deleting a sub.domain route, use "domain.com" here) select0=domain.com (select1=sub.domain.com)

DA will attempt to clear the route from the unit socket first. If it fails, the local json file will not be removed. If it failed due to the route not existing, the local json file WILL be removed.


TODO directadmin.conf option to disable unit modules, eg: unit_modules=perl:php:etc.. Access Logs for unit.

SKINS

files_users.conf:

CMD_UNIT_CREATE=user/app/app_create.html
CMD_ROUTE_EDIT=user/app/route_edit.html
CMD_UNIT=user/app/apps.html

also file for viewing all apps, and editing a given app with auto-fill. (Make use of HTM insertion to re-use the same form html file for create and edit)

However, we recommend using dynamic json, as Evolution does. The above is only a basic raw textarea json method to control it and does not include the templates like Evo does.

Last Updated: