Chapter 7. Ecosystem Integration

Introduction

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.

Reverse Proxying to Unit Applications Through NGINX

Problem

You need to serve an application running in NGINX Unit through a NGINX server acting as a reverse proxy or load balancer.

Solution

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;
    }
}

Discussion

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.

Additional Resources

NGINX Integration

Securely Serving the NGINX Unit Control API

Problem

You would like to remotely and securely configure the Unit application server.

Solution

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;
    }
}

Discussion

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.

Additional Resources

NGINX Integration

Containerized Environment

Problem

You would like to use NGINX Unit as a middleware server in a containerized environment.

Solution

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

Discussion

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.

Additional Resources

Unit in Docker

Deployments

Problem

You need to deploy a new version of an application without downtime.

Solution

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.sock 
      http://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.sock 
      http://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

Discussion

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.27.199