ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

内网离线安装nginx全流程:依赖打包、编译避坑与验证

内网离线安装nginx全流程:依赖打包、编译避坑与验证

简介:面向服务器运维人员,这份离线安装资源包专门解决无外网或内网受限环境下部署Nginx服务的难题。包内整合了GCC编译器及Nginx安装所需的RPM依赖集合,并附上Nginx 1.18.0源码包与网页版安装说明,覆盖从编译环境准备、依赖检查到启动验证的完整流程。资源压缩后共4个文件,以三个压缩包承载源码与依赖,另有一个说明网页,整体大小约62.15MB,便于拷贝到目标服务器直接解压使用。针对离线部署中常见的依赖顺序与版本兼容问题,包内对相关注意事项做了梳理,可帮助运维人员规避因缺少基础工具链而导致的安装中断。无论是数据中心离线环境,还是受安全策略限制的生产网段,都能依靠此包快速完成部署。已有1682人学习下载,适合具备基础Linux操作经验的工程师,在搭建Web服务或与Java应用(如Tomcat)配合时参考。

1. 离线安装 nginx:别再让依赖问题卡住内网部署

我在某公司的内网机房里装过不下二十次 nginx,几乎每次都会遇到同一个剧本:机器不能联网,手里只有一个 nginx 的 tar 包,然后 ./configure 开始报错,说找不到 gcc、找不到 pcre.h、找不到 zlib.h。最气人的是每次报错都少一个包,而且这些依赖之间还互相嵌套,装完这个又冒出那个。后来我把整套流程标准化了,打包了一个包含 gcc 和 nginx 全部依赖 rpm 的集合,离线环境下一遍过。这篇笔记就是记录那套方案:怎么准备 rpm 集合、怎么在隔离网络里按顺序装、哪些参数值得调、以及我踩过的最实际的几个坑。适合正在给内网、等保环境或没有外网的开发机装 nginx 的人。

2. 装之前先把环境盘明白:系统版本、gcc 与依赖关系

2.1 先确认操作系统版本和 CPU 架构,别让 rpm 包不兼容

离线安装最大的隐患不是缺包,而是拿错包。rpm 跟系统版本和架构强绑定,你在自己电脑上下载的依赖包,拿到内网机器上很可能出现 “libc.so.6: wrong ELF class” 或者 “package is for a different architecture” 这类提示。所以我每次拿到一台新机器,第一件事不是找安装包,而是先确认三件事:系统是什么发行版和版本、内核版本、CPU 架构。

cat /etc/os-release uname -a uname -m

/etc/os-release会给出系统的名字和版本号,比如 RHEL 系的 VERSION_ID。uname -m输出是 x86_64 还是 aarch64 决定了你 rpm 包的选择范围。同一个版本号下,x86_64 的包不能装在 aarch64 上,反之亦然。另一个容易忽略的点是 glibc 版本,ldd --version可以看,如果内网机器 glibc 版本太低,即使包架构对,也可能装不上。通常我的处理原则是:联网打包机和内网目标机的系统版本、架构必须保持一致,小版本差异尽量小,否则后面会有一堆麻烦。

2.2 离线包里必须有的三类东西:编译器、依赖库、nginx 本体

从零编译 nginx 时,最少需要 gcc 编译器、make 工具、PCRE/Zlib/OpenSSL 这套库的开发头文件。要注意的是,运行库和开发库是两个东西:比如 pcre 是运行库,pcre-devel 才是提供头文件的开发库。只装 pcre 不装 pcre-devel,./configure 照样报错。同样,zlib 和 zlib-devel、openssl 和 openssl-devel 都是成对出现的。

包名作用缺失时的表现
gcc / gcc-c++C 编译器./configure 报C compiler cc is not found
make构建工具报make: command not found
pcre-devel提供 PCRE 正则库头文件报pcre.h not found
zlib-devel提供压缩库头文件报zlib.h not found
openssl-devel提供 SSL/TLS 库头文件报OpenSSL headers not found

另外,nginx 本身可以通过源码包编译,也可以直接使用编译好的 nginx rpm。如果你手里是官方提供的 nginx rpm,那 gcc 和 devel 包可以不要,但常见的场景还是源码编译,因为内网环境往往需要自定义编译参数,比如增加某个 module。我这套 rpm 集合把编译器和三个 devel 包都收进去了,同时保留 nginx 源码包,这样两种安装方式都能覆盖。

2.3 在联网机器上制作 rpm 集合:yumdownloader 与 repotrack 的选择

制作离线 rpm 集合有两种常用工具:yumdownloader和repotrack。yumdownloader --resolve只会下载指定包以及它们直接依赖的包,但有时候会漏掉一些运行时才需要的依赖;repotrack则会递归分析完整的依赖链,把指定包的所有依赖都拉下来。我用过一次yumdownloader结果漏了libxcrypt,离线机器上怎么都装不上,从此之后只用repotrack。

