Working With Language Modules§
Languages supported by Unit fall into these two categories:
- External (Go, Node.js): Run outside Unit with an interface layer to the native runtime.
- Embedded (Java, Perl, PHP, Python, Ruby, WebAssembly): Execute in runtimes that Unit loads at startup.
For any specific language and its version, Unit needs a language module.
External Language Modules§
External modules are regular language libraries or packages that you install like any other. They provide common web functionality, communicating with Unit from the app’s runspace.
In Go, Unit support is implemented with a package that you import in your apps to make them Unit-aware.
In Node.js, Unit is supported by an npm-hosted package that you require in your app code. You can install the package from the npm repository; otherwise, build it for your version of Node.js using Unit’s sources.
For WebAssembly, Unit delegates bytecode execution to the Wasmtime runtime that is installed with the language module module or during a source build.
Embedded Language Modules§
Embedded modules are shared libraries that Unit loads at startup. Query Unit to find them in your system:
$ unitd -h
...
--log FILE set log filename
default: "/default/path/to/unit.log"
--modules DIRECTORY set modules directory name
default: "/default/modules/path/"
$ ps ax | grep unitd
...
unit: main v1.34.0 [unitd --log /runtime/path/to/unit.log --modules /runtime/modules/path/ ... ]
$ ls /path/to/modules
java.unit.so php.unit.so ruby.unit.so wasm_wasi_component.unit.so
perl.unit.so python.unit.so wasm.unit.so
To clarify the module versions, check the Unit log to see which modules were loaded at startup:
# less /path/to/unit.log
...
discovery started
module: <language> <version> "/path/to/modules/<module name>.unit.so"
...
If a language version is not listed, Unit can’t run apps that rely on it; however, you can add new modules:
- If possible, use the official language packages for easy integration and maintenance.
- If you installed Unit via a third-party repo, check whether a suitable language package is available there.
- If you want a customized yet reusable solution, prepare your own package to be installed beside Unit.
Packaging Custom Modules§
There’s always a chance that you need to run a language version that isn’t yet available among the official Unit packages but still want to benefit from the convenience of a packaged installation. In this case, you can build your own package to be installed alongside the official distribution, adding the latter as a prerequisite.
Here, we are packaging a custom PHP 7.3 module to be installed next to the official Unit package; adjust the command samples as needed to fit your scenario.
Note
For details of building Unit language modules, see the source code howto; it also describes building Unit itself. For more packaging examples, see our package sources.
Assuming you are packaging for the current system and have the official Unit package installed:
Make sure to install the prerequisites for the package. In our example, it’s PHP 7.3 on Debian 10:
# apt update
# apt install ca-certificates apt-transport-https debian-archive-keyring
# curl --output /usr/share/keyrings/php-keyring.gpg \ https://packages.sury.org/php/apt.gpg
# echo "deb [signed-by=/usr/share/keyrings/php-keyring.gpg] \ https://packages.sury.org/php/ buster main" > /etc/apt/sources.list.d/php.list
# apt update
# apt install php7.3
# apt install php-dev libphp-embed
Create a staging directory for your package:
$ export UNITTMP=$(mktemp -d -p /tmp -t unit.XXXXXX) $ mkdir -p $UNITTMP/unit-php7.3/DEBIAN $ cd $UNITTMP
This creates a folder structure fit for dpkg-deb; the DEBIAN folder will store the package definition.
Run unitd --version and note the ./configure flags for later use, omitting
--ld-opt
and--njs
:$ unitd --version unit version: 1.34.0 configured as ./configure FLAGS
Download Unit’s sources, configure and build your custom module, then put it where Unit will find it:
$ curl -O https://sources.nginx.org/unit/unit-1.34.0.tar.gz $ tar xzf unit-1.34.0.tar.gz # Puts Unit's sources in the unit-1.34.0 subdirectory $ cd unit-1.34.0 $ ./configure FLAGS W/O --LD-OPT & --NJS # Use the ./configure flags noted in the previous step $ ./configure php --module=php7.3 --config=php-config # Configures the module itself $ make php7.3 # Builds the module in the build/ subdirectory $ mkdir -p $UNITTMP/unit-php7.3/MODULESPATH # Use the module path set by ./configure or by default $ mv build/php7.3.unit.so $UNITTMP/unit-php7.3/MODULESPATH # Adds the module to the package
Create a $UNITTMP/unit-php7.3/DEBIAN/control file, listing unit with other dependencies:
Package: unit-php7.3 Version: 1.34.0 Comment0: Use Unit's package version for consistency: 'apt show unit | grep Version' Architecture: amd64 Comment1: To get current architecture, run 'dpkg --print-architecture' Comment2: For a list of other options, run 'dpkg-architecture -L' Depends: unit (= 1.34.0-1~buster), php7.3, libphp-embed Comment3: Specify Unit's package version to avoid issues when Unit updates Comment4: Again, run 'apt show unit | grep Version' to get this value Maintainer: Jane Doe <j.doe@example.com> Description: Custom PHP 7.3 language module for NGINX Unit 1.34.0
Save and close the file.
Build and install the package:
$ dpkg-deb -b $UNITTMP/unit-php7.3 # dpkg -i $UNITTMP/unit-php7.3.deb
Assuming you are packaging for the current system and have the official Unit package installed:
Make sure to install the prerequisites for the package. In our example, it’s PHP 7.3 on Fedora 30:
# yum install -y php-7.3.8
# yum install php-devel php-embedded
Install RPM development tools and prepare the directory structure:
# yum install -y rpmdevtools
$ rpmdev-setuptree
Create a .spec file to store build commands for your custom package:
$ cd ~/rpmbuild/SPECS
$ rpmdev-newspec unit-php7.3
Run unitd --version and note the ./configure flags for later use, omitting
--ld-opt
and--njs
:$ unitd --version unit version: 1.34.0 configured as ./configure FLAGS
Edit the unit-php7.3.spec file, adding the commands that download Unit’s sources, configure and build your custom module, then put it where Unit will find it:
Name: unit-php7.3 Version: 1.34.0 # Use Unit's package version for consistency: 'yum info unit | grep Version' Release: 1%{?dist} Summary: Custom language module for NGINX Unit License: ASL 2.0 # Unit uses ASL 2.0; your license depends on the language you are packaging URL: https://example.com BuildRequires: gcc BuildRequires: make BuildRequires: php-devel BuildRequires: php-embedded Requires: unit = 1.34.0 # Specify Unit's package version to avoid issues when Unit updates # Again, run 'yum info unit | grep Version' to get this value Requires: php >= 7.3 Requires: php-embedded %description Custom language module for NGINX Unit 1.34.0 (https://unit.nginx.org). Maintainer: Jane Doe <j.doe@example.com> %prep curl -O https://sources.nginx.org/unit/unit-1.34.0.tar.gz # Downloads Unit's sources tar --strip-components=1 -xzf unit-1.34.0.tar.gz # Extracts them locally for compilation steps in the %build section %build ./configure FLAGS W/O --LD-OPT & --NJS # Configures the build; use the ./configure flags noted in the previous step ./configure php --module=php7.3 --config=php-config # Configures the module itself make php7.3 # Builds the module %install DESTDIR=%{buildroot} make php7.3-install # Adds the module to the package %files %attr(0755, root, root) "MODULESPATH/php7.3.unit.so" # Lists the module as package contents to include it in the package build # Use the module path set by ./configure or by default
Save and close the file.
Build and install the package:
$ rpmbuild -bb unit-php7.3.spec ... Wrote: /home/user/rpmbuild/RPMS/<arch>/unit-php7.3-<moduleversion>.<arch>.rpm ...
# yum install -y /home/user/rpmbuild/RPMS/<arch>/unit-php7.3-<moduleversion>.<arch>.rpm