如何在 CentOS 上编译安装及配置最新版 Nginx

Nginx 的官方文档提供了有关如何在不同的操作系统中以不同方式安装 Nginx 的详尽资料。如果你的时间有限,急需在短时间内安装使用 Nginx,可参考本文提供的最佳实践快速进行安装配置。

本文以 Nginx 当前最新稳定版本 1.20.2 为例,详细介绍了如何在 CentOS 上安装及简单配置 Nginx。本文提供的安装步骤在 CentOS 7、CentOS 8 以及 CentOS Stream 8 中均实际测试过。

本文假设你登录的账户已取得管理员账户(root)权限,因为文中出现的命令大部分都需要用到 root 账户权限。如果你登录的是普通账户,可运行 sudo -s 命令切换到带有 root 权限的 Shell,否则需要在每条命令前添加 sudo 命令。

本文在用到包管理器时,会统一使用 yum 命令,但是要知道在 CenOS 8、CentOS Stream 8 及更新版本的 CentOS 中,yum 命令已被 dnf 命令替代(以符号链接的形式存在),运行 yum 命令实际上是运行 dnf 命令。

一、选择安装方式

Nginx 可以通过“包管理器安装”也可以通过“源代码编译安装”。这两种安装方式各有优缺点。用包管理器安装非常快捷,但是无法定制额外的功能。通过编译源代码安装有很大的定制空间,但是需要自己管理相关依赖。

另外,通过“包管理器安装”还存在两个问题。如果通过系统原生软件库安装,往往不是最新版本。如果用 Nginx 官方提供的软件库安装,虽然可以安装最新版本,但是会和系统原生软件库的安装文件混在一起,存在潜在的冲突问题。

二、下载 Nginx

Nginx 提供了两种版本,分别是“主线版本”(Mainline version)和“稳定版本”(Stable version)。前者是最新版本,虽然可用性不太会有问题,但是会引入一些实验性模块,也可能会出现一些新的错误。后者不像前者那样包含最新功能,但是在“向后移植”(Backporting)时会修复主线版本存在的严重错误。官方推荐在生产服务器使用稳定版本,也是本文示例所选择使用的版本。

从 Nginx 官方下载页面获取最新稳定版源代码压缩包的下载链接:

Nginx 官方下载页面https://nginx.org/en/download.html

切换到系统的源代码存放目录,将 Nginx 的源代码压缩包下载下来:

cd /usr/local/src
curl -LO https://nginx.org/download/nginx-1.20.2.tar.gz

三、编译 Nginx

相对于用包管理器安装 Nginx,通过源代码编译 Nginx 会有较多步骤,并且在编译过程中可能会遇到各种各样的意外情况,但是只要保持耐心,确定问题根源所在,就能有效地解决它。

编译 Nginx 主要分两步,一是用 Nginx 源代码附带的配置脚本定制功能,生成 Makefile 文件(待执行的一组任务规则),二是用 Make 工具根据 Makefile 文件中的规则自动化构建 Nginx。下文会详细解释这两个步骤。

1、编译环境

Nginx 是用 C 语言编写的,因此编译 Nginx 需要确保 CentOS 系统中安装了 C 编译器,本文以 GCCGNU Compiler Collection)为例,当然你也可以选择使用其它你所喜欢的 C 编译器。

另外还需要安装自动化构建工具 Make,它的作用是根据配置脚本生成的 Makefile 文件自动将源代码构建成可执行程序和库。

运行以下命令为 CentOS 系统安装 GCC 及 make 程序:

yum install -y gcc make

2、定制功能

解压缩 Nginx 源代码压缩包,并切换到源代码所在目录(注意,除非有说明,所有操作都会在该目录下进行,切勿离开):

tar -xvf nginx-1.20.2.tar.gz
cd nginx-1.20.2

在该目录下可以找到一个名为 configure 的 Shell 脚本文件,它是 Nginx 源代码附带的“配置脚本(configure script)”。该脚本有两个作用:一是通过它提供的丰富的选项细颗粒度地定制 Nginx 功能;二是自动匹配系统中的库和待编译 Nginx 所依赖的库(如果依赖库有缺失,该脚本会中断执行并提示缺失库的名称,以便你来解决该依赖)。

运行以下命令查看含有所有可用配置选项的脚本帮助内容(按 q 键退出):

./configure --help | less

除此外,也可以参考 Nginx 官方文档的“从源代码构建 Nginx”。这些内容对每个配置选项都做了简要说明,并提供了每个配置选项所对应功能模块的参考文档链接。

至于应该使用哪些选项,与你的实际需求有关。比如,你想要让 Nginx 支持 HTTPS 协议,就需要安装 SSL 模块,否则就不需要安装。

