在 Ubuntu 上从源码编译安装 Nginx

1,233 阅读12分钟

为了避免一万个哈姆雷特的问题,本文如果没能帮你成功编译 Nginx,找我!微信:iyoooooooo。让我参与进来,正好查漏补缺,继续完善这篇文章。

APT 包管理器中的 Nginx 版本一般都比较旧,有些新特性无法使用,而且默认提供的功能并不能满足诸如 HTTP2 等需求,所以很大概率是要根据实际需要从源码编译 Nginx 的。

本文 针对 HTTP 或反向代理服务 去编译 Nginx,除了 保留 Nginx 的默认功能 外,还 扩展了一些功能

  • HTTPS;
  • HTTP2;
  • Certificate Transparency 策略证书;
  • Brotli;

还有一些可选功能,见 “配置 Nginx 构建规则” 部分。

本文 专注在单机环境,满足个人网站、学习、原型、物联、轻量 IO 型的需求,诸如静态网站、动态网站、开放接口服务等部署涉及到 Nginx 的部分,都可以使用这篇文章来编译、安装 Nginx。”搭建 Nginx 集群” 部分请看下回分解

只要不是天天使用 Linux,难免对一些操作不熟悉,所以本文会为每项操作提供尽可能详细的指南、描述。

如果你现在就有一台全新的 VPS,直接按照下文开始一步步操作即可。

更新系统

系统权限:在 root 用户下完成操作。如果是在非管理员权限的账户下操作,记得给每项操作带上 sudo 指令前缀。

安装任何工具前,先更新(apt update)包软件源,再把已经安装的包都更新(apt upgrade -y)一下。这应该是个习惯,且是个好习惯。

通过包管理器安装必要环境

在 root 用户下完成操作。如果是在非管理员权限的账户下操作,记得给每项操作带上 sudo 指令前缀。

构建 Nginx 需要先安装(apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev libgd-dev libxml2 libxml2-dev uuid-dev libgeoip-dev)些必备环境。

准备好 “ngx_brotli” 源码

系统权限:不要求一定要在管理员账户下操作。本文设定在非管理员账户下操作。

这是让 Nginx 支持 Brotli 压缩算法的模块。

登录服务器后,确定在当前账户根目录下,下载 “ngx_brotli” 源码,成功下载后,进入 “ngx_brotli” 根目录,将子项目更新下来。最后,切换到当前账户根目录准备其它模块源码。

为了方便、快速,将上述操作整理成清单,

  1. cd ~
  2. git clone https://github.com/google/ngx_brotli.git
  3. cd ngx_brotli
  4. git submodule update --init
  5. cd ~

国内云平台下载 Github 上的项目可能会失败,并非一定会失败,但如果你碰到了一直失败的情况,那么就在能科学上网的本地环境下把这个源码下载下来(Linux、Unix 系统环境依然是跟着上述操作,Windows 系统环境下就是路径写法不同),额外就是需要将它压缩了,建议使用 “tar” 或者 “zip”,这里使用 “tar”(tar -czvf ngx_brotli.tar.gz "替换成 ngx_brotli 文件夹的绝对路径"),再通过 FTP 工具传输到服务器上指定账户根目录解压缩(tar -xzvf ngx_brotli.tar.gz)。

准备 “ngx-ct“ 源码

系统权限:不要求一定要在管理员账户下操作。本文设定在非管理员账户下操作。

这是让 Nginx 支持 Certificate Transparency 策略证书的模块。

登录服务器后,确定在当前账户根目录下,下载 “ngx-ct” 源码,下载的文件是个压缩文件,先解压它,解压后的文件夹名称叫做 “nginx-ct-1.3.2”,重命名成简易的形式以方便编译 Nginx 源码时使用。

为了方便、快速,将上述操作整理成清单,

  1. cd ~
  2. wget -O ngx-ct.zip -c https://github.com/grahamedgecombe/nginx-ct/archive/v1.3.2.zip
  3. unzip ngx-ct.zip
  4. mv nginx-ct-1.3.2 ngx-ct

准备 OpenSSL 源码

系统权限:不要求一定要在管理员账户下操作。本文设定在非管理员账户下操作。

这是实现 HTTPS 功能的加密模块。

登录服务器后,确定在当前账户根目录下,下载 “openssl” 源码,下载的文件是个压缩文件,先解压它,解压后的文件夹名称叫做 “openssl-3.0.7”,重命名成简易的形式以方便编译 Nginx 源码时使用。

为了方便、快速,将上述操作整理成清单,

  1. cd ~
  2. wget -O openssl.tar.gz -c https://www.openssl.org/source/openssl-3.0.7.tar.gz
  3. tar zxf openssl.tar.gz
  4. mv ~/openssl-3.0.7 ~/openssl

OpenSSL 3.0 是 OpenSSL 的最新主要版本,也是一个长期支持 (LTS) 版本。之前的 LTS 版本(1.1.1 系列)也可用并支持到 2023 年 9 月 11 日。所有旧版本(包括 1.1.0、1.0.2、1.0.0 和 0.9.8)现在都不再受支持,应该不被使用。

