A 15 year wait. Nginx application server

Published on September 06, 2017

A 15 year wait. Nginx application server

    Since the advent of Nginx in 2004, we have all wondered: when will it be possible to run applications on nginx? We ran PHP in php-fpm and on Apache, ran Python through uWSGI, sometimes lived with Apache, and if we needed different versions of PHP, we lived with a zoo from FPMs.

    image

    Just at the NginxConf conference in Portland, Nginx, Inc. announced the launch of the Nginx Application Platform. ITSumma tested one of its components, the Application Server itself, called the Nginx Unit with a closed version. In this post we will talk about how the Nginx Unit looks and how to run applications on it.

    Nginx Unit is a web application server that allows you to run web applications written in various programming languages ​​(php, python, go). This tool is quite lightweight and allows you to reconfigure settings and the number of applications on the fly as needed during development.

    The main site of the project

    Currently supported platforms:
    - Python 2.6, 2.7, 3
    - PHP 5, 7
    - Go 1.6 or later

    An important and cool feature for people with a zoo of platforms: different versions of the same platform can be launched within the same config , one appserver - goodbye, PHP-FPM zoo.

    → The source code of the project is uploaded to Github .

    What is cool and interesting: the guys uploaded the code to the github starting from the first commit and promise to accept pull requests in the classic style for github. Among other things, you can see the history, logic and style of development - very interesting.

    Installation


    Important: the current version is still beta, with lots of debugging code that adds its overhead. In future versions they promise significant optimization, which should surpass the current app-servers in terms of performance.

    Packages are now available for CentOS 7.0 and Ubuntu 16.04 LTS

    Installation for CentOS 7

    1. Create a file /etc/yum.repos.d/unit.repo with the following contents:

    [unit]
    name=unit repo
    baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
    gpgcheck=0
    enabled=1

    2. Run the package installation:

    # yum install unit

    Installation for Ubuntu 16.04

    1. Download the PGP dongle of NGINX , Inc.

    2. Add the key to the apt keychain. After that, there should be no alerts about the missing PGP key during Unit installation.

    # sudo apt-key add nginx_signing.key

    3. Add the following lines to the end of the /etc/apt/sources.list file:

    deb http://nginx.org/packages/mainline/ubuntu/ xenial nginx
    deb-src http://nginx.org/packages/mainline/ubuntu/ xenial nginx

    4. Download Unit:

    # apt-get update
    # apt-get install unit

    The Nginx Unit consists of several service processes (master / controller / router) and the application process itself. Configuration is done through the REST API, through the Unix socket unit.control.sock.

    Getting the current config

    curl --unix-socket ./control.unit.sock http://localhost/

    Download new

    curl -X PUT -d @/path/to/start.json  --unix-socket ./control.unit.sock http://localhost/

    The configuration consists of a set of applications (application) and workers (listener).

    Application launch


    Consider launching an application using the example of launching 1C-Bitrix and Laravel: the
    classic nginx is the frontend, and the Nginx Unit is the backend. Now, every Nginx Unit “application” for PHP has one entry point. In the case of Bitrix, there can be two of them - urlrewrite.php and index.php, respectively in beta - you need to either combine this logic into one file in the code or run two applications. In the upcoming versions of Nginx Unit, the guys promise to do routing to avoid this problem.

    Configuration for Laravel:

        location / {
            proxy_pass       http://127.0.0.1:8300;
            proxy_redirect   http://127.0.0.1:8300/ /;
            proxy_read_timeout 60s;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        location ~ \.php$ {
            proxy_pass       http://127.0.0.1:8300;
            proxy_redirect   http://127.0.0.1:8300/ /;
            proxy_read_timeout 60s;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

    Configuration for "1C-Bitrix":

     location = / {
            proxy_pass       http://127.0.0.1:8601;
            proxy_redirect   http://127.0.0.1:8601/ /;
            proxy_read_timeout 60s;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            break;
        }
        location / {
            try_files $uri /bitrix/urlrewrite.php =404;
            proxy_pass       http://127.0.0.1:8600;
            proxy_redirect   http://127.0.0.1:8600/ /;
            proxy_read_timeout 60s;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

    To replace the configuration, run

    curl -X PUT -d @/path/to/start.json  --unix-socket ./control.unit.sock http://localhost/

    (By default - a socket, you can proxy from a socket to a TCP port using nginx.)

    At the moment, the configuration must be loaded when the app server starts, in future versions of Unit it will save the loaded configuration upon restart.

    First, we list the applications, while for each application we indicate the version of the interpreter. You can specify the index parameter as the entry point (and then the script will be taken from the query string), or, in the case of the entry point, the script - and then the requests will go to a specific script. Again, note that for “1C-Bitrix” two applications are launched:

    Config:

    {                                                             
            "applications": {                                     
                    "laravel": {                                     
                            "type": "php 7.0",                    
                            "user": "nobody",                     
                            "group": "nobody",                    
                            "workers": 2,                         
                            "root": "/var/www/vhosts/laravel/public",
                            "script": "index.php",                
                    },                                            
                    "plain": {                                     
                            "type": "php 7.0",                    
                            "user": "nobody",                     
                            "group": "nobody",                    
                            "workers": 2,                         
                            "root": "/var/www/vhosts/test",       
                            "index": "index.php"                 
                    },                                            
                    "bitrix": {                                   
                            "type": "php 5.6",                    
                            "user": "nobody",                     
                            "group": "nobody",                    
                            "workers": 2,                         
                            "root": "/var/www/vhosts/bitrix",  
                            "script": "/bitrix/urlrewrite.php"    
                    },                                            
                    "bitrix_index": {                             
                            "type": "php 5.6",                    
                            "user": "nobody",                     
                            "group": "nobody",                    
                            "workers": 2,                         
                            "root": "/var/www/vhosts/bitrix",  
                            "script": "index.php"                 
                    }                                             
            },       

    Then ups are hung up on ports:

            "listeners": {                                        
                    "*:8300": {                                   
                            "application": "laravel"                 
                    },                                            
                    "*:8500": {                                   
                            "application": "plain"                 
                    },                                            
                    "*:8600": {                                   
                            "application": "bitrix"               
                    },                                            
                    "*:8601": {                                   
                            "application": "bitirx_index"         
                    }                                             
            }                                                     
    }        

    We have all been waiting for this for quite some time, but let's still look at cases where Unit will bring a serious advantage:

    • heterogeneous application infrastructure. Now, within the same app-server, you can keep different versions of PHP, run Python and Go. By the end of the year, NodeJS, Java, and possibly Ruby are expected. All this in one config, the same app-server. Applications no longer write in one language, and it really makes our lives easier.
    • Zoo versions on one system . Tired of numerous fpm configurations and builds with different versions? Now it can be run within the same application. It is clear that this is not a “clean” situation, but it is often encountered and, again, a serious relief of life.
    • if we feel points 1 and 2 on ourselves, then the third, about which Nginx speaks, remains to be tried. Unified and easy configuration management with microservice architecture. Unified configuration management system through the REST API, a single product as a whole.

    While the Application Platform is still beta, but you can already try and prepare your configurations for production. Looking forward to further news!