本文示例假设所编译的 Nginx 用途是 Web 服务器,并且能够支持 SSLHTTP/2 以及从指定 HTTP 请求头获取客户端 IP 地址。这些功能与编译配置选项的对应关系如下所示:

配置选项对应功能
–prefix指定安装路径
–with-http_ssl_module支持 HTTPS 协议
–with-http_v2_module支持 HTTP/2
–with-http_realip_module从指定请求头获取客户端 IP 地址
编译 Nginx 的配置选项与对应的功能

要想让 Nginx 具备上面所提到的那些附加功能,编译时可能需要依赖一些函数库(Library),如果缺少某个库,在运行配置脚本时就会中断并抛出提示,不过每次中断只会抛出一个提示。如果上面提到的功能符合你的需求,为避免多次尝试浪费时间,可以直接运行以下代码为操作系统安装这些程序库:

yum install pcre-devel zlib-devel \
openssl-devel 

在安装完编译 Nginx 所依赖的库后,运行配置脚本进行配置:

./configure --prefix=/usr/local/nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module

注意,命令中的 --prefix 选项是用来指定 Nginx 安装位置的,你可以选择任意位置,但是作为最佳实践,将其指定为系统的本地程序目录是一个不错的选择。当然,你也可以忽略该选项,这会导致 Nginx 的安装文件散落在各处(即 /usr/local 目录下的 etclibbin 等目录)。

配置脚本运行完毕,如果你能看到如下所示的提示信息,就表示一切正常,可以正式开始进行编译了。

...
Configuration summary
  + using system PCRE library
  + using system OpenSSL library
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

3、进行编译

接下来就可以运行以下代码对 Nginx 源码进行编译了:

make

如果你的服务器配置较高,可以在编译时通过 make 命令的 -j 选项开启多个进程以加快编译速度,比如同时用 3 个进程进行编译:make -j3

编译时间的长短与服务器的配置、可用系统资源以及具体的编译配置有关。编译 Nginx 所需要的系统资源不多,一般情况下,即便是配置不高的服务器也能很快编译成功。

编译成功后,你可以看到如下所示的提示信息:

...
-ldl -lpthread -lcrypt -lpcre -lssl -lcrypto -ldl -lpthread -lz \
-Wl,-E
sed -e "s|%%PREFIX%%|/usr/local/nginx|" \
	-e "s|%%PID_PATH%%|/usr/local/nginx/logs/nginx.pid|" \
	-e "s|%%CONF_PATH%%|/usr/local/nginx/conf/nginx.conf|" \
	-e "s|%%ERROR_LOG_PATH%%|/usr/local/nginx/logs/error.log|" \
	< man/nginx.8 > objs/nginx.8
make[1]: Leaving directory '/usr/local/src/nginx-1.20.2'

四、安装 Nginx

编译完成后即可运行以下命令将 Nginx 安装到之前指定的目录:

make install

至此 Nginx 就安装完成了。如果你是第一次按照本文步骤安装 Nginx,为方便之后运行 Nginx 的相关命令,可运行以下命令将 Nginx 的可执行文件目录添加到系统环境变量 PATH 中:

echo 'export PATH="/usr/local/nginx/sbin:$PATH"' >> ~/.bashrc
source ~/.bashrc

现在运行以下命令,应该能够看到所安装 Nginx 的版本号:

nginx -v

五、配置 Nginx

根据 Nginx 的不同用途,Nginx 官方文档的“管理员指南”提供了丰富的配置指南,如负载均衡(Load Balancer)、Web 服务器(Web Server)、邮件代理(Mail Proxy)等。本文仅以最佳实践配置一个简单的 Web 服务器,使其能够正常访问静态文件(如 HTML 页面、图片等)。

1、分配用户权限

Nginx 启动后会出现两种进程,分别是主进程(master process)和工作进程(worker process)。前者只有一个,作用是读取、估算配置,以及管理工作进程。后者可以有多个(个数可通过配置文件中的指令 worker_processes 进行设置),作用是处理请求。

主进程要以管理员账户(root)的身份运行。这是因为在 Linux 系统中,绑定低于 1024 的本地 TCP 端口号必须使用管理员账户(root)权限,而 Web 服务器所使用的 HTTP 协议和 HTTPS 协议的默认端口分别是 80 和 443,Nginx 要绑定这两个端口号,就必须有管理员账户权限。另外,还需要 root 权限读取配置文件。

而工作进程则需要以普通用户身份运行。这是因为实际处理请求的是工作进程,限制其权限可以避免出现危及操作系统安全的潜在隐患。该账户通常是 Web 服务器专用账户,如 www-data(接下来会在 Nginx 的配置文件中设定),一般与 FastCGI 程序(如 PHP-FPM)所使用的账户相同。

