从源代码构建 Nginx
首先
因为有机会编写Nginx模块,所以现在我来写一下从源代码构建Nginx的方法。虽然现在有点晚了。本来我想一直写到制作模块的部分,但是进展不大,所以暂时搁置了。这篇文章比较简单。
如果只需要教授指令的人,请点击这里,写字不必要。
行动指南
根据我看到的 Qiita 上的其他 nginx 构建文章,似乎有一种名为 nginx-build 的构建辅助工具,但在本文中,我会手动逐个下载。我还会使用源代码而非预编译软件包来构建所需的库。
如果在我手上的 Ubuntu 22.04 上使用 “apt install nginx” 安装 nginx,则构建选项如下。我计划将其配置成相同的构建,并替换正在运行的二进制文件。尽管有些模块我不打算使用,但暂时还是会安装它们。然而,不管正在运行的版本如何,我会使用最新版本的 nginx 和各个库。
$ nginx -V
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 3.0.2 15 Mar 2022
TLS SNI support enabled
configure arguments:
--with-cc-opt='-g -O2 -ffile-prefix-map=/build/nginx-d8gVax/nginx-1.18.0=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2'
--with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC'
--prefix=/usr/share/nginx
--conf-path=/etc/nginx/nginx.conf
--http-log-path=/var/log/nginx/access.log
--error-log-path=/var/log/nginx/error.log
--lock-path=/var/lock/nginx.lock
--pid-path=/run/nginx.pid
--modules-path=/usr/lib/nginx/modules
--http-client-body-temp-path=/var/lib/nginx/body
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi
--http-proxy-temp-path=/var/lib/nginx/proxy
--http-scgi-temp-path=/var/lib/nginx/scgi
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi
--with-compat
--with-debug
--with-pcre-jit
--with-http_ssl_module
--with-http_stub_status_module
--with-http_realip_module
--with-http_auth_request_module
--with-http_v2_module
--with-http_dav_module
--with-http_slice_module
--with-threads
--add-dynamic-module=/build/nginx-d8gVax/nginx-1.18.0/debian/modules/http-geoip2
--with-http_addition_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_sub_module
下载列表
我先列出一份清单。现在全部都放在 GitHub 上,这很方便。在我的环境中,所有的源代码都放在 /data/src 目录下,安装的路径是 /data/bin。
工具
由于使用全新的Ubuntu,我们将从构建工具进行安装。为了构建libmaxminddb,我们需要安装autoconf,automake和libtool。
$ sudo apt install build-essential autoconf automake libtool
下载
按照前面提到的表格,只需简单地执行 git clone 命令。很简单。由于 libmaxminddb 包含子模块,所以需要使用 –recursive 参数。
$ cd /data/src
$ git clone --depth=1 --branch=release-1.23.3 https://github.com/nginx/nginx.git
$ git clone --depth=1 --branch=3.4 https://github.com/leev/ngx_http_geoip2_module.git
$ git clone --depth=1 --branch=1.7.1 --recursive https://github.com/maxmind/libmaxminddb
$ git clone --depth=1 --branch=openssl-3.0.8 https://github.com/openssl/openssl.git
$ git clone --depth=1 --branch=v1.2.13 https://github.com/madler/zlib.git
$ git clone --depth=1 --branch=pcre2-10.42 https://github.com/PCRE2Project/pcre2.git
关于 pcre2,您需要事先运行 autogen。如果忘记了,会因为找不到 configure 文件而导致构建 nginx 时产生错误提示。
$ cd /data/src/pcre2
$ ./autogen.sh
只需下载源代码并在配置nginx时传递路径即可一次性构建所需的依赖模块。但是,nginx的子模块,即geoip2模块,依赖于libmaxminddb,并不会自动构建,所以需要事先自己构建。
$ cd /data/src/libmaxminddb
$ ./bootstrap
$ ./configure --prefix=/data/bin/libmaxminddb
$ make -j8
$ make install
建造
基本上,我们会将通过 nginx -V 输出的选项传递给 auto/configure,但会更改以下依赖于构建环境的部分。
-
- コンパイルオプションから -ffile-prefix-map 削除
-
- コンパイルオプションに libmaxminddb のヘッダーパスを追加
-
- リンカオプションに libmaxminddb のライブラリパスを追加
-
- ngx_http_geoip2_module のソースコードパスを変更
- –with-pcre、–with-openssl、–with-zlib を追加
只需要进行常规的配置-编译-装载步骤,不需要执行 “make install” 步骤。原因是因为 –prefix 设为 /usr/share/nginx,需要使用 sudo 运行 make install,但我们不希望意外地替换掉不需要的文件。
如果想要以更加干净的方式运行“make install”,最好将–prefix、–conf-path、–modules-path这些选项修改为不需要sudo权限的目录,例如/data/bin。
$ cd /data/src/nginx
# auto/configure \
--with-cc-opt='-g -O2 -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2 -I/data/bin/libmaxminddb/include' \
--with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC -L/data/bin/libmaxminddb/lib' \
--prefix=/usr/share/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--modules-path=/usr/lib/nginx/modules \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
--with-compat \
--with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_v2_module \
--with-http_dav_module \
--with-http_slice_module \
--with-threads \
--add-dynamic-module=/data/src/ngx_http_geoip2_module \
--with-http_addition_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-pcre=/data/src/pcre2 \
--with-openssl=/data/src/openssl \
--with-zlib=/data/src/zlib
$ make -j8
由於二進制文件被創建在objs/nginx和objs/ngx_http_geoip2_module.so中,因此將替換正在運行的二進制文件。值得注意的是,apt安裝的軟體包中除了geoip2外還包含其他動態模塊,在安裝後的狀態下將從/etc/nginx/modules-enabled目錄下的conf文件中加載所有模塊。由於我們將nginx版本從1.18.0升級到1.23.3,因此通過apt安裝的動態模塊與我們編譯的geoip2模塊無法混合。如果使用了動態模塊,則需要重新編譯所有模塊。如果沒有使用,我認為可以將/etc/nginx/modules-enabled目錄下的conf文件備份到其他地方,不必煩惱重新加載。
尝试
为了测试,运行构建的ssl和geoip2模块。它可以获取客户端IP的国家信息并输出到访问日志中。
我们需要在 /etc/nginx/nginx.conf 的 http 部分中添加以下配置。配置内容几乎与 https://github.com/leev/ngx_http_geoip2_module 上写的完全一样。mmdb 文件是从 http://dev.maxmind.com/geoip/geoip2/geolite2/ 下载的。
http {
...
geoip2 /data/conf/GeoLite2-Country.mmdb {
auto_reload 5m;
$geoip2_data_country_code default=? country iso_code;
$geoip2_data_country_name default=? country names en;
}
geoip2 /data/conf/GeoLite2-City.mmdb {
auto_reload 5m;
$geoip2_data_city_name default=? city names en;
}
log_format geolog
'[$time_local] $remote_addr'
' ($geoip2_data_country_code $geoip2_data_country_name $geoip2_data_city_name)'
' "$request" $status $bytes_sent $request_time "$http_user_agent"';
...
}
此外,您可以将以下虚拟主机设置内容作为单独的 conf 文件,或将其写入 /etc/nginx/nginx.conf 文件中。
server {
listen 443 ssl;
ssl_certificate /data/conf/cert.pem;
ssl_certificate_key /data/conf/privkey.pem;
access_log /var/log/nginx/ssl-access.log geolog;
error_log /var/log/nginx/ssl-error.log;
location / {
proxy_pass http://localhost:8000;
}
}
当从内部 IP 和 https://reqbin.com/ 访问此 SSL 服务器时,以下是日志记录的内容。看起来 geoip2 正在运行。
$ sudo tail -f /var/log/nginx/ssl-access.log
[19/Feb/2023:19:28:04 -0800] 10.0.0.99 (? ? ?) "GET / HTTP/1.1" 200 850 0.000 "curl/7.83.1"
[19/Feb/2023:19:29:34 -0800] 10.0.0.99 (? ? ?) "GET / HTTP/1.1" 200 850 0.000 "curl/7.83.1"
[19/Feb/2023:19:30:10 -0800] 206.189.205.251 (US United States North Bergen) "GET / HTTP/1.1" 200 645 0.000 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0 X-Middleton/1"
[19/Feb/2023:19:32:53 -0800] 206.189.205.251 (US United States North Bergen) "GET / HTTP/1.1" 200 645 0.000 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0 X-Middleton/1"
命令列表
mkdir /data/src
mkdir /data/bin
sudo apt update -y
sudo apt install build-essential autoconf automake libtool -y
cd /data/src
git clone --depth=1 --branch=release-1.23.3 https://github.com/nginx/nginx.git
git clone --depth=1 --branch=3.4 https://github.com/leev/ngx_http_geoip2_module.git
git clone --depth=1 --branch=1.7.1 --recursive https://github.com/maxmind/libmaxminddb
git clone --depth=1 --branch=openssl-3.0.8 https://github.com/openssl/openssl.git
git clone --depth=1 --branch=v1.2.13 https://github.com/madler/zlib.git
git clone --depth=1 --branch=pcre2-10.42 https://github.com/PCRE2Project/pcre2.git
cd /data/src/pcre2
./autogen.sh
cd /data/src/libmaxminddb
./bootstrap
./configure --prefix=/data/bin/libmaxminddb
make -j8
make install
cd /data/src/nginx
auto/configure \
--with-cc-opt='-g -O2 -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2 -I/data/bin/libmaxminddb/include' \
--with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -fPIC -L/data/bin/libmaxminddb/lib' \
--prefix=/usr/share/nginx \
--conf-path=/etc/nginx/nginx.conf \
--http-log-path=/var/log/nginx/access.log \
--error-log-path=/var/log/nginx/error.log \
--lock-path=/var/lock/nginx.lock \
--pid-path=/run/nginx.pid \
--modules-path=/usr/lib/nginx/modules \
--http-client-body-temp-path=/var/lib/nginx/body \
--http-fastcgi-temp-path=/var/lib/nginx/fastcgi \
--http-proxy-temp-path=/var/lib/nginx/proxy \
--http-scgi-temp-path=/var/lib/nginx/scgi \
--http-uwsgi-temp-path=/var/lib/nginx/uwsgi \
--with-compat \
--with-debug \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_realip_module \
--with-http_auth_request_module \
--with-http_v2_module \
--with-http_dav_module \
--with-http_slice_module \
--with-threads \
--add-dynamic-module=/data/src/ngx_http_geoip2_module \
--with-http_addition_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_sub_module \
--with-pcre=/data/src/pcre2 \
--with-openssl=/data/src/openssl \
--with-zlib=/data/src/zlib
make -j8