Nginx Unit
CMD_UNIT: Nginx Unit for other handlers
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 Unit 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.
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 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.
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.
NOTE: Nginx Unit does not have route rewrites yet: https://github.com/nginx/unit/issues/530
Test the Application
Allow a moment for everything to load before you proceed with testing. Then simply load the domain in the browser!
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/
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-existent:
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 CUSTOM2 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, first big box (not the CUSTOM* boxes below).
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/https://unit.nginx.org/howto/samples/https://unit.nginx.org/howto/https://www.nginx.com/blog/application-isolation-nginx-unit/
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=yes
CMD_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/#routes
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.