Debian 10重新打包Nginx,新增Google、Purge、Brotli及HTTP3等模块

对于一个追求软件新版本及喜欢折腾的人来说,每次有了新版本不升级到最新的版本总是有点不舒服,一转眼Debian 10都发布半年多了,服务器上也升级到了Debian 10有一段时间了,一直用的Nginx官方源里自带的Nginx版本,最近有点时间,想折腾下HTTP3,顺带想把Nginx的Purge及Brotli等模块也给加上,于是就有了这篇文章。

写在最开始

虽然Nginx官方提供编译好的Nginx,版本也足够新,也自带了部分模块,但是有些我需要的模块却并没有,比如说Purge、Brotli及刚通过的HTTP3,想要使用这些模块,只能自己编译了。

本文内容基于Debian 10 64位系统,使用的是root账户,整个过程走完会生成一个可以随意复制安装的Deb软件包。

编译过程中会安装大量的软件包,其中设计相关的编译软件,以及编译Nginx本身所需要的依赖,还有Nginx模块编译所需要的东西,如果这些软件包全部安装到正式服务器上,这肯定不合适,建议是单独找一台干净的测试服务器来做这些事。

至于测试服务器,我推荐使用Vultr的服务器,有如下好处:

  • 按量付费,需要的时候开启,编译完成直接Destory即可停止收费,特别适合这种临时用途
  • 可以灵活调整配置,内存太小可能会导致编译过程中失败,Vultr可以随时调整配置大小加快编译速度
  • Vutlr的服务器在国外,下载软件包及从Github克隆源码的时候速度快,不像国内机器,直连情况下要么龟速要么到一半就断开了
  • 支持创建快照,搞定编译环境之后,可以打个快照,下次软件版本有更新的时候可以更新对应的软件包然后直接打包,省去配置环境的时间

我就是使用的是Vultr的1核CPU1G内存25G SSD硬盘的配置,建议内存不要小于1G,不然可能导致编译出错。

关于Vultr的更多介绍,可以移步这里:Vultr-月付2.5美元起高性价比VPS 新注册赠送50美元

添加Nginx及下载Nginx源代码

因为是重新打包,没必要自己去写makefile等,Nginx官方已经为我们做好了这些事,我们只需要添加Nginx的软件源然后根据我们的需要修改对应的文件,即可方便打包出我们所需要的安装包。

首先,添加Nginx的软件源及对应的key等,命令如下:

apt update
apt upgrade
apt install curl gnupg2 ca-certificates lsb-release
echo "deb http://nginx.org/packages/debian `lsb_release -cs` nginx"     | tee /etc/apt/sources.list.d/nginx.list
echo "deb-src http://nginx.org/packages/debian `lsb_release -cs` nginx"     | tee /etc/apt/sources.list.d/nginx.list
curl -fsSL https://nginx.org/keys/nginx_signing.key | apt-key add -

到这一步就完成了添加Nginx官方源的操作,注意,上面有两行echo,第一行是添加源,第二行是加上源代码,方便后面我们通过apt-get下载Nginx的源代码。

因为我更偏向于稳定版,所以我选择的是stable版,如果想要尝鲜的,可以选择mainline版。stable版目前的版本号位1.16.1。

这部份内容可以移步这里,参考Nginx:https://nginx.org/en/linux_packages.html

配置系统环境

首先,安装官方源的Nginx,命令如下:

apt update
apt install nginx

然后创建对应的文件夹,及下载Nginx的源代码,并且安装Nginx本身的依赖:

mkdir -p ~/new/nginx_rebulid/
cd ~/new/nginx_rebulid/
apt-get source nginx #使用apt-get命令下载源代码
apt-get build-dep nginx #安装对应的依赖

上面我Nginx的保存目录在~/new/nginx_rebulid/

然后安装编译过程中所需要的编译软件包:

apt install build-essential ca-certificates zlib1g-dev libpcre3 libpcre3-dev tar unzip libssl-dev wget curl git cmake

准备所要编译的Nginx模块

我这里只是根据我自己所需要的模块进行编译,如果你需求跟我不一样,可以根据你实际的情况来处理。

需要说明的是,我喜欢把自己的源代码放到/usr/local/src/,你可以根据自己的喜好来放置,只要前后路径一致即可。

相关命令:

cd /usr/local/src/
git clone https://github.com/cuber/ngx_http_google_filter_module #Google相关,我不太方便说用来干嘛的
git clone https://github.com/yaoweibin/ngx_http_substitutions_filter_module #跟上述一样
git clone https://github.com/google/ngx_brotli.git #brolti
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
tar zxvf ngx_cache_purge-2.3.tar.gz #purge模块
git clone --recursive https://github.com/cloudflare/quiche #HTTP3模块
cd /usr/local/src/ngx_brotli && git submodule update --init
cd /usr/local/src/ngx_http_google_filter_module && git checkout -b dev origin/dev

