lamess / Nginx编译安装与多平台自动化构建

Created Thu, 27 Jun 2024 11:52:30 +0800 Modified Fri, 24 Jul 2026 15:06:03 +0800

Nginx编译安装与多平台自动化构建

手动编译一次Nginx并不难,麻烦的是在多个发行版(openEuler、Kylin、CentOS)、多种架构(x86_64、aarch64)和不同安装路径下重复同样的工作。本文前半部分梳理手动编译的完整流程,后半部分介绍如何用GitHub Actions把这套流程重构为自动化的矩阵构建流水线:multi-platform-nginx-build-workflow

手动编译

安装编译依赖

dnf install -y ca-certificates gcc glibc-devel git gzip make perl tar wget \
    pcre-devel openssl-devel zlib-devel \
    libxslt-devel gd-devel perl-devel gperftools-devel GeoIP-devel

最后一行的libxslt-devel、gd-devel、perl-devel、gperftools-devel、GeoIP-devel只有全功能编译才需要。

软件下载

从官网下载Nginx源码包。OpenSSL、PCRE2和zlib会在编译Nginx时从源码一并编译并静态链接,因此同时下载这三个依赖的源码。

wget https://nginx.org/download/nginx-1.31.3.tar.gz
wget https://www.openssl.org/source/openssl-3.0.12.tar.gz
wget https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.gz
wget https://github.com/madler/zlib/releases/download/v1.3.2/zlib-1.3.2.tar.gz
tar -xzf nginx-1.31.3.tar.gz
tar -xzf openssl-3.0.12.tar.gz
tar -xzf pcre2-10.47.tar.gz
tar -xzf zlib-1.3.2.tar.gz

第三方模块从GitHub克隆。

git clone --recursive https://github.com/winshining/nginx-http-flv-module.git
git clone --recursive https://github.com/openresty/headers-more-nginx-module

编译参数的组织

编译参数可以拆成两部分,这也是后文自动化构建的组织方式:

  • 基础参数:安装路径、依赖源码路径、编译和链接选项,所有场景一致;
  • 模块参数:启用哪些模块,按需选择,对应一个构建profile。

基础参数中,--with-openssl--with-pcre--with-zlib指向依赖的源码目录,configure会在编译Nginx时一并编译这些依赖并静态链接进二进制,不依赖系统中安装的版本。

基础功能:SSL模块,适合以最小依赖部署到生产环境。

cd nginx-1.31.3
./configure \
--prefix=/usr/local/nginx \
--with-openssl=../openssl-3.0.12 \
--with-pcre=../pcre2-10.47 \
--with-zlib=../zlib-1.3.2 \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-cc-opt='-O2 -g -grecord-gcc-switches -pipe -fstack-protector-strong -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection' \
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,-E'

全功能编译:参考YUM源内Nginx的nginx -V参数,包含HTTP/2、HTTP/3、stream、mail等全部模块。

全功能编译参数
cd nginx-1.31.3
./configure \
--prefix=/usr/local/nginx \
--with-openssl=../openssl-3.0.12 \
--with-pcre=../pcre2-10.47 \
--with-zlib=../zlib-1.3.2 \
--add-module=../nginx-http-flv-module \
--add-module=../headers-more-nginx-module \
--with-select_module \
--with-poll_module \
--with-threads \
--with-file-aio \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--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_degradation_module \
--with-http_slice_module \
--with-http_stub_status_module \
--with-http_perl_module=dynamic \
--with-http_auth_request_module \
--with-mail=dynamic \
--with-mail_ssl_module \
--with-pcre-jit \
--with-stream=dynamic \
--with-stream_ssl_module \
--with-stream_realip_module \
--with-stream_geoip_module \
--with-stream_ssl_preread_module \
--with-google_perftools_module \
--with-debug \
--with-compat \
--with-cc-opt='-O2 -g -grecord-gcc-switches -pipe -fstack-protector-strong -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection' \
--with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,-E'

注意--with-cc-opt中的-m64只适用于x86_64,在aarch64上编译时需要去掉。

编译安装与验证

make -j$(nproc)
make install

