Running Nginx Unit on CentOS 7

table of contents
Hello.
I'm Mandai, the Wild team member in charge of development.
Everyone loves the new Nginx family, "Nginx Unit," which was released a while ago
I did some research to find out how to use Nginx Unit
table of contents
- What is Nginx Unit?
- How to install
- First, start the service
- Check Nginx Unit configuration
- Change Nginx Unit settings
- Delete Nginx Unit Configuration
- summary
What is Nginx Unit?
Nginx Unit is a middleware that acts as a web application server, just like Nginx
The features of Nginx Unit are as follows:
- Dynamically modify the configuration file (no restart required)
- A single Nginx can run services in multiple programming languages
It is said that there is a place like this
This time, I'd like to actually install it and get a feel for what it's like
How to install
In the case of CentOS, it can be installed via yum, which is very easy
mostlythe official documentationjust followed the instructions in
First, register the Nginx Unit repository
sudo vi /etc/yum.repos.d/unit.repo # Paste the following content [unit] name=unit repo baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/ gpgcheck=0 enabled=1
That completes the preliminary setup.
Next, we'll run the yum command.
yum install unit Loaded plugins:fastestmirror, langpacks Loading mirror speeds from cached hostfile * base: ftp.riken.jp * epel: mirror.dmmlabs.jp * extras: ftp.riken.jp * nux-dextop: li.nux.ro * remi-safe: mirror.bebout.net * updates: ftp.riken.jp Resolving dependencies --> Running transaction check ---> Installing package unit.x86_64 0:0.1-1.el7.ngx --> Processing dependencies: libphp5-5.4.so()(64bit) for package: unit-0.1-1.el7.ngx.x86_64 --> Running transaction check ---> Installing package php-embedded.x86_64 0:5.4.16-42.el7 --> Processing dependencies: php-common(x86-64) = 5.4.16-42.el7 for package: php-embedded-5.4.16-42.el7.x86_64 --> Running transaction check ---> Installing package php-common.x86_64 0:5.4.16-42.el7 --> Processing dependencies: libzip.so.2()(64bit) for package: php-common-5.4.16-42.el7.x86_64 --> Running transaction check ---> Installing package libzip.x86_64 0:0.10.1-8.el7 --> Dependency resolution finished. Dependencies resolved ~ Omitted ~ Thank you for installing NGINX Unit! You may want to load demo configuration and check a couple of apps: # service unitd start # service unitd restoreconfig /usr/share/doc/unit/examples/example.config # curl http://localhost:8300/ # curl http://localhost:8400/ Online documentation is available at http://unit.nginx.org/ ---------------------------------------------------------------------- Testing: php-embedded-5.4.16-42.el7.x86_64 1/4 Testing: libzip-0.10.1-8.el7.x86_64 2/4 Testing: php-common-5.4.16-42.el7.x86_64 3/4 Testing: unit-0.1-1.el7.ngx.x86_64 4/4 Installed: unit.x86_64 0:0.1-1.el7.ngx Installed dependencies: libzip.x86_64 0:0.10.1-8.el7 php-common.x86_64 0:5.4.16-42.el7 php-embedded.x86_64 0:5.4.16-42.el7 Done!
It's a mystery why PHP (and version 5 at that!) is being flagged in the dependency check (presumably because it's pulling it from the base repository to provide the execution environment as well).
If you already have PHP installed or want to use it in a PHP7 environment, source installation seems like a better option.
For source installation, you'll need to prepare the necessary libraries for your execution environment and compile them.
Especially if you're using PHP7, installing via yum seems difficult, sothesetry following
First, start the service
At the end of the yum installation screen we just saw, there was a command to start the service, so I'll try running that first.
Even though it requires CentOS 7, it uses the `service` command, so I'll show you the `systemctl` command I recently learned!
# First, start the service sudo systemctl start unitd # Restore the configuration file $ service unitd restoreconfig /usr/share/doc/unit/examples/example.config Restoring configuration from /usr/share/doc/unit/examples/example.config... { "success": "Reconfiguration done." }
For the second command, I had no idea how to convert it to a systemctl command, so I simply used the service command
By the way, if you run the first command as a service command, the result will be as follows
sudo service unitd start Redirecting to /bin/systemctl start unitd.service
It does execute correctly, but it keeps reminding you that it was executed using the systemctl command.
However, when I ran it with restoreconfig, there were no such warnings, so I'm wondering if the service command is the correct way to do it.
At this point, it should be running correctly, so you might be tempted to verify its operation with the curl command... but here's the key point: with Nginx, the execution order of the above commands is reversed.
When you update the configuration file of Nginx, a restart is always required, which inevitably makes it difficult to change the configuration while it's running. This
is something that might be easily overlooked, but it's a moment where you can catch a glimpse of the benefits of Nginx Unit.
Now try accessing the web server again
$ curl http://localhost:8300/ [email protected] $ curl http://localhost:8400/ 2017-10-17 02:11:15 AM ENV Variables: LANG ja_JP.utf8 PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin UNITD_OPTIONS --log /var/log/unitd.log --pid /run/unitd.pid
Port 8300 appears to be functioning as a normal web server, with phpinfo() being executed.
Port 8400 is currently of unknown purpose, but it seems to be displaying the execution environment settings. We'll explore
the mystery of this port later.
The installation seems to have gone well, so next we'll check the settings
Check Nginx Unit configuration
For now, the only thing that looks like an Nginx Unit configuration file is /usr/share/doc/unit/examples/example.config, so let's take a look at that
less /usr/share/doc/unit/examples/example.config { "applications": { "example_php": { "type": "php", "user": "nobody", "workers": 2, "root": "/usr/share/doc/unit/examples/php-app", "index": "index.php" }, "example_python": { "type": "python", "user": "nobody", "workers": 2, "path": "/usr/share/doc/unit/examples/python-app", "module": "wsgi" }, "example_go": { "type": "go", "user": "nobody", "executable": "/tmp/go-app" } }, "listeners": { "*:8300": { "application": "example_php" }, "*:8400": { "application": "example_python" }, "*:8500": { "application": "example_go" } } }
When I opened the file, it was a JSON file.
A JSON file makes the configuration structure easy to understand.
It seems that the "http://localhost:8400" mentioned earlier is actually a standby URL for the Python program
According to the documentation, it seems that the settings can be checked via socket communication.
It looks something like this.
curl --unix-socket /path/to/socket http://localhost/
However, to do this, we need to know the location of the socket file, so we will look at this from the perspective of process activity
First, use the ps command to identify the Nginx Unit process
ps auxwwwf | grep [u]nit root 5821 0.0 0.0 18256 636 ? Ss 00:21 0:00 unit: main [/usr/sbin/unitd --log /var/log/unitd.log --pid /run/unitd.pid] nobody 5824 0.0 0.0 18256 680 ? S 00:21 0:00 \_ unit: controller nobody 5825 0.0 0.0 18256 680 ? S 00:21 0:00 \_ unit: router
The Nginx Unit appears to run with three processes: a daemon, a controller, and a router. This
number may increase or decrease depending on the configuration, but this is the current setup.
Next, use the lsof command to check the files that process 5821 is holding
lsof -p 5821 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME unitd 5821 root cwd DIR 253,0 4096 2 / unitd 5821 root rtd DIR 253,0 4096 2 / unitd 5821 root txt REG 253,0 397232 806046 /usr/sbin/unitd unitd 5821 root mem REG 253,0 37352 805753 /usr/lib64/libnss_sss.so.2 unitd 5821 root mem REG 253,0 62184 787847 /usr/lib64/libnss_files-2.17.so unitd 5821 root mem REG 253,0 2118128 787829 /usr/lib64/libc-2.17.so unitd 5821 root mem REG 253,0 143944 787855 /usr/lib64/libpthread-2.17.so unitd 5821 root mem REG 253,0 19776 787835 /usr/lib64/libdl-2.17.so unitd 5821 root mem REG 253,0 44448 787859 /usr/lib64/librt-2.17.so unitd 5821 root mem REG 253,0 1141928 787837 /usr/lib64/libm-2.17.so unitd 5821 root mem REG 253,0 155464 806682 /usr/lib64/ld-2.17.so unitd 5821 root 0u CHR 1,3 0t0 1028 /dev/null unitd 5821 root 1u CHR 1,3 0t0 1028 /dev/null unitd 5821 root 2w REG 253,0 258231 136119 /var/log/unitd.log unitd 5821 root 3u a_inode 0,9 0 5832 [eventpoll] unitd 5821 root 4u a_inode 0,9 0 5832 [signalfd] unitd 5821 root 5u a_inode 0,9 0 5832 [eventfd] unitd 5821 root 6u unix 0xffff8800783ba400 0t0 48362 /var/run/control.unit.sock # <- this unitd 5821 root 7w REG 253,0 258231 136119 /var/log/unitd.log unitd 5821 root 8u unix 0xffff880023ebb400 0t0 49423 socket unitd 5821 root 9u unix 0xffff880023ebb800 0t0 49424 socket unitd 5821 root 12u unix 0xffff8800b1954800 0t0 49428 socket unitd 5821 root 13u unix 0xffff880023eb9c00 0t0 49430 socket
It seems that "/var/run/control.unit.sock" is the socket file, so the command to check the settings is as follows
curl --unix-socket /var/run/control.unit.sock http://localhost/ { "applications": { "example_php": { "type": "php", "user": "nobody", "workers": 2, "root": "/usr/share/doc/unit/examples/php-app", "index": "index.php" }, "example_python": { "type": "python", "user": "nobody", "workers": 2, "path": "/usr/share/doc/unit/examples/python-app", "module": "wsgi" }, "example_go": { "type": "go", "user": "nobody", "executable": "/tmp/go-app" } }, "listeners": { "*:8300": { "application": "example_php" }, "*:8400": { "application": "example_python" }, "*:8500": { "application": "example_go" } } }
Using the curl command to check the web server settings feels quite novel, but it returned the same content as "/usr/share/doc/unit/examples/example.config".
This means the test configuration file was successfully loaded.
Next, I'd like to change the settings
Change Nginx Unit settings
the official documentationLooking at
To quote from the documentation:
# Example: Create a Full Configuration curl -X PUT -d @/path/to/start.json \ --unix-socket ./control.unit.sock http://localhost/ # Example: Create an Application Object curl -X PUT -d @/path/to/wiki.json \ --unix-socket ./control.unit.sock http://localhost/applications/wiki
I easily understood how to apply the first JSON file, but the second setting method is a nightmare.
It allows applying JSON to only a portion of the code, but specifying which part to apply it to using a URL...!!
I'd also like to test reading a JSON file I created myself.
I've prepared a simple JSON file like the one below.
{
"type": "php",
"user": "nobody",
"workers": 4,
"root": "/var/www/html",
"index": "index.php"
}
This is a simple setting to make the document root under the common "/var/www/html" directory, but will it work?
Save this file as "/home/hogehoge/test-php.json".
Let's try sending this to the Nginx Unit using the curl command!
Add it directly under the applications directory.
curl -X PUT -d @/home/hogehoge/test-php.json --unix-socket /var/run/control.unit.sock http://localhost/applications/test { "success": "Reconfiguration done." }
It appears the registration was successful.
Let's also check the current settings.
curl --unix-socket /var/run/control.unit.sock http://localhost/ { "applications": { "example_php": { "type": "php", "user": "nobody", "workers": 2, "root": "/usr/share/doc/unit/examples/php-app", "index": "index.php" }, "example_python": { "type": "python", "user": "nobody", "workers": 2, "path": "/usr/share/doc/unit/examples/python-app", "module": "wsgi" }, "example_go": { "type": "go", "user": "nobody", "executable": "/tmp/go-app" }, "test": { "type": "php", "user": "nobody", "workers": 4, "root": "/var/www/html", "index": "index.php" } }, "listeners": { "*:8300": { "application": "example_php" }, "*:8400": { "application": "example_python" }, "*:8500": { "application": "example_go" } } }
It seems to have been added successfully.
Now, I'd like to check if it works correctly with the curl command... but routing won't work if the listener isn't registered, so I'll also add the routing JSON file.
{
"application": "test"
}
We will register the above JSON using curl in the same way as before
curl -X PUT -d @/home/hogehoge/test-php-listener.json --unix-socket /var/run/control.unit.sock http://localhost/listeners/*:8301 { "success": "Reconfiguration done." }
The last URL is unusual, but strictly speaking, it's not a URL, so we won't worry about it too much.
If success is returned, we'll check the entire configuration.
curl --unix-socket /var/run/control.unit.sock http://localhost/ { "applications": { "example_php": { "type": "php", "user": "nobody", "workers": 2, "root": "/usr/share/doc/unit/examples/php-app", "index": "index.php" }, "example_python": { "type": "python", "user": "nobody", "workers": 2, "path": "/usr/share/doc/unit/examples/python-app", "module": "wsgi" }, "example_go": { "type": "go", "user": "nobody", "executable": "/tmp/go-app" }, "test": { "type": "php", "user": "nobody", "workers": 4, "root": "/var/www/html", "index": "index.php" } }, "listeners": { "*:8300": { "application": "example_php" }, "*:8400": { "application": "example_python" }, "*:8500": { "application": "example_go" }, "*:8301": { "application": "test" } } }
The settings seem to have been applied correctly.
"http://localhost:8301" using the curl command or in a browserChecking
(There was still content developed with fuelPHP under this document root, but there were no problems.)
Delete Nginx Unit Configuration
When making changes, you send the curl HTTP method PUT, so when deleting, you naturally use the DELETE method
Even without looking at the official documentation, you can probably guess the answer, but let's double-check just to be sure.
The curl command for deletion using curl is as follows:
curl -X DELETE --unix-socket ./control.unit.sock \ 'http://localhost/listeners/*:8400'
Let's try deleting the Listener settings we added earlier
curl -X DELETE --unix-socket /var/run/control.unit.sock http://localhost/listeners/*:8301 { "success": "Reconfiguration done." }
Yes, it seems to have been successfully deleted
This part is very easy
By the way, since both the input and output are JSON, saving the settings is very easy
# Write the results of curl to a file curl --unix-socket /var/run/control.unit.sock http://localhost/ > /path/to/unitd.conf.json # Check that writing is possible cat /path/to/unitd.conf.json { "applications": { "example_php": { "type": "php", "user": "nobody", "workers": 2, "root": "/usr/share/doc/unit/examples/php-app", "index": "index.php" }, "example_python": { "type": "python", "user": "nobody", "workers": 2, "path": "/usr/share/doc/unit/examples/python-app", "module": "wsgi" }, "example_go": { "type": "go", "user": "nobody", "executable": "/tmp/go-app" }, "test": { "type": "php", "user": "nobody", "workers": 4, "root": "/var/www/html", "index": "index.php" } }, "listeners": { "*:8300": { "application": "example_php" }, "*:8400": { "application": "example_python" }, "*:8500": { "application": "example_go" } } } # Restart Nginx Unit systemctl restart unitd # Check the configuration, there is nothing entered curl --unix-socket /var/run/control.unit.sock http://localhost/ { "listeners": {}, "applications": {} } # Input the JSON data output to the file earlier curl -X PUT -d @/root/unitd.conf.json --unix-socket /var/run/control.unit.sock http://localhost { "success": "Reconfiguration done." } # Check if the settings are reflected curl --unix-socket /var/run/control.unit.sock http://localhost/ { "applications": { "example_php": { "type": "php", "user": "nobody", "workers": 2, "root": "/usr/share/doc/unit/examples/php-app", "index": "index.php" }, "example_python": { "type": "python", "user": "nobody", "workers": 2, "path": "/usr/share/doc/unit/examples/python-app", "module": "wsgi" }, "example_go": { "type": "go", "user": "nobody", "executable": "/tmp/go-app" }, "test": { "type": "php", "user": "nobody", "workers": 4, "root": "/var/www/html", "index": "index.php" } }, "listeners": { "*:8300": { "application": "example_php" }, "*:8400": { "application": "example_python" }, "*:8500": { "application": "example_go" } } }
It worked!
summary
What did you think of the promising newcomer, Nginx Unit?
The official documentation even describes a combination where Nginx acts as a reverse proxy and requests are routed to Nginx Unit via socket communication. While it's a bit too easy to rewrite the configuration for standalone use, and there are some quirks in how the settings are applied at startup, I think it's a good complement to the less flexible aspects of Nginx.
The version is 0.1.
Of course, it's a beta version.
I'm looking forward to seeing how it will be refined in the future.
That's all
1