yum install -y yum-utils repotrack -p /root/nginx-offline gcc gcc-c++ make pcre-devel zlib-devel openssl-devel

-p指定输出目录,后面跟要拉取的包名。repotrack会自动把每个包的完整依赖链都下载到这个目录里,这样离线机器上就不再需要联网解析依赖。如果系统中没有repotrack,先安装yum-utils。这里有个细节:执行命令前,先把联网机器的 yum 源换成国内的速度快的镜像源,否则从默认源拉包会非常慢,而且某些源可能因为网络原因中断。换源的操作不复杂,改/etc/yum.repos.d/下的 repo 文件,把 baseurl 改成镜像站地址,然后yum clean all && yum makecache即可。

3. 实操:从零打包一套可离线安装的 gcc 与 nginx 依赖

3.1 准备一台同版本同架构的联网机器,并配置好 yum 源

打包第一步是找一台“参照机”。这台机器必须是干净的、系统版本和架构与内网目标机一致的。如果参照机上面已经装了一堆乱七八糟的开发工具,yum 可能会判断某些依赖已安装,从而跳过下载,导致离线包里缺文件。我一般会在虚拟机里重新装一个最小化系统来当打包机,装完什么都不做,先改 yum 源,然后立刻开始拉依赖。

mv /etc/yum.repos.d/*.repo /tmp/ vi /etc/yum.repos.d/offline.repo

注意:mv操作是清掉系统自带 repo,换成自己写的源。写源的时候要确认 repo 文件里的gpgcheck=0,避免在离线环境下因为缺 GPG key 无法安装。镜像站点有很多,选一个连通性好的即可,没有特别推荐,哪个快用哪个。改完源后执行:

yum clean all yum makecache

看到metadata cache created就说明源可用。如果 makecache 失败,大概率是 baseurl 写错或者 DNS 不通,换一个镜像源重新试。

3.2 用 repotrack 拉取完整依赖列表

这一步是整个打包过程的核心。repotrack会把 gcc、make、pcre-devel 等包以及它们全部依赖项拉到一个目录。我建议把 nginx 的源码包也放进同一个目录,这样整个离线资源就是一个完整的集合。

mkdir -p /root/nginx-offline/src repotrack -p /root/nginx-offline gcc gcc-c++ make pcre-devel zlib-devel openssl-devel cd /root/nginx-offline/src wget http://nginx.org/download/nginx-1.24.0.tar.gz

repotrack -p指定的目录如果不存在会自动创建。这里我把src子目录单独建出来,是为了把源码包和 rpm 包分开,避免后面rpm -Uvh *.rpm时误伤 tar 包。源码包下载时注意,如果你需要的版本不在官方源,那就去镜像站下载,但一定要记下版本号,因为后面 configure 参数里不需要指定版本,但档案里要写清楚。拉下来的 rpm 集合数量通常在几十到上百个,数量多不用慌,这是正常的,gcc 的依赖链很长。

拉完后做一次完整性检查:

ls /root/nginx-offline/*.rpm | wc -l rpm -qpl /root/nginx-offline/*.rpm | grep -E "libssl.so|libcrypto.so" | head -n 5

第一条命令统计 rpm 数量,第二条检查关键运行库文件是否存在。OpenSSL 的依赖很典型,如果缺少libssl.so或libcrypto.so,后面 nginx 的 ssl 模块编译必挂。检查通过后,把整个目录打包:

tar czf nginx-offline-bundle.tar.gz nginx-offline/

到这里,联网机器上的工作就结束了。把这个 tar 包通过内网传输工具(比如 scp 或 U 盘拷贝)运到目标机器上。

3.3 把 tar 包传输到内网机器并解压

内网机器上没有外网,所以传输方式不限,U 盘、内网 FTP、堡垒机、甚至扫码传文件都行。解压时注意保留目录结构:

tar xzf nginx-offline-bundle.tar.gz -C /opt/ ls /opt/nginx-offline/

我习惯放在/opt下面,因为这个目录对应用软件是开放的,权限也容易控制。解压后,/opt/nginx-offline下应该同时有.rpm文件和src子目录。先不要急着装,先把包列表导出来看一眼,心里有数。

ls /opt/nginx-offline/*.rpm | sed 's/.*\///' | tee package-list.txt

package-list.txt这个文件建议保留,后面排错时能快速定位某个包是否在内。如果发现某个包缺失,可以回到联网机器上单独补拉。

4. 离线服务器上的安装顺序:先装依赖,再编译 nginx

4.1 批量安装 rpm 时的依赖顺序问题

依赖包的数量一多,最省事的方法是用一条命令装完所有 rpm。但直接rpm -Uvh *.rpm经常遇到依赖死锁,因为 rpm 命令本身不解决依赖,它只按你给的顺序安装,遇到还没装的依赖就报错。正确的做法是用yum localinstall,它会把本地目录里的 rpm 当作源,自动解析依赖关系。

cd /opt/nginx-offline yum localinstall -y --disablerepo=* ./rpm/*.rpm

注意我用了--disablerepo=*,这是关键的参数。因为目标机器上没有外网,如果不禁用 repo,yum 会尝试去访问网络源,然后卡在连接超时等很久。--disablerepo=*让 yum 只在本地 rpm 文件里找依赖,不会去请求网络。./rpm/*.rpm的路径如果不对,可以先确认你的目录结构。如果rpm文件都直接放在/opt/nginx-offline/根目录下,那上面命令里的路径就改成./*.rpm。

如果yum localinstall因为缺失 GPG key 而失败,加上--nogpgcheck强制跳过校验。离线环境里 rpm 包是自己准备的,安全性可控,跳过 GPG 校验是常见做法。装完之后验证一下编译工具是否可用:

gcc --version make --version

如果gcc能输出版本号,说明编译链完整。如果提示gcc: command not found,多半是 rpm 没有装全,回到上一步重新检查。

4.2 编译安装 nginx 的 configure 参数

依赖装好后,就可以编译 nginx 了。这里我把 nginx 的源码包解压出来,进入目录:

cd /opt/nginx-offline/src tar xzf nginx-1.24.0.tar.gz cd nginx-1.24.0 ./configure --prefix=/usr/local/nginx \ --with-http_ssl_module \ --with-http_stub_status_module \ --with-pcre

--prefix指定安装路径,默认是/usr/local/nginx,我一般不改它,因为后续 systemd 服务文件里写路径也方便。--with-http_ssl_module启用 HTTPS 支持,这个模块必须要有 OpenSSL 开发库,是我们前面打包 openssl-devel 的原因。--with-http_stub_status_module提供 nginx 的运行状态页面,后面验证和后端负载均衡时很有用。--with-pcre是显式指定使用 PCRE 库做正则。

如果 configure 没有任何错误,最后会生成一个 Makefile。接着执行:

make -j$(nproc) make install

-j$(nproc)是用 CPU 核数并行编译,内网机器如果核数少,可以去掉-j参数避免内存不足。编译过程持续一至三分钟不等,看到make install无报错,nginx 就装到了/usr/local/nginx。此时先不启动,先做基础配置。

4.3 配置 nginx 全局参数与 systemd 管理

nginx 默认配置在/usr/local/nginx/conf/nginx.conf。先修改 worker 进程数、运行用户和日志路径等基础项:

vi /usr/local/nginx/conf/nginx.conf user nginx; worker_processes 4; error_log logs/error.log; pid logs/nginx.pid;

worker_processes一般设为 CPU 核数或核数 x2,具体值取决于机器配置。user nginx需要先在系统里创建 nginx 用户,一行命令即可:

useradd -r nginx

创建完用户后,用nginx -t测试配置语法:

/usr/local/nginx/sbin/nginx -t

输出syntax is ok和test is successful说明配置无问题。为了能让 nginx 随系统启动,写一个 systemd 服务文件:

vi /etc/systemd/system/nginx.service

内容是:

[Unit] Description=nginx service After=network.target [Service] Type=forking ExecStart=/usr/local/nginx/sbin/nginx ExecReload=/usr/local/nginx/sbin/nginx -s reload ExecStop=/usr/local/nginx/sbin/nginx -s quit PrivateTmp=true [Install] WantedBy=multi-user.target

Type=forking是因为 nginx 启动时 master 进程会 fork 出 worker 进程,systemd 需要确认 master 起来才算启动成功。写完后执行systemctl daemon-reload让服务文件生效,再用systemctl enable nginx设置开机自启。这样后续维护 nginx 可以直接用systemctl start nginx、systemctl reload nginx之类的命令,跟系统服务一致,运维上更省心。

5. 这些坑我全踩过:离线安装 nginx 的常见问题与排查

5.1 现象:rpm 提示 libssl.so.10 找不到

离线机器上安装依赖包时,报错error: Failed dependencies: libssl.so.10()(64bit) is needed by openssl-devel。原因是系统之前已经装过一个老版本的 openssl,新装的 openssl-devel 需要匹配的 libssl.so 版本,而老的运行库没有覆盖到。

解决方法是把 openssl 和 openssl-devel 相关的所有包先卸载或强制覆盖安装:rpm -e openssl --nodeps,然后重新用yum localinstall批量装。这个操作有点危险,但内网环境可控,只要 rpm 集合里版本一致就没问题。如果不想卸载,也可以直接加--nodeps --force强制安装,但后续使用 SSL 模块时可能不稳定。我的习惯是优先让系统 openssl 全家桶和集合里的版本保持完全一致。

5.2 现象:./configure 提示 pcre.h 找不到

源码编译 nginx 时./configure报pcre.h not found,但是已经安装了 pcre 包。原因是 pcre 和 pcre-devel 是两个包,只有 pcre-devel 才会提供头文件。我总结过一个规律:凡是出现xxx.h not found,就去查xxx-devel是否安装。不要只装运行库就跑去编译。用rpm -q pcre-devel检查,如果返回not installed,回到联网机器补拉 pcre-devel 及其依赖,再传输过来安装。

5.3 现象:rpm -Uvh *.rpm 时依赖死循环

离线目录里明明有所有 rpm,但rpm -Uvh *.rpm依然报requires X is needed by Y。原因就是rpm -Uvh不处理依赖顺序,当你给的文件列表里,Y 排在 X 前面时,Y 找不到 X 就报错。解决方法是不要用 rpm 直装,改用yum localinstall,并配合--disablerepo=*。yum 会从本地所有 rpm 文件里排序解析依赖,一次性装上。这是我推荐的核心做法,除非极少数 yum 无法处理的情况,否则不用--nodeps硬闯。

5.4 现象:编译安装成功后,nginx 启动端口被占用

nginx 默认监听 80 端口,如果目标机器上已经有 Apache/httpd 或者其他服务占用了 80,启动 nginx 会报bind() to 0.0.0.0:80 failed (98: Address already in use)。解决方法是先找出占用进程:ss -lntp | grep :80,如果确认是不需要的服务,直接停掉并禁用;如果是需要的服务,就在 nginx.conf 里把listen改成其他端口,或者用server块做虚拟主机。我一般会把这个检查放到编译之前,省得装完再折腾。

5.5 现象:离线机器上 glibc 版本过低,rpm 装不上

这种情况多见于老旧服务器,比如系统还是多年前的版本,而打包机用的是新版本。rpm 安装时报requires glibc >= 2.17,但你系统只有 2.12。这个坑基本无解,唯一的办法是改用与目标机相同系统版本的机器打包,或者降低目标机系统的处理方法。我吃过这个亏之后,在打包机的/etc/os-release和ldd --version两个输出上做了对比检查,确认一致才继续。如果你的内网机器版本特别老,建议在虚拟机里还原同版本系统来打包,别用较新的系统凑合。

6. 装完怎么验证真的能跑:从本地 curl 到代理 java 服务

依赖装完、nginx 编译完成后,最终验证不能只看进程启动,还要确认它真的能响应请求。先从最基础的开始:启动服务,然后看端口和进程。

systemctl start nginx ss -lntp | grep 80 ps -ef | grep nginx

ss输出里能看到nginx: master和nginx: worker两个进程,说明 master-worker 模型正常工作。接着用本机 curl 请求 nginx 默认页面:

curl -I http://127.0.0.1/

返回HTTP/1.1 200 OK且 header 里有Server: nginx/1.24.0,说明静态服务已经通了。这一步不通就先看日志:tail -f /usr/local/nginx/logs/error.log,端口冲突、权限问题、配置语法错误都会在这里体现。

对于 Java 后端场景,nginx 最常用的身份是反向代理,验证时我会配置一个标准代理块,把请求转发给本机或内网某台机器上的 Java 应用。假设某个 Spring Boot 服务监听在 8080 端口,那么在 nginx.conf 里加一个 location:

location /api/ { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }

proxy_pass指定后端 Java 服务的地址,这里用 127.0.0.1 表示本机。proxy_set_header三行是为了让 Java 应用拿到真实的客户端 IP,如果不加,后端只能看到 nginx 的地址。改完配置后执行nginx -t和systemctl reload nginx,然后用 curl 验证代理链路:

curl -I http://127.0.0.1/api/health

如果返回 200,说明 nginx 已经能把请求正确转发给 Java 服务。还可以用curl -v查看响应头里有没有 nginx 和后端服务信息,进一步确认转发链路。整个验证走完后,离线安装这件事才算闭环。

从那以后,我每到一个新环境部署 nginx,都会强制走一遍这套流程:先核对系统版本和架构,再用 repotrack 打包依赖,离线机器上用yum localinstall --disablerepo=*安装,最后必须用 curl 测试真实请求才算结束。这个习惯帮我避开了大半的按环境翻车问题。希望这篇记录也能让你在内网装 nginx 时少走几步弯路,一次跑通。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进