编译完成后验证编译参数和默认配置。

/usr/local/nginx/sbin/nginx -V
/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf -p /usr/local/nginx

部署

创建用户并授权。

groupadd nginx
useradd -g nginx -s /bin/false nginx
chown -R nginx:nginx /usr/local/nginx/

增加软链接。

ln -s /usr/local/nginx/sbin/nginx /usr/sbin/nginx

部署systemd监控,按需修改执行文件路径为实际的路径即可。

cat > /usr/lib/systemd/system/nginx.service << EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
User=nginx
Group=nginx
LimitNOFILE=65535
LimitNPROC=65535
Type=forking
PIDFile=/usr/local/nginx/nginx.pid
# Nginx will fail to start if /usr/local/nginx/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running \`nginx -t\` from the cmdline.
ExecStartPre=/usr/bin/rm -f /usr/local/nginx/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload

这里使用/usr/local/nginx/nginx.pid存放pid文件,需要对应地将nginx.conf中的pid配置为相同的路径。

pid        /usr/local/nginx/nginx.pid;

使用GitHub Actions自动化多平台构建

以上流程在一台机器上跑一次没有问题,但要覆盖「多种发行版 × 不同CPU架构」时,手动编译或为每个发行版维护一个Dockerfile都难以为继。multi-platform-nginx-build-workflow把这套流程搬到了GitHub Actions上,核心思路:

  • matrix策略展开全部构建组合,各组合并行构建、互不影响;
  • 容器提供各发行版的编译环境(openEuler、Kylin官方镜像),aarch64跑在ARM Runner上原生编译,无需QEMU模拟;
  • 把易变的部分抽离为配置文件:依赖版本放进build-config.env,模块清单放进build-profiles/*.conf,工作流本身保持稳定。

项目结构

multi-platform-nginx-build-workflow
├── .github
│   └── workflows
│       ├── build-nginx-multi-distro.yml   # 主工作流:openEuler/Kylin矩阵构建
│       └── build-nginx-centos_7.yml       # CentOS 7独立工作流
├── build-config.env                       # 全局构建配置
└── build-profiles                         # 构建profile,一行一个configure参数
    ├── minimal.conf
    └── standard.conf

构建矩阵

主工作流用系统、架构、安装前缀三个维度展开矩阵,每个组合是一个独立的job,运行在对应发行版的容器里。

strategy:
  fail-fast: false
  matrix:
    os:
      - name: kylin_v10
        image: macrosan/kylin:v10-sp3-2403
        openssl: "1.1.1w"
      - name: openeuler_22_03
        image: openeuler/openeuler:22.03-lts-sp4
        openssl: "1.1.1w"
      - name: openeuler_24_03
        image: openeuler/openeuler:24.03-lts-sp3
        openssl: "3.0.12"
    arch:
      - arch: x86_64
        runner: ubuntu-24.04
      - arch: aarch64
        runner: ubuntu-24.04-arm
    prefix:
      - prefix_name: usr_local
        INSTALL_PREFIX: /usr/local/nginx
        PACKAGE_ROOT: /usr/local
  • OpenSSL版本跟随发行版:Kylin V10和openEuler 22.03使用1.1.1w,openEuler 24.03使用3.0.12,所以它定义在os维度里而不是全局配置里;
  • fail-fast: false保证单个组合失败不会取消其他组合;
  • Nginx版本不写在矩阵里,release触发时取tag名,手动触发时由表单输入。

全局配置build-config.env

PCRE2_VERSION=10.47
ZLIB_VERSION=1.3.2
NGINX_BUILD_PROFILE=minimal
ALLOWED_PREFIXES=usr_local
  • 升级PCRE2、zlib版本只需要修改这个文件,不用动工作流;
  • NGINX_BUILD_PROFILE指定release构建默认使用的profile;
  • ALLOWED_PREFIXES限制release构建的安装前缀(逗号分隔,留空则全部构建),手动触发不受它限制,使用表单里的过滤器。

构建Profile

build-profiles/目录下每个.conf文件就是一份模块清单,一行一个configure参数,空行和#开头的行会被忽略。minimal.conf

--with-http_ssl_module
--with-http_realip_module
--with-http_stub_status_module

standard.conf即前文全功能编译的模块参数。工作流读取profile后,与固定的基础参数拼接执行:

PROFILE_ARGS=$(grep -v '^#' "build-profiles/${NGINX_BUILD_PROFILE}.conf" | grep -v '^[[:space:]]*$' | tr '\n' ' ')

cd nginx-src
./configure \
  --prefix="${INSTALL_PREFIX}" \
  --with-openssl=../openssl-${OPENSSL_VERSION} \
  --with-pcre=../pcre2-${PCRE2_VERSION} \
  --with-zlib=../zlib-${ZLIB_VERSION} \
  --with-cc-opt="${CC_OPT_FLAGS}" \
  --with-ld-opt="${LD_OPT_FLAGS}" \
  $PROFILE_ARGS

基础参数由工作流固定提供,profile只负责模块清单,-m64这类架构相关的编译选项也由工作流按架构动态追加。新增profile只需在目录下添加一个.conf文件,并把名字加进工作流build_profile的下拉选项。

触发方式

触发方式 Nginx版本来源 产物去向
release发布 tag名(如1.31.3 上传为release附件
手动触发(workflow_dispatch) 表单输入 workflow artifact,保留3天

手动触发时可以按系统、架构、前缀过滤,只构建需要的组合。工作流的第一步会检查当前矩阵组合是否命中过滤条件(包括release构建的ALLOWED_PREFIXES),未命中的组合跳过所有后续步骤。

打包

每个组合编译安装并通过nginx -Vnginx -t验证后,把安装目录整体打包为nginx-{版本}-{架构}-{系统}-{前缀}.tar.gz,例如nginx-1.31.3-x86_64-openeuler_24_03-usr_local.tar.gz。包内目录有两种模式:

  • static:固定的nginx/目录,release构建固定使用这种;
  • versioned(手动构建默认):版本号目录加一个指向它的软链接,方便多版本并存,回滚只需改软链接指向。
/usr/local/
├── nginx -> nginx-1.31.3
└── nginx-1.31.3/
    ├── sbin/nginx
    ├── conf/
    ├── html/
    └── logs/

CentOS 7的特殊处理

CentOS 7没法走主工作流的container:方式:GitHub Actions要求容器内能运行基于Node 20的action(checkout、upload-artifact等),CentOS 7的glibc太旧。因此单独建一个工作流,在job里手动docker run centos:7,构建逻辑以内联脚本执行。

另外CentOS 7已经EOL,官方源已下线,构建前需要把YUM源切到vault归档源。

cd /etc/yum.repos.d
mkdir -p backup
mv -f *.repo backup/

cat > CentOS-Vault.repo << 'EOF'
[base]
name=CentOS-7 - Base
baseurl=http://vault.centos.org/7.9.2009/os/$basearch/
enabled=1
gpgcheck=0

[updates]
name=CentOS-7 - Updates
baseurl=http://vault.centos.org/7.9.2009/updates/$basearch/
enabled=1
gpgcheck=0

[extras]
name=CentOS-7 - Extras
baseurl=http://vault.centos.org/7.9.2009/extras/$basearch/
enabled=1
gpgcheck=0
EOF

yum clean all
yum makecache

下载使用

构建产物随release发布,按平台拼接下载地址。

VERSION=1.31.3
ARCH=x86_64               # x86_64 / aarch64
PLATFORM=openeuler_24_03  # openeuler_24_03 / openeuler_22_03 / kylin_v10 / centos7(仅x86_64)
PREFIX=usr_local          # usr_local

wget https://github.com/lamess233/multi-platform-nginx-build-workflow/releases/download/${VERSION}/nginx-${VERSION}-${ARCH}-${PLATFORM}-${PREFIX}.tar.gz
tar -xzf nginx-${VERSION}-${ARCH}-${PLATFORM}-${PREFIX}.tar.gz -C /usr/local

解压到前缀对应的父目录(/usr/local),再按前文「部署」一节创建用户和systemd服务即可使用。