2、创建专用账户

正如前面所提到的,Web 服务器通常会使用专用账户,用于存放、读写 Web 文件(包括图片、HTML 文件及 Web 应用程序)。

创建专用账户可以用任意用户名,本例使用 www-data。你可以运行以下命令检查系统中是否存在该用户:

id www-data

如果出现类似“no such user”的提示就表示不存在此账户,可以运行以下命令创建一个名为 www-data 的无登录权限的系统用户:

useradd www-data -s /sbin/nologin

3、修改配置文件

Nginx 提供了一个开箱即用的配置文件,里面提供了一个静态 Web 服务器配置示例,只要启动 Nginx 就能访问。此外,该配置文件还提供了一些其它可以展示 Nginx 功能的配置示例,只是默认情况下是被注释的。

为了方便对 Nginx 配置文件中的相关指令进行解释说明,避免被不相关信息的干扰,本文不使用该默认配置文件,而是新建一个配置文件,仅放入我们所需要的指令。

首先运行以下命令将 Nginx 默认配置文件备份一下:

mv /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf.bak

然后用你喜欢的编辑器(这里用的是 vi 编辑器)为 Nginx 创建一个新配置文件,文件名与默认配置文件一致,也是 nginx.conf

vi /usr/local/nginx/conf/nginx.conf

将以下内容复制粘贴到新创建的配置文件中,然后保存并退出编辑器(vi 编辑器先按 ESC 再输入 :wq 并回车):

user  www-data;
worker_processes  auto;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   /home/www-data/www;
            index  index.html index.htm;
        }
    }
}

以上配置中一共出现了 13 个指令,其中包括 9 个单指令(simple directive)和 4 个块指令(block directive),即后面带有花括号 {} 的指令。如果一个块指令能够包含其它指令,即可称其为“上下文”(context)。

在这些指令中,有的属于 Nginx 的“核心功能”,用来配置与 Nginx 程序自身运行相关的功能,如 user、worker_processes、events、worker_connections 和 include;有的属于 Nginx 的“HTTP 核心模块”,如用来配置与 HTTP 服务器相关的功能,如 http、default_type、server、listen、server_name、location 和 root;还有的属于 Nginx 的“HTTP 索引模块”,用来处理结尾为斜杠 / 的请求,如 index。下面会按照从上到下的顺序依次解释这些指令的作用。

第 1 个是 user 指令,用来设定运行 Nginx 工作进程的用户和用户组,这里将其设定为之前创建的专用账户,以便 Nginx 有权限访问所有者是该用户的文件。

第 2 个是 worker_processes 指令,用来设定 Nginx 工作进程的个数,如果你的服务器配置较高,可以更改其值增加工作进程个数,以提升 Web 服务器的性能。该指令的最佳值取决于许多因素,不过一般可设为 CPU 内核数量,或设为 auto(自动检测 CPU 核心数)。

第 3 个是一个名为 events 的块指令,它是一个上下文,作用是通过添加一些指令来影响连接处理。

第 4 个是包含在 events 块指令中的 worker_connections 指令,用来设定每个 Nginx 工作进程能够同时打开的最大连接数。你可以将其设为操作系统对每个进程打开文件最大数量限制(即通过运行命令 ulimit -n 获取到的值),如本例中的 1024

第 5 个是名为 http 的块指令,作用是通过添加一些指令来控制 HTTP 通信。接下来要介绍的 8 个指令都包含在其中。

第 6 个是 include 指令,作用是将外部文件包含到配置文件中。本例将 Nginx 预置的名为 mime.types 的文件包含了进来,该文件中只有一个名为 types 的块指令,其作用是设置文件扩展名与“MIME 类型“的映射,当客户端请求带有某种扩展名的文件时,Nginx 就会用相应的 MIME 类型进行响应。

第 7 个是 default_type 指令,用来设定默认的 MIME 类型,当 Nginx 找不到某种扩展名所对应的 MIME 类型时,会使用此默认类型。本例中将其设置为 application/octet-stream,表示默认以普通二进制文件的形式响应给客户端,换句话说就是下载这个文件。

第 8 个是名为 server 的块指令,作用是通过添加一些指令配置虚拟服务器(virtual server)。一个 server 指令对应一个虚拟服务器。接下来的指令都包含在其中。

第 9 个是 listen 指令,通常用来为虚拟服务器设定一个供请求的端口。如果没有特殊需要,需要将该指令的值设为 HTTP 协议的默认端口 80,如果虚拟服务器要使用 HTTPS 协议,则要使用其默认端口 443。

第 10 个是 server_name 指令,作用是为虚拟服务器设定名称,通常利用其绑定一个或多个域名,由于绑定域名超出了本文范围,所以本文仅以本地主机名 localhost 为例。