准备 Nginx 源码

系统权限:不要求一定要在管理员账户下操作。本文设定在非管理员账户下操作。

登录服务器后,确定在当前账户根目录下,下载最新 “nginx” 源码,下载的文件是个压缩文件,先解压它,解压后的文件夹名称叫做 “nginx-1.23.2”,这里不需要重命名它,直接切换到这个文件夹的根目录即可。

为了方便、快速,将上述操作整理成清单,

  1. wget http://nginx.org/download/nginx-1.23.2.tar.gz
  2. tar zxvf nginx-1.23.2.tar.gz
  3. cd nginx-1.23.2

配置 Nginx 编译规则

系统权限:不要求一定要在管理员账户下操作。本文设定在非管理员账户下操作。

在开始构建 Nginx 前,需要设定下构建规则,遵循 “优先保留默认配置,仅对关键部分定制” 的原则。紧跟着上一步,此时应该在 ~/nginx-1.23.2 文件夹的根位置,可以操作 pwa 指令检查一下。直接执行下述指令,

./configure --add-module=../ngx_brotli --add-module=../ngx-ct --with-openssl=../openssl --user=nginx --group=nginx --with-file-aio --with-http_ssl_module --with-http_v2_module --with-http_gzip_static_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module --with-http_slice_module --with-http_stub_status_module --with-http_degradation_module

--add-module=../ngx_brotli --add-module=../ngx-ct --with-openssl=../openssl 这部分目的是关联之前准备的必要模块源码。

“ngx_brotli”、“ngx-ct”、”openssl“、”nginx-1.23.2“ 文件夹都在用户根目录,即:

~
|- ngx_brotli
|- ngx-ct
|- openssl
|- nginx-1.23.2

但当前工作位置在 ”nginx-1.23.2“ 文件夹根目录中,所以使用 ../ 相对路劲指向 “ngx_brotli”、“ngx-ct”、”openssl“。

--user=nginx --group=nginx 这部分设置非特权用户的名称,默认是 “nobody”,为了增强辨识性,改名为 “nginx”。

--with-file-aio --with-http_ssl_module --with-http_v2_module 这部分启用几个 Nginx 内置但未默认启用的功能,它们对于当前文章而言时必须的。

--with-http_gzip_static_module --with-http_gunzip_module --with-http_realip_module --with-http_geoip_module --with-http_slice_module --with-http_stub_status_module --with-http_degradation_module 这部分同样是启用几个 Nginx 内置但未默认启用的功能,但这它们对于当前文章而言是可选的。

日志、缓存之类的路径都采用默认的,

  • Nginx 可执行文件的位置就在 /usr/local/nginx/sbin/nginx 这里;
  • 配置文件在 /usr/local/nginx/conf 这里;
  • 主要错误、警告、诊断、锁、请求日志、进程 ID 文件都在 /usr/local/nginx/logs 里;
  • 静态资源目录都在 /usr/share/nginx/html 这里;
  • 各类缓存目录也会在 /usr/local/nginx 里,执行 ls /usr/local/nginx 可快速查看,这类文件件名都会带个 “_temp” 后缀;
  • 安装 nginx 动态模块的目录在 /usr/local/nginx/modules 这里;

发现没,所有路径的基础路径都是 /usr/local/nginx,如果要修改,可以通过设置 --prefix=路径 参数(父级路径,默认是 /usr/local/nginx)统一修改他们的,没有特殊需求的情况下,没必要修改。修改了之后,接下来的操作,但凡包含 /usr/local/nginx 路径的都得修改。

从 Nginx v1.9.11 开始,有 2 种方式使用额外的模块,本文选择将它们集成编译,而非编译成可单独动态加载的独立模块,因为目前官方只有几个模块支持动态加载,第三方模块需要自身升级支持才可编译成动态模块,支持加载动态模块的麻烦胜过好处。待生态支持较好了,再优先使用 “加载动态模块” 方式,到时候也会更新到本文中。

编译、安装 Nginx

系统权限:部分操作需要管理员权限。本文设定在非管理员账户下操作。

紧跟着上一步,此时应该在 ~/nginx-1.23.2 文件夹的根位置,可以操作 pwa 指令检查一下。

上一步中 Nginx 的构建规则已配置好,但系统中还没有名为 “nginx” 的用户、工作组,先创建它们,之后就可以开始构建了,构建成功后直接安装即可。

为了方便、快速,将上述操作整理成清单,

  1. sudo groupadd -f nginx
  2. sudo useradd -g nginx nginx
  3. make
  4. sudo make install
  5. cd ~

如果本来就在管理员账户下,上述操作不需要 sudo 指令部分。

检测 Nginx 安装成功与否

系统权限:需要管理员权限。本文设定在管理员账户下操作。

如果当前不在 root 用户下,会发现检查(/usr/local/nginx/sbin/nginx -t)结果是失败的。

