akishin999の日記

調べた事などを書いて行きます。

ngx_set_misc モジュールを組み込んだ Nginx の RPM を作成する

Nginx に URI エンコード&デコードや Base64 エンコード&デコードなどの機能を追加する ngx_set_misc モジュールを組み込んだ RPM を作成してみたのでメモ。

Set Misc | NGINX
http://mogile.web.fc2.com/nginx_wiki/modules/set_misc.html

openresty/set-misc-nginx-module
https://github.com/openresty/set-misc-nginx-module

素直に OpenResty 使えば?という声が聞こえてきそうな気もしますが、ここでは敢えて公式の SRPM に組み込んでみました。
環境は CentOS 7.1 x86_64 です。

# cat /etc/redhat-release
CentOS Linux release 7.1.1503 (Core)
# uname -a
Linux centos7-test01 3.10.0-229.el7.x86_64 #1 SMP Fri Mar 6 11:36:42 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

RPM 作成環境の構築

まずは RPM 作成環境の構築です。
必要なパッケージをインストール。

$ su -
# yum install -y gcc rpmdevtools redhat-rpm-config

RPM 作成用ユーザを追加。

# useradd rpmdevel
# passwd rpmdevel

作成したユーザになって rpmdev-setuptree コマンドを実行。

# su - rpmdevel
$ rpmdev-setuptree

以下のディレクトリと設定ファイルが作成されました。

$ ls -ld ~/rpmbuild/
drwxrwxr-x. 7 rpmdevel rpmdevel 67 1220 09:38 /home/rpmdevel/rpmbuild/
$ ls -la ~/.rpmmacros
-rw-rw-r--. 1 rpmdevel rpmdevel 620 1220 09:38 /home/rpmdevel/.rpmmacros

これで RPM 作成の準備は完了です。

Nginx のビルド

Nginx 公式のCentOSSRPM は以下から辿っていくとダウンロードできます。

http://nginx.org/packages/centos/

CentOS 7 用は以下。

http://nginx.org/packages/centos/7/SRPMS/nginx-1.8.0-1.el7.ngx.src.rpm

RPM 作成用ユーザで SRPM を取得してインストールします。

$ rpm -ivh http://nginx.org/packages/centos/7/SRPMS/nginx-1.8.0-1.el7.ngx.src.rpm

SRPM をインストールしたら「~rpmbuild/SPECS/nginx.spec」内の「BuildRequires」の部分を確認し、一旦 root になって必要なパッケージをインストールします。

$ su -
# yum install -y openssl-devel zlib-devel pcre-devel

再度 RPM 作成用ユーザに戻り、ngx_set_misc モジュールをダウンロードして展開します。

# su - rpmdevel
$ wget https://github.com/openresty/set-misc-nginx-module/archive/v0.29.tar.gz
$ tar xzf v0.29.tar.gz

モジュールのビルドには ngx_devel_kit も必要なのでこちらもダウンロードして展開。

$ wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz
$ tar xzf v0.2.19.tar.gz

それぞれ展開後のパスを確認しておきます。

$ ls -ld /home/rpmdevel/set-misc-nginx-module-0.29/
drwxrwxr-x. 6 rpmdevel rpmdevel 4096  622 22:08 /home/rpmdevel/set-misc-nginx-module-0.29/

$ ls -ld /home/rpmdevel/ngx_devel_kit-0.2.19/
drwxrwxr-x. 9 rpmdevel rpmdevel 4096  926  2013 /home/rpmdevel/ngx_devel_kit-0.2.19/

SRPM に含まれていた SPEC ファイルを編集。

$ vi ~/rpmbuild/SPECS/nginx.spec

「./configure」のところに以下のように「--add-module」を使って先ほど展開した ngx_devel_kit と ngx_set_misc モジュールのパスを指定します。

--add-module=/home/rpmdevel/ngx_devel_kit-0.2.19 \
--add-module=/home/rpmdevel/set-misc-nginx-module-0.29 \

nginx.spec では「./configure」が 2 回定義されているので、ターミナルを狭くして編集している場合など見逃さないように注意が必要です(--with-debug の付いている方と付いていない方があります)。
debug の方は今は特にいらない気もしますが、ここでは取り敢えず両方につけておきました。

追記後の「./configure」の部分は以下のようになります。