想知道上述模块的具体用处的,可以进入对应的主页进行查看,有些内容我不太方便说,你懂的。

为Nginx的编译准备

在进行编译之前,还需要做一些准备,下面是具体步骤。

为Nginx打补丁:

cd ~/new/nginx_rebulid/nginx-1.16.1/
patch -p1 < /usr/local/src/quiche/extras/nginx/nginx-1.16.patch

更改Nginx的rules文件,命令如下:

vim debian/rules

这里要修改的其实就两点,就是上述文件的两个CFLAGS后面的内容,下面是我根据实际需求修改之后的部分文件内容,如果不知道怎么修改的,可以参考下我的,注意,这只是部分内容,不能删除别的内容:

config.status.nginx: config.env.nginx
        cd $(BUILDDIR_nginx) && \
        CFLAGS="" ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --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-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_realip_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --add-module=/usr/local/src/ngx_http_google_filter_module --add-module=/usr/local/src/ngx_http_substitutions_filter_module  --add-module=/usr/local/src/ngx_brotli --with-http_v3_module --with-openssl=/usr/local/src/quiche/deps/boringssl --with-quiche=/usr/local/src/quiche --add-module=/usr/local/src/ngx_cache_purge-2.3
        touch $@
config.status.nginx_debug: config.env.nginx_debug
        cd $(BUILDDIR_nginx_debug) && \
        CFLAGS="" ./configure --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --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-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_realip_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --add-module=/usr/local/src/ngx_http_google_filter_module --add-module=/usr/local/src/ngx_http_substitutions_filter_module  --add-module=/usr/local/src/ngx_brotli --with-http_v3_module --with-openssl=/usr/local/src/quiche/deps/boringssl --with-quiche=/usr/local/src/quiche --add-module=/usr/local/src/ngx_cache_purge-2.3 --with-debug
        touch $@

修改完了之后,当前目录下面执行下列命令即可开始进行编译及打包:

dpkg-buildpackage -b

如果过程没有问题,应该能在~/new/nginx_rebulid目录生成两个deb包,比如我这里生成的是nginx_1.16.1-1~buster_amd64.debnginx-dbg_1.16.1-1~buster_amd64.deb,两个都可以直接安装,我是建议正式环境安装前者。

到这一步,即可把生成的deb安装包随意复制到别的机器比如说生产服务器进行安装,安装命令如下:

dpkg -i nginx_1.16.1-1~buster_amd64.deb

相关输出如下:

root@cloudbool:~# dpkg -i nginx_1.16.1-1~buster_amd64.deb
Selecting previously unselected package nginx.
(Reading database ... 31466 files and directories currently installed.)
Preparing to unpack nginx_1.16.1-1~buster_amd64.deb ...
----------------------------------------------------------------------
Thanks for using nginx!
Please find the official documentation for nginx here:
* http://nginx.org/en/docs/
Please subscribe to nginx-announce mailing list to get
the most important news about nginx:
* http://nginx.org/en/support.html
Commercial subscriptions for nginx are available on:
* http://nginx.com/products/
----------------------------------------------------------------------
Unpacking nginx (1.16.1-1~buster) ...
Setting up nginx (1.16.1-1~buster) ...
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service.
Processing triggers for systemd (241-7~deb10u2) ...
Processing triggers for man-db (2.8.5-2) ...

如果编译打包过程出错,那建议根据实际的错误信息进行一步步调试,就我遇到的问题来说,要么是模块没有初始化,要么就是rust或者cargo版本出现了问题,根据错误排除即可。

报错

本项目编译过程中可能会遇到类似如下报错:

cd /usr/local/src/quiche && cargo build --release --no-default-features --features ffi
   Compiling quiche v0.6.0 (/usr/local/src/quiche)
error: attributes are not yet allowed on `if` expressions
    --> src/lib.rs:2700:13
     |
2700 |             #[allow(unused_assignments)]
     |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
error: could not compile `quiche`.
To learn more, run the command again with --verbose.
make[2]: *** [objs/Makefile:2137: /usr/local/src/quiche/target/release/libquiche.a] Error 101
make[2]: Leaving directory '/root/new/nginx_rebulid/nginx-1.16.1/debian/build-nginx'
make[1]: *** [Makefile:8: build] Error 2
make[1]: Leaving directory '/root/new/nginx_rebulid/nginx-1.16.1/debian/build-nginx'
make: *** [debian/rules:52: build-arch.nginx] Error 2
dpkg-buildpackage: error: debian/rules build subprocess returned exit status 2

如果遇到这个问题,可以使用这两个命令手动安装rust,命令如下:

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env