Throughout this chapter you will learn about operational integration as it pertains to NGINX Unit. Unit applications may need to be served via an NGINX proxy or load balancer, to which the configuration will be detailed. Also included are recipes that enable you to securely expose the Unit control interface through NGINX. Other topics include running Unit within a container and deploying application version upgrades through the control API.
You need to serve an application running in NGINX Unit through a NGINX server acting as a reverse proxy or load balancer.
Configure an upstream
block in the NGINX configuration made up of Unit servers:
upstream unit_backend { server 127.0.0.1:8080; # Local Reverse Proxy server 10.0.0.12:8080; # Remote Server Load Balance server 10.0.1.12:8080; # Remote Server Load Balance }
Configure a server
block within the NGINX configuration to proxy requests to the upstream
server set:
server { # Typical NGINX server setup and security directives location / { # NGINX Proxy Settings proxy_pass http://unit_backend; } }
The NGINX web server and reverse proxy load balancer is a fully dynamic application gateway. It can be used as a web server, reverse proxy, load balancer, and more. For brevity, this recipe assumes that the NGINX server
block has been configured with the necessary required and security-concerned directives.
In a reverse proxy situation, the NGINX server would be configured on the same physical or virtual machine as NGINX Unit. The upstream
block would be configured with a server
directive with a parameter specifying the same interface configured for the Unit listener object. In this example, the localhost 127.0.0.1
is used, in conjunction with the port 8080
.
In a load balancing situation, the NGINX server would be configured with an upstream
block that contains multiple remote server
directives. The example provides two server
directives specifying different remote NGINX Unit servers at IP addresses 10.0.0.12
and 10.0.1.12
. Both of these Unit servers would be configured with listener objects on port 8080
for the same application.
This example further demonstrates how a properly configured server
block can receive connections and direct the request to the application defined by the upstream
block. This is done by defining a location
block and using the proxy_pass
directive with a parameter that specifies the protocol and destination. In this example, the destination is the upstream
server block, named unit_backend
.
Incoming connections to the NGINX server will be processed, and requests matching the configured server definition will be directed to the configuration within this server
block. In this example, all configuration requests will be sent to the NGINX Unit server for processing. The NGINX Unit server will return the request to the NGINX server, which will return the request to the client.
You would like to remotely and securely configure the Unit application server.
Configure a NGINX reverse proxy to the control interface Unix socket. Ensure that it is only available internally and that client-server encryption is enforced.
server { # Configure SSL encryption server 443 ssl; ssl_certificate /path/to/ssl/cert.pem; ssl_certificate_key /path/to/ssl/cert.key; # Configure SSL client certificate validation ssl_client_certificate /path/to/ca.pem; ssl_verify_client on; # Configure network ACLs #allow 1.2.3.4; # Uncomment and update with the IP addresses # and networks of your administrative systems. deny all; # Configure HTTP Basic authentication auth_basic on; auth_basic_user_file /path/to/htpasswd; location / { proxy_pass http://unix:/var/run/control.unit.sock; } }
This recipe configures the NGINX reverse proxy server to serve the NGINX Unit control interface through an HTTPS connection. The NGINX server is configured to serve only on port 443
and to only accept encrypted connections. The SSL/TLS directives of the NGINX server must be configured to specify a given certificate and key for encryption. This configuration also requires the client to provide a certificate signed by the specified certificate authority as a means of authentication. For further security, the configuration denies all requests from any client IP that is not specified by the allow
directive. The allow
directive must be uncommented and configured to your internal IP or CIDR. Finally, a username and password must be specified via HTTP basic auth. The auth_basic_user_file
directive defines a file that contains usernames and hashed passwords of authorized users.
Once all security measures are met, NGINX will proxy the request to the NGINX Unit control interface. By default, the Unit control interface listens on a Unix socket. The system user running NGINX must have permission to read and write to this Unix socket file.
You would like to use NGINX Unit as a middleware server in a containerized environment.
Build a unit configuration file at the base of the project. Name the file unit-conf.json:
{
"listeners"
:
{
"*:8080"
:
{
"pass"
:
"applications/php_project"
}
},
"applications"
:
{
"php_project"
:
{
"type"
:
"php"
,
"processes"
:
1
,
"root"
:
"/var/app"
,
"index"
:
"index.php"
}
}
}
Use the Official NGINX Unit Docker Image as the base. Create a Dockerfile with the following:
FROM
nginx/unit
ADD
/ /var/app/
ADD
/unit-conf.json /var/lib/unit/conf.json
Build the Dockerfile into an image:
docker build -t unit-example .
Run the Docker image and expose the listener through the Docker proxy for testing. The following example uses the Docker -p
flag to configure a proxy, exposing port 8080
proxied to port 8080
. As a reminder, the port number before the :
is the port exposed on the local machine:
docker run -p 8080:8080 unit-example
Make a request to the exposed Docker proxy to validate:
curl localhost:8080
This recipe demonstrates the basics of using NGINX Unit as a middleware server for dockerized applications. A Unit configuration file is created for the application. A Dockerfile is then crafted, based on the Official NGINX Unit Docker Image. Within the Dockerfile, the application code is added to the image. The configuration file is then added to the image in the location of the Unit state file. This ensures that Unit will start with the application and listener objects configured.
The Dockerfile is then built, rendering an image tagged unit-example
. The Docker image is then run with the proxy flag to expose the listener to the host. Once running, the Docker container is validated.
Furthermore, with Docker you are able to mount volumes with the -v
flag. By doing so you are able to expose the host’s filesystem. If the control interface is overridden via the CMD
directive in the Dockerfile, and exposed by the Docker proxy, remote reconfiguration of the Unit container is enabled. In this configuration it is possible to add applications that exist on the host’s filesystem and to reconfigure Unit listeners to serve these applications remotely through the control API. This technique may be helpful for local development environments.
You need to deploy a new version of an application without downtime.
Utilize NGINX Unit’s API to switch between application versions through an API call. This recipe will use a directory structure laid out in the following way:
/var/app/ ├── version-1 │ ├── index.php │ └── ... └── version-2 ├── index.php └── ...
The current state of the Unit configuration is as such:
{
"listeners"
:
{
"*:8080"
:
{
"pass"
:
"applications/php_project_version_1"
}
},
"applications"
:
{
"php_project_version_1"
:
{
"type"
:
"php"
,
"processes"
:
2
,
"root"
:
"/var/app/version-1"
,
"index"
:
"index.php"
}
}
}
Create another file named php-v2.json file with the following JSON:
{
"type"
:
"php"
,
"processes"
:
2
,
"root"
:
"/var/app/version-2"
,
"index"
:
"index.php"
}
Make an API call to the control interface. Provide the php-v2.json as the JSON body. Use the RESTful syntax to name the Unit application php_project_version_2
:
sudo curl -X PUT -d @php-v2.json--unix-socket /var/run/control.unit.sock
http://localhost/config/applications/php_project_version_2
Make the following request to the Unit control interface to validate that both applications are configured:
sudo curl --unix-socket /var/run/control.unit.sockhttp://localhost/config
{
"listeners"
:{
"*:8080"
:{
"pass"
:"applications/php_project_version_1"
}
}
,"applications"
:{
"php_project_version_1"
:{
"type"
:"php"
,"processes"
: 2,"root"
:"/var/app/version-1"
,"index"
:"index.php"
}
,"php_project_version_2"
:{
"type"
:"php"
,"processes"
: 2,"root"
:"/var/app/version-2"
,"index"
:"index.php"
}
}
}
Make a request to the control interface with the following command, instructing Unit to switch the listener *:8080
to point to the php_project_version_2
application:
sudo curl -X PUT -d'"php_project_version_2"'
--unix-socket /var/run/control.unit.sock
'http://localhost/config/listeners/*:8080/application'
Make the following request to the Unit control interface to validate that the listener has been reconfigured to direct requests to the php_project_version_2
application:
sudo curl --unix-socket /var/run/control.unit.sockhttp://localhost/config
{
"listeners"
:{
"*:8080"
:{
"pass"
:"applications/php_project_version_2"
}
}
,"applications"
:{
"php_project_version_1"
:{
"type"
:"php"
,"processes"
: 2,"root"
:"/var/app/version-1"
,"index"
:"index.php"
}
,"php_project_version_2"
:{
"type"
:"php"
,"processes"
: 2,"root"
:"/var/app/version-2"
,"index"
:"index.php"
}
}
}
Make a request to the control interface to remove the php_project_version_1
application:
sudo curl -X DELETE--unix-socket /var/run/control.unit.sock
http://localhost/config/applications/php_project_version_1
This recipe demonstrates the deployment of a new version of an application. The example starts from a pre-configured state, with a single application version being served on port 8080
. NGINX Unit is then configured to start another application of a new version. Both versions run in parallel as separate process sets. Unit is then instructed to route incoming requests to the new application version. Finally, the older application version is removed, and the processes that served that application are removed.
3.144.27.199