%build
./configure \
        --prefix=%{_sysconfdir}/nginx \
        --sbin-path=%{_sbindir}/nginx \
        --conf-path=%{_sysconfdir}/nginx/nginx.conf \
        --error-log-path=%{_localstatedir}/log/nginx/error.log \
        --http-log-path=%{_localstatedir}/log/nginx/access.log \
        --pid-path=%{_localstatedir}/run/nginx.pid \
        --lock-path=%{_localstatedir}/run/nginx.lock \
        --http-client-body-temp-path=%{_localstatedir}/cache/nginx/client_temp \
        --http-proxy-temp-path=%{_localstatedir}/cache/nginx/proxy_temp \
        --http-fastcgi-temp-path=%{_localstatedir}/cache/nginx/fastcgi_temp \
        --http-uwsgi-temp-path=%{_localstatedir}/cache/nginx/uwsgi_temp \
        --http-scgi-temp-path=%{_localstatedir}/cache/nginx/scgi_temp \
        --user=%{nginx_user} \
        --group=%{nginx_group} \
        --with-http_ssl_module \
        --with-http_realip_module \
        --with-http_addition_module \
        --with-http_sub_module \
        --with-http_dav_module \
        --with-http_flv_module \
        --with-http_mp4_module \
        --with-http_gunzip_module \
        --with-http_gzip_static_module \
        --with-http_random_index_module \
        --with-http_secure_link_module \
        --with-http_stub_status_module \
        --with-http_auth_request_module \
        --with-mail \
        --with-mail_ssl_module \
        --with-file-aio \
        --with-ipv6 \
        --with-debug \
        --add-module=/home/rpmdevel/ngx_devel_kit-0.2.19 \
        --add-module=/home/rpmdevel/set-misc-nginx-module-0.29 \
        %{?with_spdy:--with-http_spdy_module} \
        --with-cc-opt="%{optflags} $(pcre-config --cflags)" \
        $*
make %{?_smp_mflags}
%{__mv} %{_builddir}/%{name}-%{version}/objs/nginx \
        %{_builddir}/%{name}-%{version}/objs/nginx.debug
./configure \
        --prefix=%{_sysconfdir}/nginx \
        --sbin-path=%{_sbindir}/nginx \
        --conf-path=%{_sysconfdir}/nginx/nginx.conf \
        --error-log-path=%{_localstatedir}/log/nginx/error.log \
        --http-log-path=%{_localstatedir}/log/nginx/access.log \
        --pid-path=%{_localstatedir}/run/nginx.pid \
        --lock-path=%{_localstatedir}/run/nginx.lock \
        --http-client-body-temp-path=%{_localstatedir}/cache/nginx/client_temp \
        --http-proxy-temp-path=%{_localstatedir}/cache/nginx/proxy_temp \
        --http-fastcgi-temp-path=%{_localstatedir}/cache/nginx/fastcgi_temp \
        --http-uwsgi-temp-path=%{_localstatedir}/cache/nginx/uwsgi_temp \
        --http-scgi-temp-path=%{_localstatedir}/cache/nginx/scgi_temp \
        --user=%{nginx_user} \
        --group=%{nginx_group} \
        --with-http_ssl_module \
        --with-http_realip_module \
        --with-http_addition_module \
        --with-http_sub_module \
        --with-http_dav_module \
        --with-http_flv_module \
        --with-http_mp4_module \
        --with-http_gunzip_module \
        --with-http_gzip_static_module \
        --with-http_random_index_module \
        --with-http_secure_link_module \
        --with-http_stub_status_module \
        --with-http_auth_request_module \
        --with-mail \
        --with-mail_ssl_module \
        --with-file-aio \
        --with-ipv6 \
        --add-module=/home/rpmdevel/ngx_devel_kit-0.2.19 \
        --add-module=/home/rpmdevel/set-misc-nginx-module-0.29 \
        %{?with_spdy:--with-http_spdy_module} \
        --with-cc-opt="%{optflags} $(pcre-config --cflags)" \
        $*
make %{?_smp_mflags}

これで準備はできたので rpmbuild コマンドを実行します。

$ rpmbuild -ba ~/rpmbuild/SPECS/nginx.spec

以下の RPM ファイルが作成されました。

