Creating Installable Packages for Dynamic Modules
NGINX 1.11.5 and NGINX Plus R11 introduced support for compiling dynamic modules independently of NGINX itself. This allows users of NGINX and NGINX Plus to use the official builds from the NGINX, Inc. repositories and load in the dynamic modules they need. There are several sources of dynamic modules:
- Official repository of prebuilt open source NGINX packages and modules
- Official repository of NGINX Plus packages and modules
- NGINX Plus Certified Modules
- Third‑party (community) modules
This blog focuses on the use of third‑party dynamic modules with NGINX and NGINX Plus. We discuss best practices for building, deploying, and upgrading dynamic modules in a production environment.
The Problem with .so Files
When you compile a dynamic module, the raw output is a shared object (.so file). At startup and reload, NGINX and NGINX Plus load each of the shared objects specified by a load_module
directive. Shared objects are typically loaded from /etc/nginx/modules.
Dynamic modules are binary‑compatible with the official builds of NGINX and NGINX Plus. However, this binary compatibility has limitations. Dynamic modules must be compiled against the same version of NGINX they are loaded into. For NGINX Plus, dynamic modules must be compiled against the open source version that NGINX Plus is built on. This means that upgrading NGINX or NGINX Plus without first installing a new version of the dynamic module built against the matching version results in a failed upgrade.
Manually managing the dependency between NGINX and its dynamic modules is error‑prone. Dynamic module .so files do not indicate which version of NGINX they were built against, which makes the process of manually copying them around somewhat precarious. In a development environment this is generally acceptable, but for production environments dependencies need to be protected and upgrades automated.
The goal is for all dynamic modules to be automatically upgraded when you upgrade NGINX or NGINX Plus, regardless of whether the module was provided by NGINX, a Certified Module vendor, or a third‑party provider.
Packaging Dynamic Modules with Dependencies
If you use the official repositories for NGINX or NGINX Plus then you are already familiar with using a package manager to install and upgrade NGINX – yum
for Red Hat/CentOS, apt
for Ubuntu/Debian. The official NGINX and NGINX Plus repositories also contain installable packages for a number of dynamic modules. The metadata of a dynamic module package indicates the NGINX version the module was compiled against, automatically triggering an upgrade of the module during NGINX or NGINX Plus upgrade.
Using installable packages for third‑party dynamic modules is the key to honoring the dependency with NGINX, avoiding upgrade failures, and facilitating seamless upgrades.
NGINX, Inc. uses automated tooling to create the dynamic module packages for our official repositories. This tooling, called pkg‑oss can also be used to create installable packages for third‑party modules.
You can use the pkg‑oss tooling to create an installable package for any dynamic module. It also includes a script, build_module.sh, that automates the process, as an example of how to create an installable package with the correct dependency on NGINX or NGINX Plus. Simply specify the version of NGINX or NGINX Plus and the location of the dynamic module sources. The module sources may be on the local disk, point at a GitHub repo, or be a general download link. The following example builds the RTMP module for NGINX Plus R11 on Ubuntu/Debian.
$ wget ttp://hg.nginx.org/pkg-oss/raw-file/tip/build_module.sh
$ chmod a+x build_module.sh
$ ./build_module.sh -r 11 https://github.com/arut/nginx-rtmp-module.git
...
build_module.sh: INFO: Module packages created
~/debuild/nginx-plus-module-rtmp_1.11.5_amd64.deb
~/debuild/nginx-plus-module-rtmp-dbg_1.11.5_amd64.deb
The filename indicates the module was built against the base NGINX version for NGINX Plus R11 (1.11.5
), and we can confirm that by examining the package metadata.
$ dpkg-deb -f ~/debuild/nginx-plus-module-rtmp_1.11.5_amd64.deb Depends
libc6 (>= 2.14), nginx-plus (>> 1.11.4), nginx-plus (<< 1.11.6)
When using the build_module.sh script, take note of the following points.
-
Run the script in a build environment
In a production environment, it is best practice to install only the software necessary for correct, which does not include tools required for compiling and packaging dynamic modules. We recommend running the build_module.sh script in a separate build environment, but on the same platform as production. -
The script does not work for every module
The script has been tested successfully on the vast majority of third‑party modules available for NGINX. It even attempts to upgrade static modules to dynamic modules on the fly. However, some modules have additional compile‑time dependencies that the script cannot predict, or need to be packaged with other software components. -
Installable packages are not intended for redistribution
The script creates installable packages for internal use. There is no copyright, license, or documentation included in the package. If you are planning to redistribute a module as an installable package then you can use the pkg‑oss tooling to define a custom package. -
Seamless upgrades require a
yum
orapt
repository
The script provides a convenient way of building installable packages for dynamic modules, but it does not automatically provide a seamless upgrade solution unless the package is installed from ayum
orapt
repository. The remainder of this article describes how to achieve seamless upgrades.
Setting Up a Private Repository for Seamless Upgrades
Many organizations use private repositories for distributing software. After copying the .deb/.rpm files produced by the NGINX pkg‑oss tooling to such a repository, you can install, remove, and upgrade dynamic modules with the same package manager you use to install NGINX and NGINX Plus. If you do not have a private repository, then it is a simple exercise to create one locally on the server.
To illustrate this process we show how to create a private repository for Ubuntu/Debian and Red Hat/CentOS so that our dynamic module can be installed with apt(8) or yum(8) respectively. Note that these steps require root access. Also, we’ve omitted the command prompt in this section to facilitate copying and pasting.
-
Prepare dependencies and create the local repository for the package manager.
-
On Ubuntu/Debian systems:
mkdir /opt/deb
echo "deb file:/opt deb/" > /etc/apt/sources.list.d/local.list -
On Red Hat/CentOS systems:
yum install createrepo
mkdir /opt/rpm
cat << EOF > /etc/yum.repos.d/localrepo.repo
[localrepo]
name=Dynamic modules for NGINX
baseurl=file:///opt/rpm
gpgcheck=0
enabled=1
EOF
-
-
Copy the installable package for the dynamic module to the local repository.
-
On Ubuntu/Debian systems:
cp ~/debuild/nginx-plus-module-rtmp_1.11.5_amd64.deb /opt/deb
-
On Red Hat/CentOS systems:
cp ~/rpmbuild/RPMS/x86_64/nginx-plus-module-rtmp-1.11.5-1.el7.centos.ngx.x86_64.rpm /opt/rpm
-
-
Update the package manager to be aware of the dynamic module package.
-
On Ubuntu/Debian systems:
cd /opt && dpkg-scanpackages deb | gzip > deb/Packages.gz
apt-get update -
On Red Hat/CentOS systems:
createrepo -v /opt/rpm
yum clean all
yum update
-
-
Repeat Steps 2 and 3 for each module.
Installing a Module from a Private Repository
When a dynamic module is stored in a private repository, you can use the local package manager to install it.
-
On Ubuntu/Debian systems:
$ apt-get install nginx-plus-module-rtmp
-
On Red Hat/CentOS systems:
$ yum install nginx-plus-module-rtmp
Note that the name of the package is the same as the filename produced by the build script, without the version and platform information.
When installation is complete, a banner explains how to configure NGINX to load the newly installed dynamic module.
----------------------------------------------------------------------
The rtmp dynamic module for nginx has been installed.
To enable this module, add the following to /etc/nginx/nginx.conf
and reload nginx:
load_module modules/ngx_rtmp_module.so;
----------------------------------------------------------------------
Seamless Upgrade
With the dynamic module installed in this way, you are protected from version mismatch during upgrades of NGINX or NGINX Plus. If an upgrade of NGINX or NGINX Plus is attempted before installed dynamic modules are upgraded, the local package manager reports the problem.
-
On Ubuntu/Debian systems:
$ apt install nginx-plus
...
The following packages will be REMOVED
nginx-plus-module-rtmp
The following packages will be upgraded:
nginx-plus
Do you want to continue? [Y/n] -
On Red Hat/CentOS systems:
$ yum install nginx-plus
...
Error: Package: nginx-plus-module-rtmp-1.11.5-1.el7.centos.ngx.x86_64 (@localrepo)
Requires: nginx-plus = 1.11.5
To ensure a seamless upgrade, first build a new version of the dynamic module against the version of NGINX or NGINX Plus you intend to upgrade to. The following example shows the steps required to upgrade NGINX Plus from R11 to R12 with the RTMP dynamic module installed.
-
Build the dynamic module for NGINX Plus R12.
$ ./build_module.sh -r 12 https://github.com/arut/nginx-rtmp-module.git
...
build_module.sh: INFO: Module packages created
~/debuild/nginx-plus-module-rtmp_1.11.10_amd64.deb
~/debuild/nginx-plus-module-rtmp-dbg_1.11.10_amd64.deb -
Repeat Steps 2 and 3 from Setting Up a Private Repository for Seamless Upgrades to update the private repository with the new dynamic module.
-
Upgrade NGINX Plus.
-
On Ubuntu/Debian systems:
$ apt-get install nginx-plus
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be upgraded:
nginx-plus nginx-plus-module-rtmp
2 to upgrade, 0 to newly install, 0 to remove
Need to get 2,571 kB/2,731 kB of archives.
After this operation, 411 kB of additional disk space will be used.
Do you want to continue? [Y/n] -
On Red Hat/CentOS systems:
$ yum install nginx-plus
...
Resolving Dependencies
--> Running transaction check
---> Package nginx-plus.x86_64 0:1.11.5-1.el7.ngx will be updated
--> Processing Dependency:
---> Package nginx-plus-module-rtmp.x86_64 0:1.11.5-1.el7.centos.ngx will be updated
--> Finished Dependency ResolutionDependencies Resolved
=========================================================================
Package Arch Version Repository Size
=========================================================================
Updating:
nginx-plus x86_64 1.11.10-3.el7.ngx nginx-plus 2.4 M
Updating for dependencies:
nginx-plus-module-rtmp x86_64 1.11.10-1.el7.centos.ngx localrepo 176 kTransaction Summary
=========================================================================
Upgrade 1 Package (+1 Dependent package)Total download size: 2.6 M
Is this ok [y/d/N]:
-
Summary
Dynamic modules for NGINX and NGINX Plus enable you to compile only the specific extensions you require while taking advantage of the prebuilt and tested packages from NGINX, Inc. The pkg‑oss tooling and the build_module.sh script provide a straightforward solution to creating, installing, and upgrading third‑party modules for production deployments of NGINX and NGINX Plus.
The post Creating Installable Packages for Dynamic Modules appeared first on NGINX.
Leave a Reply