nginx-buildでnginxをビルドしよう

この記事はnginx Advent Calendar 2014 の1日目の投稿です。

# nginx-build

[nginx-build](https://github.com/cubicdaiya/nginx-build)はGoで書かれたnginxをビルドするためのツールです。Goの環境が整っていれば`go get`でインストールすることができます。

```
go get -u github.com/cubicdaiya/nginx-build
```

また、Goがインストールされてない環境向けに↓でビルド済みバイナリ(linuxとmacの64bit版)を用意しています。


https://github.com/cubicdaiya/nginx-build/releases

## nginx-buildにできること

[nginx-build](https://github.com/cubicdaiya/nginx-build)は主にnginxのビルドにまつわる以下のタスクの大部分を自動化します。

 * nginxのソースコードのダウンロード
 * configureのオプション指定
 * 依存ライブラリ(PCRE、ZLIB、OpenSSL)のダウンロード、組み込み
 * サードパーティーモジュールのダウンロード、組み込み、バージョン管理

筆者は過去にnginxのサードパーティモジュールを開発したり、数十台のnginxサーバを運用していたので、これらのタスクを頻繁に実行していました。しかし、ある時あまりにも面倒になったのでこの作業を自動化するプログラムをGoで書きました。それが[nginx-build](https://github.com/cubicdaiya/nginx-build)です。(最初はshで書き始めましたが、メンテするのが大変なのですぐにやめました)

## nginx-buildでnginxをビルドする

前置きはほどほどにして本題に入りましょう。まずはnginxをビルドするためのワーキングディレクトリを作成します。(この作業は近い将来やらなくてもいいようにする予定です)

```bash
$ mkdir work
```

あとは`nginx-build`コマンドを実行するだけです。

```bash
$ nginx-build -d work -clear
nginx-build: 0.0.6
Compiler: gc go1.3.3
2014/11/29 23:23:56 [warn]configure option is empty.
2014/11/29 23:23:56 Download nginx-1.7.7.....
2014/11/29 23:23:59 Extract nginx-1.7.7.tar.gz.....
2014/11/29 23:23:59 Generate configure script for nginx-1.7.7.....
2014/11/29 23:23:59 Configure nginx-1.7.7.....
2014/11/29 23:24:04 Build nginx-1.7.7.....
2014/11/29 23:24:13 Complete building nginx!
 
nginx version: nginx/1.7.7
built by gcc 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9) 
configure arguments:
 
2014/11/29 23:24:13 Enter the following command for install nginx.
 
   $ cd work/1.7.7/nginx-1.7.7
   $ sudo make install
$
```

上記のログが示しているようにnginxのソースコードをダウンロードして`configure`スクリプトの生成&実行、ビルドを行ってくれています。ただし、インストールは最後の出力が示すように自分で行う必要があります。また、`-clear`はnginxをビルドする前にワーキングディレクトリを空にするオプションです。

### 依存ライブラリの組み込み

nginxの依存ライブラリはたくさんありますが、中でも利用頻度が高いのがPCRE、ZLIB、OpenSSLの3つです。`nginx-build`はこれら3つの依存ライブラリの静的組み込みの自動化をサポートします。以下ではPCRE、ZLIB、OpenSSLを静的に組み込んでnginxをビルドしています。

```bash
$ nginx-build -d work -pcre -zlib -openssl -clear
Compiler: gc go1.3.3
2014/11/29 23:25:55 [warn]configure option is empty.
2014/11/29 23:25:55 Download pcre-8.36.....
2014/11/29 23:25:55 Download zlib-1.2.8.....
2014/11/29 23:25:55 Download openssl-1.0.1j.....
2014/11/29 23:25:55 Download nginx-1.7.7.....
2014/11/29 23:25:56 Extract zlib-1.2.8.tar.gz.....
2014/11/29 23:26:00 Extract nginx-1.7.7.tar.gz.....
2014/11/29 23:26:00 Extract pcre-8.36.tar.gz.....
2014/11/29 23:26:02 Extract openssl-1.0.1j.tar.gz.....
2014/11/29 23:26:02 Generate configure script for nginx-1.7.7.....
2014/11/29 23:26:02 Configure nginx-1.7.7.....
2014/11/29 23:26:06 Build nginx-1.7.7.....
2014/11/29 23:28:46 Complete building nginx!
 
nginx version: nginx/1.7.7
built by gcc 4.8.1 (Ubuntu/Linaro 4.8.1-10ubuntu9) 
TLS SNI support enabled
configure arguments: --with-pcre=../pcre-8.36 --with-openssl=../openssl-1.0.1j --with-zlib=../zlib-1.2.8 --with-http_ssl_module
 
2014/11/29 23:28:46 Enter the following command for install nginx.
 
   $ cd work/1.7.7/nginx-1.7.7
   $ sudo make install
$
```

### ビルド時に利用するconfigureスクリプトを指定する

`nginx-build`が完全に自動化できてないタスクの1つに`configure`オプションの生成があります。現在は例えば以下のような`configure`スクリプトを用意して、

```bash:configure.sh
#!/bin/sh

./configure \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/lock/nginx.lock \
--http-log-path=/var/log/nginx/access.log \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--with-http_stub_status_module \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--with-debug \
--with-http_ssl_module \
--with-http_gzip_static_module \
--with-http_gunzip_module \
--with-http_spdy_module \
--with-pcre-jit \
```

`-c`に`configure`スクリプトのパスを指定する必要があります。

```bash
$ nginx-build -d work -c ./configure.sh -clear
nginx-build: 0.0.6
Compiler: gc go1.4rc1
2014/12/01 00:11:54 Download nginx-1.7.7.....
2014/12/01 00:11:57 Extract nginx-1.7.7.tar.gz.....
2014/12/01 00:11:57 Generate configure script for nginx-1.7.7.....
2014/12/01 00:11:57 Configure nginx-1.7.7.....
2014/12/01 00:12:03 Build nginx-1.7.7.....
2014/12/01 00:12:08 Complete building nginx!

nginx version: nginx/1.7.7
built by clang 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
TLS SNI support enabled
configure arguments: --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --with-http_stub_status_module --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-debug --with-http_ssl_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_spdy_module --with-pcre-jit

2014/12/01 00:12:08 Enter the following command for install nginx.

   $ cd work/1.7.7/nginx-1.7.7
   $ sudo make install
$
```

### サードパーティモジュールの組み込み

サードパーティモジュールの組み込みは少し特殊です。例えば[echo-nginx-module](https://github.com/openresty/echo-nginx-module)や[headers-more-nginx-module](https://github.com/openresty/headers-more-nginx-module)を組み込む際はまず以下のようなINIファイルを用意します。

```ini:modules3rd.ini
[echo-nginx-module]
form=git
url=https://github.com/openresty/echo-nginx-module.git
rev=v0.54

[headers-more-nginx-module]
form=git
url=https://github.com/openresty/headers-more-nginx-module.git
rev=v0.25
```

セクションにモジュール名を記述し、モジュールのダウンロードに必要な情報を各セクションに追記します。各パラメータの意味は以下の通りです。

| パラメータ名|解説          |備考|
|:----------|:------------|:--|
|form       |ダウンロード形式|gitのみ|
|url        |ダウンロード先  |gitのcloneで指定するURL|
|rev        |バージョン     |gitのタグ、コミットハッシュ|

`modules3rd.ini`を`-m`に与えてビルドしてみます。

```
$ nginx-build -d work -m modules3rd.ini -clear
nginx-build: 0.0.6
Compiler: gc go1.4rc1
2014/12/01 00:14:43 [warn]configure option is empty.
2014/12/01 00:14:43 Download headers-more-nginx-module-v0.25.....
2014/12/01 00:14:43 Download echo-nginx-module-v0.54.....
2014/12/01 00:14:43 Download nginx-1.7.7.....
2014/12/01 00:14:54 Extract nginx-1.7.7.tar.gz.....
2014/12/01 00:14:54 Generate configure script for nginx-1.7.7.....
2014/12/01 00:14:54 Configure nginx-1.7.7.....
2014/12/01 00:15:01 Build nginx-1.7.7.....
2014/12/01 00:15:04 Complete building nginx!

nginx version: nginx/1.7.7
built by clang 6.0 (clang-600.0.54) (based on LLVM 3.5svn)
configure arguments: --with-cc-opt=-Wno-deprecated-declarations --add-module=../echo-nginx-module --add-module=../headers-more-nginx-module

2014/12/01 00:15:04 Enter the following command for install nginx.

   $ cd work/1.7.7/nginx-1.7.7
   $ sudo make install
$
```

無事に[echo-nginx-module](https://github.com/openresty/echo-nginx-module)と[headers-more-nginx-module](https://github.com/openresty/headers-more-nginx-module)が組み込まれました。

# まとめ

[nginx-build](https://github.com/cubicdaiya/nginx-build)を利用することでnginxのビルドにまつわる面倒事の大部分を自動化および簡略化することができます。筆者の環境ではnginxのカスタムRPMパッケージを作成する際、実際に[nginx-build](https://github.com/cubicdaiya/nginx-build)を利用して外部ライブラリやサードパーティモジュールの管理を簡略化しています。

また、昨日開催されたGo Conference 2014 autumnのLTでnginx-buildについて発表した資料(英語)が↓にあるのでよかったらご覧ください。

https://speakerdeck.com/cubicdaiya/nginx-build