有多个原因,比如:日志路径(/usr/local/nginx/logs)、缓存路径(/usr/local/nginx)都在根用户权限的路径(/usr/local/nginx)下。但这些都不是关键,关键是:只有 root 进程可以监听低于 1024 的端口,而一般的服务器都会监听 80 或者 443 接口,它们都低于 1024。

所以,Nginx 只能运行在根用户名下。或者说,只要切换到根用户下,检查(/usr/local/nginx/sbin/nginx -t)结果就是通过的。

否则就需要修改 Nginx 涉及到的所有路径的权限,监听的端口号也不能低于 1024,这会变得极其麻烦,可执行性很差。

支持 nginx 全局化名

系统权限:需要管理员权限。本文设定在管理员账户下操作。

从源码构建、安装 Nginx 后,全局系统环境下没有 nginx 这个指令,需要修改(vim ~/.bashrc) Bash 配置文件,在最后添加PATH=/usr/local/nginx/sbin:$PATH,重载 Bash 会话即可。如果是 zsh 的话,就修改 “~/.zshrc” 文件,再重载会话。

支持以守护进程的方式操作 Nginx

系统权限:部分操作需要管理员权限。本文设定在管理员账户下操作。

维护系统难免重启,重启后 Nginx 是不会自己启动,要手动启动。每次重启服务器都需要重启一次,非常的麻烦。这时候可以利用守护进程解决这个问题。

创建(vim /lib/systemd/system/nginx.service)守护进程文件,

[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

之后,还需要手动设置(systemctl enable nginx)为在系统引导时自动启用 Nginx。

如果修改了 "/lib/systemd/system/nginx.service",需要告知 systemctl,systemctl daemon-reload

启动 Nginx

系统权限:需要管理员权限。本文设定在管理员账户下操作。

先让 Nginx 自检(nginx -t),自检通过的话,一般显示如下,

nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

自检通过后可直接启动(systemctl start nginx),之后就可以在浏览器里输入 http://[替换成服务器的 IP] 浏览 Nginx 服务器提供的默认页面了。

本文不会赘述 Nginx 配置文件的部分,不过每次修改了配置文件后,都可以这样先自检再启动或重载 Nginx 服务。

顺利启动了,但 http://[替换成服务器的 IP] 无法访问

检查下防火墙是不是没配置 HTTP 流量可出可入。 这几个指令可以看系统里默认使用的是什么防火墙,

  • systemctl status firewalld
  • systemctl status ufw 出现类似 Unit firewalld.service could not be found. 字样说明系统使用的不是指令中检测的防火墙。 假设系统默认使用 ufw 配置防火墙,这番操作后刷新 http://[替换成服务器的 IP] 即可访问,
  • ufw allow http
  • ufw allow https
  • ufw enable \ ufw reload

重载 Nginx

系统权限:需要管理员权限。本文设定管理员账户下操作。

systemctl reload nginx

如果网站配置中包括缓存配置,重载前先清理缓存,也就是清空缓存目录,否则可能发生重载后网站没变化的问题。

停止 Nginx

系统权限:需要管理员权限。本文设定在管理员账户下操作。

systemctl stop nginx

查看 Nginx 进程状态

系统权限:需要管理员权限。本文设定在管理员账户下操作。

systemctl status nginx

卸载

系统权限:需要管理员权限。本文设定在管理员账户下操作。

  • Nginx 可执行文件;
  • 配置文件;
  • 主要错误、警告、诊断、锁、请求日志、进程 ID 文件;
  • 静态资源目录;
  • 各类缓存目录;
  • nginx 动态模块的目录; … 这些文件、目录都要删除掉,但因为它们都在 /usr/local/nginx 这个位置,直接执行 rm -rf /usr/local/nginx 指令即可。

/usr/share/doc 位置可能会有 Nginx 的帮助文档,如果存在,也需要将它删除。

检查(grep '^ubuntu' /etc/passwdid nginx)目前系统里有没有 “nginx” 用户,有的话也得清除(sudo deluser --remove-home nginx)掉,还得检查(getent group nginx)是否还有 “nginx” 分组,有的话也得清除(sudo groupdel nginx)掉。

如果为 Nginx 创建了守护进程,删除相关文件(rm -rf /lib/systemd/system/nginx.service)。

到这里就把 Nginx 卸载干净了,一般这时候会重启系统(systemctl reboot),确保内存中不会残留。

结语

本文 针对 HTTP 或反向代理服务 去编译 Nginx,除了 保留 Nginx 的默认功能 外,还 扩展了一些功能。但是具体的 HTTP 服务、反向代理服务如何配置,并非本文偏重,且听下回分解。本文单一为了顺利从源码编译、安装 Nginx。

附言一

打算将我的笔记都以文章的形式发布出来,与大家分享,更多(80%)还是想交流,集思广益,另外也想结识些志趣相投的新朋友,好朋友,🫵🏼,我知道你就在那儿,快联系我吧!😬(微信:iyoooooooo