NGINX Unit

Working With Language Modules§

Languages supported by Unit fall into these two categories:

  • External (Go, Node.js): Run outside Unit and communicate with it via wrapper packages.
  • Embedded (Java, Perl, PHP, Python, Ruby): 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 build into your apps. The package is available from the official Unit repository; you can also build it with Unit sources for a custom version of Go.

In Node.js, Unit is supported by an npm-hosted package that your apps require in their code among other dependencies. To make it available in your system, install it from the npm repository.

Embedded Language Modules§

Embedded modules are shared libraries that Unit loads at startup. Query Unit to find them in your system:

# unitd -h             # Run as root to check default log and module paths
       ...

      --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   # Check whether the defaults were overridden at launch
      ...
      unit: main v1.11.0 [unitd --log /runtime/path/to/unit.log --modules /runtime/modules/path/ ... ]

$ ls /path/to/modules

      java.unit.so  perl.unit.so  php.unit.so  python.unit.so  ruby.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 to your scenario as needed. For Debian, Ubuntu, and other .deb-based distributions, see the steps here; for CentOS, Fedora, RHEL, and other .rpm-based distributions, follow the steps here.

Note

For elaborate Unit packaging examples, refer to our packaging system sources.

.deb Packages§

Assuming you are packaging for the current system and have the official Unit package installed:

  1. 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
    # curl -sL https://packages.sury.org/php/apt.gpg | apt-key add -
    # echo "deb 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
    
  2. 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.

  3. Run unitd --version as root and note the ./configure flags for later use, omitting --ld-opt:

    # unitd --version
    
        unit version: 1.11.0
        configured as ./configure <./configure flags>
    
  4. Download Unit sources, configure and build your custom module, then put it where Unit will find it:

    $ curl -O https://unit.nginx.org/download/unit-1.11.0.tar.gz
    $ tar xzf unit-1.11.0.tar.gz                                 # Puts Unit sources in the unit-1.11.0 subdirectory
    $ cd unit-1.11.0
    $ ./configure <./configure flags w/o --ld-opt>               # Configures the build; use the ./configure flags from unitd output
    $ ./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/<module path>                # Use the module path from the ./configure flags
    $ mv build/php7.3.unit.so $UNITTMP/unit-php7.3/<module path> # Adds the module to the package
    
  5. Create a control file in the $UNITTMP/unit-php7.3/DEBIAN/ directory; list unit with other dependencies:

    Package: unit-php7.3
    Version: 1.11.0
    Comment0: Use Unit 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.11.0), php7.3, libphp-embed
    Comment3: Specify Unit 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.11.0
    

    Save and close the file.

  6. Build and install the package:

    $ dpkg-deb -b $UNITTMP/unit-php7.3
    # dpkg -i $UNITTMP/unit-7.3.deb
    

.rpm Packages§

Assuming you are packaging for the current system and have the official Unit package installed:

  1. 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
    
  2. Install RPM development tools and prepare the directory structure:

    # yum install -y rpmdevtools
    $ rpmdev-setuptree
    
  3. Create a .spec file to store build commands for your custom package:

    $ cd ~/rpmbuild/SPECS
    $ rpmdev-newspec unit-php7.3
    
  4. Run unitd --version as root and note the ./configure flags for later use, omitting --ld-opt:

    # unitd --version
    
        unit version: 1.11.0
        configured as ./configure <./configure flags>
    
  5. Edit the unit-php7.3.spec file, adding the commands that download Unit sources, configure and build your custom module, then put it where Unit will find it:

    Name:           unit-php7.3
    Version:        1.11.0
    # Use Unit 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.11.0
    # Specify Unit 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.11.0 (https://unit.nginx.org).
    
    Maintainer: Jane Doe <j.doe@example.com>
    
    %prep
    curl -O https://unit.nginx.org/download/unit-1.11.0.tar.gz
    # Downloads Unit sources
    tar --strip-components=1 -xzf unit-1.11.0.tar.gz
    # Extracts them locally for compilation steps in the %build section
    
    %build
    ./configure <./configure flags w/o --ld-opt>
    # Configures the build; use the ./configure flags from unitd output
    ./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) "<module path>/php7.3.unit.so"
    # Lists the module as package contents to include it in the package build
    # Use the module path from the ./configure flags
    

    Save and close the file.

  6. Build and install the package:

    $ rpmbuild -bb unit-php7.3.spec
    
        ...
        Wrote: /home/user/rpmbuild/RPMS/<arch>/unit-php7.3-<version>.<arch>.rpm
        ...
    
    # yum install -y /home/user/rpmbuild/RPMS/<arch>/unit-php7.3-<version>.<arch>.rpm