NGINX Unit
v. 1.25.0

NGINX Integration§

Unit is a potent and versatile server in its own right. However, if you’re used to NGINX’s rich feature set, you can deploy it in front of Unit; one notable use case for NGINX here is securing the Unit control socket.

Fronting Unit with NGINX§

Configure a listener in Unit:

{
    "127.0.0.1:8080": {
        "pass": "...",
        "client_ip": {
            "header": "X-Forwarded-For",
            "source": [
                "127.0.0.1"
            ]
        }
    }
}

Here, client_ip is optional; it enables identifying the originating IPs of requests proxied from source.

In NGINX configuration, create an upstream in the http context, adding the listener’s socket as a server:

http {
    upstream unit_backend {
        server 127.0.0.1:8080;
    }

    server {
        location /unit/ {
            proxy_pass http://unit_backend;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

A more compact alternative would be a direct proxy_pass in your location:

http {
    server {
        location /unit/ {
            proxy_pass http://127.0.0.1:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }
}

The proxy_set_header X-Forwarded-For directives work together with the listener’s client_ip option.

For details, see the NGINX documentation. Commercial support and advanced features are also available.

Securely Proxying Unit’s Control API§

By default, Unit exposes its control API via a Unix domain socket. These sockets aren’t network accessible, so the API is local only. To enable secure remote access, you can use NGINX as a reverse proxy.

Warning

Avoid exposing an unprotected control socket to public networks. Use NGINX or a different solution such as SSH for security and authentication.

Use this configuration template for NGINX (replace placeholders in ssl_certificate, ssl_certificate_key, ssl_client_certificate, allow, auth_basic_user_file, and proxy_pass with real values):

server {

    # Configure SSL encryption
    listen 443 ssl;

    ssl_certificate /path/to/ssl/cert.pem;
    ssl_certificate_key /path/to/ssl/cert.key;

    # SSL client certificate validation
    ssl_client_certificate /path/to/ca.pem;
    ssl_verify_client on;

    # Network ACLs
    allow 1.2.3.4;
    deny all;

    # HTTP Basic authentication
    auth_basic on;
    auth_basic_user_file /path/to/htpasswd;

    location / {
        proxy_pass http://unix:/path/to/control.unit.sock;
    }
}

The same approach works for an IP-based control socket:

location / {
    proxy_pass http://127.0.0.1:8080;
}