第 11 个是名为 location 的块指令,用来设定与“请求 URI”(Request URI)[1] 进行比对的“前缀字符串”(prefix strings),如果请求 URI 与前缀相匹配,就将请求 URI 添加到 root 指令设定的路径上,形成本地文件系统上的请求文件路径。本例中将该指令的字符串前缀设定为斜杠 /,即匹配所有请求,如果请求的文件路径存在,Nginx 就会发送该文件。

第 12 个是 root 指令,用来设定供客户端请求的根目录。该指令可用在 http、server、location 等多个上下文中,默认值为安装目录下的 html 文件夹。本例将其用在了 location 上下文中,并将其值设定为 /home/www-data/www

第 13 个是 index 指令,用来指定用作索引的文件,其值可以是用空格分隔的多个文件名。如果请求的是一个目录,即请求 URI 是以斜杠 / 结尾的,Nginx 将会尝试在 root 指令所设定的目录中逐个查找该指令所设定的文件,一旦找到就会导致一个内部重定向,进而使用匹配该请求的 location 块指令进行处理。

正如前面所提到的,默认情况下 root 指令设定的存放 Web 文件目录是与 Nginx 的安装文件混放在一起的,如下所示:

/usr/local/nginx/html

这显然不是一个好习惯,因此,作为最佳实践,我们将其转移至专用账户 www-data 的家目录(/home/www-data)下。

运行以下两条命令,将 Nginx 默认的 Web 文件存放目录其转移至 www-data 家目录下,同时重命名为 www,并更改该文件夹的所有者和用户组为 www-data:

mv /usr/local/nginx/html /home/www-data/www
chown -R www-data:www-data /home/www-data/www

配置修改完成后,可以运行以下命令进行测试,如果能看到 successful 字样就表示配置文件不会影响 Nginx 的运行:

nginx -t

六、启动 Nginx

虽然可以直接通过 nginx 命令启动 Nginx,但是为了让其更稳定的运行(避免因服务器宕机或维护性重启导致 Nginx 停止运行),有必要将其作为服务托管给操作系统,这样不论何种原因导致的系统重启,Nginx 都能随机启动。

在 CenOS 中,可以使用系统服务管理器 systemd 来管理各种服务。要将 Nginx 托管给 systemd,需要为其创建一个配置文件,以便让其管理。

使用你喜欢的编辑器创建一个名为 nginx.service 的配置文件到如下所示路径(这里使用的是 vi 编辑器):

vi /etc/systemd/system/nginx.service

然后将如下所示的内容复制粘贴到该文件中并保存(vi 编辑器先按 ESC 再输入 :wq):

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

[Service]
Type=forking
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID

[Install]
WantedBy=multi-user.target

接着运行以下命令,让 systemd 读取新创建的配置文件:

systemctl daemon-reload

现在通过运行以下命令启动 Nginx 服务:

systemctl start nginx

通过运行以下命令重新启动 Nginx 服务:

systemctl restart nginx

如果修改了 Nginx 的配置文件,可以通过运行以下命令重新加载配置文件,并使用新配置启动新的工作进程,优雅地关闭旧的工作进程:

systemctl reload nginx

当然你也可以直接运行 nginx 命令达到与此相同的效果:

nginx -s reload

运行以下命令查看 Nginx 服务的状态:

systemctl status nginx

如果服务的状态为 Active: active (running) 且没有显示任何错误或警告信息的话,就表示一切正常。可以运行以下命令进行测试:

curl 127.0.0.1

如果能看到含有“Welcome to nginx!”字样的 HTML 代码,说明 Nginx 服务已经可以正常运行了。如果你的云服务器 VPC 安全组规则和 CentOS 系统防火墙均已放行 80 端口入站,也可以在网页浏览器通过服务器的 IP 地址访问该页面。

最后,将 FPM 作为服务添加到随机启动:

systemctl enable nginx

至此,就完成了在 CentOS 上安装配置 Nginx 的全部流程。

七、升级 Nginx

如果想要升级到 Nginx 今后发布的新版本,只需要按照以上步骤重新操作一到四步即可。因为重新安装 Nginx 时不会覆盖已有配置文件,所以无需修改它们。

八、总结

完成以上流程后,应该能够得到如下所示的这些可用文件或信息。这些信息可能会在维护 Nginx 时用到。

Nginx 配置文件路径:

/usr/local/nginx/conf/nginx.conf

Nginx 的系统服务配置文件路径:

/etc/systemd/system/nginx.service

如果你在操作的过程中遇到了任何问题,可留言提出。


[1] 注意这里术语 Request-URI 是由 HTTP 规范(RFC 2616,§5.1.2)定义的。

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注