$ ll ~/rpmbuild/RPMS/x86_64/
合計 3288
-rw-rw-r--. 1 rpmdevel rpmdevel  380228 1220 10:00 nginx-1.8.0-1.el7.centos.ngx.x86_64.rpm
-rw-rw-r--. 1 rpmdevel rpmdevel 1753000 1220 10:00 nginx-debug-1.8.0-1.el7.centos.ngx.x86_64.rpm
-rw-rw-r--. 1 rpmdevel rpmdevel 1232812 1220 10:00 nginx-debuginfo-1.8.0-1.el7.centos.ngx.x86_64.rpm

念の為ビルドされたバイナリを -V してみると、表示されるオプションに先ほど spec ファイル内で指定した --add-module が追加されている事を確認できます。

$ ./rpmbuild/BUILD/nginx-1.8.0/objs/nginx -V
nginx version: nginx/1.8.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)
built with OpenSSL 1.0.1e-fips 11 Feb 2013
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-http_ssl_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module --with-mail --with-mail_ssl_module --with-file-aio --with-ipv6 --add-module=/home/rpmdevel/ngx_devel_kit-0.2.19 --add-module=/home/rpmdevel/set-misc-nginx-module-0.29 --with-http_spdy_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic'

問題無さそうです。

ちょっとだけ使ってみる

作成した RPM ファイルを別サーバに持って行ってインストールしてみます。

$ su -
# yum install -y ./nginx-1.8.0-1.el7.centos.ngx.x86_64.rpm

問題なくインストールされたら、動作確認のため /etc/nginx/conf.d/default.conf を編集します。

# vi /etc/nginx/conf.d/default.conf

いくつか簡単に試せるディレクティブを使ってみます。
default.conf 内の server ブロックの中に以下の設定を追加。

location /today {
    set_local_today $today;
    rewrite ^(.*)$ http://localhost?date=$today permanent;
}

location /base64encode {
    set $a $arg_str;
    set_encode_base64 $a;
    set $args "";
    rewrite ^(.*)$ http://localhost?result=$a permanent;
}

location /base64decode {
    set $a $arg_str;
    set_decode_base64 $b $a;
    set $args "";
    rewrite ^(.*)$ http://localhost?result=$b permanent;
}

設定に問題がないか確認してから Nginx を再起動します。
systemctl 使った方がいいのかも知れませんが取り敢えず使い慣れた service で・・・。

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# service nginx restart
Redirecting to /bin/systemctl restart  nginx.service

curl で動作確認してみます。
まずは set_local_today ディレクティブ。

# curl -I -L http://localhost/today
HTTP/1.1 301 Moved Permanently
Server: nginx/1.8.0
Date: Sun, 20 Dec 2015 08:33:25 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: http://localhost?date=2015-12-20

HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Sun, 20 Dec 2015 08:33:25 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 20 Dec 2015 01:34:20 GMT
Connection: keep-alive
ETag: "5676059c-264"
Accept-Ranges: bytes

リダイレクト先(Location) の部分に実行日が設定されているのが判ります。
次は set_encode_base64 ディレクティブ。

# curl -I -L http://localhost/base64encode?str=hello
HTTP/1.1 301 Moved Permanently
Server: nginx/1.8.0
Date: Sun, 20 Dec 2015 08:33:32 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: http://localhost?result=aGVsbG8=

HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Sun, 20 Dec 2015 08:33:32 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 20 Dec 2015 01:34:20 GMT
Connection: keep-alive
ETag: "5676059c-264"
Accept-Ranges: bytes

Base64 エンコードされた文字列が返って来ました。
上で返って来た文字列を使って今度は set_decode_base64 ディレクティブを使ってみます。

# curl -I -L http://localhost/base64decode?str=aGVsbG8=
HTTP/1.1 301 Moved Permanently
Server: nginx/1.8.0
Date: Sun, 20 Dec 2015 08:33:40 GMT
Content-Type: text/html
Content-Length: 184
Connection: keep-alive
Location: http://localhost?result=hello

HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Sun, 20 Dec 2015 08:33:40 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Sun, 20 Dec 2015 01:34:20 GMT
Connection: keep-alive
ETag: "5676059c-264"
Accept-Ranges: bytes

ちゃんと元の文字列に戻っています。

ngx_set_misc モジュールでは他にもいろいろなディレクティブが追加されます。

https://github.com/openresty/set-misc-nginx-module#directives

上手に使えばアプリケーションに少し楽をさせてあげることも出来そうです。