nginx のモジュール追加リビルド (CentOS 7 EPEL 版)

nginx 公式や epel パッケージの nginx バイナリでは使いたいモジュールがコンパイルされていない。特に nginx-dav-ext-module(WebDAV で OPTIONS メソッドが利用可能になる)、headers-more-nginx-module(HTTPヘッダを追加したり削除したり)、nginx-ct(証明書の透明性対応ができる)を使いたいので、ソースからビルドすることにする。

前提として、使用 OS は CentOS 7 である。

nginx 公式の RPM パッケージもあるが、この記事では epel リポジトリの nginx RPM をベースに、必要なモジュールの記述を追加して SRPM からリビルドしてみる。

1. コンパイルに必要なパッケージをインストール

$ sudo yum install gperftools-devel openssl-devel pcre-devel zlib-devel GeoIP-devel gd-devel perl-devel perl-ExtUtils-Embed libxslt-devel expat-devel git

2. epel リポジトリを追加

epel リポジトリを追加する。追加済みであれば作業の必要なし。
$ sudo yum install epel-release

3. SRPM の入手

SRPM をダウンロード・インストールする。
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --enable epel-testing
$ sudo yum install @buildsys-build
$ yumdownloader --source nginx
$ rpm -ivh nginx-1.20.1-9.el7.src.rpm

今後 yum update で勝手にアップデートされないように、epel レポジトリを無効化しておく。
$ sudo yum-config-manager --disable epel\*

4. カスタマイズ

SRPM の spec ファイルを編集する。
$ vi rpmbuild/SPECS/nginx.spec

以下、nginx.spec に追加する部分を diff -u 形式で記述する。追加する3つのモジュールのうち、nginx-ct は元々 nginx に含まれていて動的モジュール化されている mod-mail と mod-stream に依存するため、これも動的モジュール化する(そうしないとビルドエラーになる)。

--- nginx.spec.orig 2021-10-19 08:55:50.000000000 +0900
+++ nginx.spec 2022-04-28 09:38:22.327765589 +0900
@@ -92,6 +92,8 @@
%endif
BuildRequires: pcre-devel
BuildRequires: zlib-devel
+BuildRequires: expat-devel
+BuildRequires: git

Requires: nginx-filesystem = %{epoch}:%{version}-%{release}
%if 0%{?el7}
@@ -107,6 +109,7 @@

Requires: openssl
Requires: pcre
+Requires: expat
Requires(pre): nginx-filesystem
%if 0%{?with_mailcap_mimetypes}
Requires: nginx-mimetypes
@@ -140,6 +143,7 @@
Requires: nginx-mod-http-xslt-filter = %{epoch}:%{version}-%{release}
Requires: nginx-mod-mail = %{epoch}:%{version}-%{release}
Requires: nginx-mod-stream = %{epoch}:%{version}-%{release}
+Requires: nginx-mod-ct = %{epoch}:%{version}-%{release}

%description all-modules
Meta package that installs all available nginx modules.
@@ -236,12 +240,22 @@
%description mod-devel
%{summary}.

+%package mod-ct
+Summary: Nginx ct modules
+Requires: nginx
+
+%description mod-ct
+%{summary}.
+

%prep
# Combine all keys from upstream into one file
cat %{S:2} %{S:3} %{S:4} > %{_builddir}/%{name}.gpg
%{gpgverify} --keyring='%{_builddir}/%{name}.gpg' --signature='%{SOURCE1}' --data='%{SOURCE0}'
%autosetup -p1
+git clone https://github.com/arut/nginx-dav-ext-module.git
+git clone https://github.com/openresty/headers-more-nginx-module.git
+git clone https://github.com/grahamedgecombe/nginx-ct.git
cp %{SOURCE200} %{SOURCE210} %{SOURCE10} %{SOURCE12} .

%if 0%{?rhel} > 0 && 0%{?rhel} < 8
@@ -322,6 +336,9 @@
--with-stream=dynamic \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
+ --add-module=./nginx-dav-ext-module \
+ --add-module=./headers-more-nginx-module \
+ --add-dynamic-module=./nginx-ct \
--with-threads \
--with-cc-opt="%{optflags} $(pcre-config --cflags)" \
--with-ld-opt="$nginx_ldopts"; then
@@ -421,6 +438,14 @@
> %{buildroot}%{nginx_moduleconfdir}/mod-mail.conf
echo 'load_module "%{nginx_moduledir}/ngx_stream_module.so";' \
> %{buildroot}%{nginx_moduleconfdir}/mod-stream.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-ct.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_http_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-http-ct.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_mail_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-mail_ct.conf
+echo 'load_module "%{_libdir}/nginx/modules/ngx_stream_ssl_ct_module.so";' \
+ > %{buildroot}%{_datadir}/nginx/modules/mod-stream_ct.conf

# Install files for supporting nginx module builds
## Install source files
@@ -479,6 +504,11 @@
/usr/bin/systemctl reload nginx.service >/dev/null 2>&1 || :
fi

+%post mod-ct
+if [ $1 -eq 1 ]; then
+ /usr/bin/systemctl reload nginx.service >/dev/null 2>&1 || :
+fi
+
%preun
%systemd_preun nginx.service

@@ -576,6 +606,16 @@
%{_fileattrsdir}/nginxmods.attr
%{nginx_srcdir}/

+%files mod-ct
+%{_datadir}/nginx/modules/mod-ct.conf
+%{_datadir}/nginx/modules/mod-http-ct.conf
+%{_datadir}/nginx/modules/mod-mail_ct.conf
+%{_datadir}/nginx/modules/mod-stream_ct.conf
+%{_libdir}/nginx/modules/ngx_http_ssl_ct_module.so
+%{_libdir}/nginx/modules/ngx_mail_ssl_ct_module.so
+%{_libdir}/nginx/modules/ngx_ssl_ct_module.so
+%{_libdir}/nginx/modules/ngx_stream_ssl_ct_module.so
+

%changelog
* Mon Oct 18 2021 Felix Kaechele <heffer@fedoraproject.org> - 1:1.20.1-9

5. ビルド、インストール

ビルドを実行する。
$ rpmbuild --with geoip -ba rpmbuild/SPECS/nginx.spec

RPM が出来上がったらインストールする。すでに EPEL や nginx 公式 RPM をインストールしてしまっている場合は、先に削除しておくこと。

既存パッケージの削除:
$ sudo yum erase `rpm -qa | grep nginx`

カスタマイズした RPM のインストール:
$ sudo yum localinstall rpmbuild/RPMS/x86_64/nginx-1.*.rpm rpmbuild/RPMS/x86_64/nginx-mod-*.rpm rpmbuild/RPMS/noarch/nginx-*.rpm

6. 起動

デーモンを起動する。
$ sudo systemctl enable nginx
$ sudo systemctl start nginx