公司动态
Nginx Web服务器搭建:从安装配置到反向代理与HTTPS实战
1. 项目概述为什么选择 Nginx 来搭建 Web 服务器如果你手头有一台 Linux 服务器无论是云上的 ECS 还是家里的旧电脑想让它对外提供网站服务搭建一个 Web 服务器通常是第一步。在众多选择中Nginx 是我个人最推荐也是业界使用最广泛的选择之一。它不仅仅是一个 Web 服务器更是一个高性能的反向代理、负载均衡器和 HTTP 缓存服务器。简单来说它就像一个能力超强的“前台”和“调度员”既能高效地处理用户请求把静态网页文件飞快地送出去也能把复杂的动态请求转发给后端的应用服务器比如 PHP、Python、Java 写的程序自己则专注于处理网络 I/O 这种它最擅长的事情。为什么是 Nginx 而不是别的早年 Apache 的httpd是绝对主流它采用“一个连接一个进程”的模式在面对成千上万的并发连接时内存和 CPU 开销会变得很大。Nginx 则采用了事件驱动的异步非阻塞架构用很少的进程通常就几个就能处理海量的连接在高并发场景下资源占用极少性能表现非常出色。这对于个人博客、企业官网乃至大型互联网应用都至关重要。而且它的配置文件非常清晰模块化设计让功能扩展也很方便。从你提供的热词也能看出大家关心的不仅仅是安装还有反向代理、负载均衡、安全配置等进阶话题这恰恰说明了 Nginx 在真实生产环境中的核心地位。接下来我会以一个从零开始的视角带你完成在 Linux 上搭建和配置一个基础但稳固的 Nginx Web 服务器的全过程并穿插那些只有踩过坑才知道的细节。2. 核心需求解析与方案选型在动手之前我们得先想清楚我们要做什么以及为什么这么做。搭建一个 Web 服务器核心需求无非是让外界能通过 IP 地址或域名访问到我们放在服务器上的网页文件。但为了实现这个目标背后有一系列决策要做。2.1 安装方式的选择包管理器 vs 源码编译这是你遇到的第一个选择。从热词“nginx linux 需要安装不还是解压就可以”、“非yum形式安装nginx”、“yum安装nginx”就能看出大家的困惑。主流方式有两种使用系统包管理器如 yum, apt安装这是最推荐新手使用的方式。以 CentOS/RHEL用 yum或 Ubuntu/Debian用 apt为例命令简单sudo yum install nginx或sudo apt install nginx系统会自动解决软件依赖关系安装后的服务管理也集成到了系统systemctl start nginx。安装的版本通常是系统维护的较稳定版本可能不是最新的但用于学习和生产环境起步完全足够。它的配置文件通常位于/etc/nginx/日志在/var/log/nginx/结构非常规范。源码编译安装从 nginx.org 下载tar.gz源码包自己配置./configure、编译make、安装make install。这种方式优点是可以自定义一切选择最新的版本裁剪不需要的模块以减小体积添加第三方模块如nginx-rtmp-module用于流媒体以及自定义安装路径。但缺点也很明显过程繁琐需要手动解决依赖如 PCRE、zlib、OpenSSL服务管理也需要自己配置。热词中“linux离线安装nginx”通常就指向这种方式因为在内网无网络环境下你需要准备好所有依赖包和 Nginx 源码包进行编译。我的选择与建议除非你有明确的定制化模块需求或者需要特定版本否则一律使用包管理器安装。它省时省力符合系统规范后续维护和升级都更方便。本文后续演示将以 CentOS 8/Stream 或 Rocky Linux 8 为例使用dnfyum 的下一代进行安装其他发行版命令略有不同但思路一致。2.2 基础服务与安全初步考量我们的目标是搭建一个安全的、可维护的 Web 服务器而不仅仅是“能访问”。这意味着在安装配置时我们需要同步考虑以下几点防火墙Linux 系统自带的防火墙如firewalld或iptables默认会阻止外部对 80HTTP和 443HTTPS端口的访问。安装后必须放行。SELinux在 RHEL/CentOS 系列发行版上SELinux 是一个强大的安全模块如果配置不当即使权限正确Nginx 也可能无法读取网页文件。我们需要知道如何排查或临时调整其策略。站点目录规划网页文件放在哪里默认通常是/usr/share/nginx/html或/var/www/html。清晰的目录结构有助于后期管理多个网站。权限管理Nginx 进程通常以nginx用户身份运行我们的网页文件需要让这个用户有读取权限但同时又要避免给予过高的权限如777这是一个安全关键点。3. 一步步安装与初始配置 Nginx让我们开始实际操作。假设你拥有一台全新的 CentOS 8 Stream 服务器并通过 SSH 登录。3.1 通过包管理器安装 Nginx首先更新系统软件包仓库确保我们能获取到最新的软件信息sudo dnf update -y然后直接安装 Nginxsudo dnf install nginx -y这个-y参数表示自动确认安装提示。安装过程会同时解决所有依赖包括 PCRE、OpenSSL 等。安装完成后启动 Nginx 服务并设置开机自启sudo systemctl start nginx sudo systemctl enable nginx现在使用systemctl status nginx命令检查服务状态你应该看到绿色的 “active (running)” 字样。3.2 配置防火墙放行流量如果系统防火墙firewalld是开启的默认通常开启我们需要放行 HTTP (80) 和 HTTPS (443) 服务sudo firewall-cmd --permanent --add-servicehttp sudo firewall-cmd --permanent --add-servicehttps sudo firewall-cmd --reload--permanent表示永久生效--reload是重载配置使其立即生效。3.3 进行首次访问测试在服务器上你可以用curl命令测试本地是否可访问curl http://localhost如果看到返回的 HTML 代码通常是 Nginx 的欢迎页面说明服务在本地运行正常。最关键的一步从你的个人电脑的浏览器访问服务器的公网 IP 地址。你可以在服务器上使用curl -4 icanhazip.com或ip addr show来查看公网 IP。在浏览器地址栏输入http://你的服务器IP你应该能看到 Nginx 的默认欢迎页面。第一个实操心得如果此时浏览器显示“无法连接”或“连接超时”请按顺序排查1.systemctl status nginx确认服务真的在运行2.sudo firewall-cmd --list-all查看http服务是否在允许列表中3. 如果你使用的是云服务器如阿里云、腾讯云还需要检查云服务商控制台的安全组规则确保入方向放行了 80 端口。云服务器安全组是一个虚拟防火墙优先级往往高于系统自身防火墙这是新手最容易踩的坑。4. 核心配置文件详解与第一个自定义站点看到欢迎页只是第一步。接下来我们要理解 Nginx 的配置并搭建自己的网站。Nginx 的核心魅力就在于其清晰、灵活的配置文件。4.1 Nginx 配置文件的组织结构通过包管理器安装后主要的配置文件和目录如下/etc/nginx/nginx.conf主配置文件。这是所有配置的入口通常我们不会直接大量修改它而是通过include指令引入其他文件。/etc/nginx/conf.d/这是存放自定义站点配置的推荐目录。你可以在这里为每个网站创建一个独立的.conf文件例如myblog.confNginx 会自动读取。这种模块化管理方式非常清晰。/etc/nginx/sites-available/和/etc/nginx/sites-enabled/在一些发行版如 Ubuntu的安装中会采用这种模式。available里存放所有可用的配置enabled里存放通过软链接激活的配置。在 RHEL 系中我们主要用conf.d。/usr/share/nginx/html/默认的网站根目录。你刚才看到的欢迎页index.html就在这里。/var/log/nginx/存放访问日志 (access.log) 和错误日志 (error.log)。4.2 创建你的第一个网站配置假设我们要建立一个名为myproject的个人站点。创建网站根目录我们不建议直接使用默认目录。创建一个专属目录便于管理。sudo mkdir -p /var/www/myproject-p参数确保如果父目录不存在则一并创建。设置目录权限将目录的所有者改为你当前的用户方便上传文件同时让nginx用户有读取权限。sudo chown -R $USER:$USER /var/www/myproject sudo chmod -R 755 /var/www/myproject$USER会自动替换为你的用户名。755权限表示所有者可读可写可执行同组用户和其他用户可读可执行。对于静态文件执行权x对于目录意味着可以进入。创建一个测试页面echo htmlbodyh1Hello from MyProject!/h1pThis is my first Nginx site./p/body/html | sudo tee /var/www/myproject/index.html在/etc/nginx/conf.d/下创建站点配置文件sudo vi /etc/nginx/conf.d/myproject.conf使用你熟悉的编辑器如nano。写入以下基础配置server { listen 80; server_name _; # 使用下划线表示匹配所有域名/IP仅用于测试。生产环境请换成具体域名。 root /var/www/myproject; index index.html index.htm; location / { try_files $uri $uri/ 404; } error_page 404 /404.html; location /404.html { internal; } }这个配置块定义了一个虚拟主机server监听 80 端口网站文件根目录在/var/www/myproject默认索引文件是index.html或index.htm。location /块处理所有请求try_files指令会按顺序尝试寻找对应的文件或目录如果都找不到则返回 404 错误。测试配置并重载 NginxNginx 配置修改后务必先测试语法是否正确再重载服务。sudo nginx -t如果看到syntax is ok和test is successful的提示说明语法无误。sudo systemctl reload nginx使用reload而不是restart可以实现平滑重载不影响正在处理的连接。现在再次从浏览器访问你的服务器 IP你应该能看到刚刚创建的 “Hello from MyProject!” 页面而不是默认欢迎页了。第二个实操心得关于server_name在测试阶段我们可以用_或localhost。但当你有域名后必须将server_name改为你的域名例如www.yourdomain.com。Nginx 会根据 HTTP 请求头中的Host字段来匹配server_name从而决定使用哪个server块的配置。一个 Nginx 可以同时服务多个不同域名的网站这就是基于名称的虚拟主机。5. 深入核心配置与性能调优基础站点搭建好后我们可以深入一些关键配置以提升安全性、性能和可维护性。5.1 用户与进程配置打开主配置文件/etc/nginx/nginx.conf看最开头的部分user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid;user nginx;指定 Nginx 工作进程的运行用户。出于安全绝不应该使用root。worker_processes auto;这是性能关键它设置工作进程的数量。auto是一个很好的默认值它会自动设置为 CPU 核心数。对于计算密集型的操作如大量 SSL 加解密可以设置为 CPU 核心数对于 I/O 密集型静态文件服务可以设置为核心数的 1.5 到 2 倍。你可以通过nproc命令查看核心数。error_log错误日志路径和级别。生产环境可以设置为error_log /var/log/nginx/error.log warn;只记录警告及以上级别的错误。5.2 事件模块与连接数优化在nginx.conf的events块中events { worker_connections 1024; # use epoll; # 在Linux上epoll是高性能的事件驱动模型通常Nginx会自动选择。 }worker_connections单个工作进程可以同时处理的最大连接数。这个值直接影响服务器能支持的并发连接上限。最大并发数理论上是worker_processes * worker_connections。对于内存充足的服务器可以适当调高如 4096。但同时需要检查系统的全局文件描述符限制ulimit -n确保其大于worker_connections。5.3 HTTP 块内的通用优化在http块内我们可以设置一些对所有虚拟主机都生效的优化参数http { ... # 关闭Nginx版本号在错误页和响应头中的显示增强安全性 server_tokens off; # 设置客户端请求体的最大大小防止过大请求攻击 client_max_body_size 10m; # 开启高效文件传输模式sendfile对于静态文件服务性能提升显著 sendfile on; # 与sendfile配合减少网络包数量提升大文件传输效率 tcp_nopush on; # 保持连接超时时间减少连接建立开销 keepalive_timeout 65; # 开启Gzip压缩有效减少传输数据量 gzip on; gzip_min_length 1k; gzip_comp_level 2; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; ... }5.4 针对静态站点的 Location 优化在我们站点的server块内可以针对静态资源如图片、CSS、JS进行缓存优化减轻服务器压力并加速客户端访问。server { ... location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; # 告诉浏览器缓存30天 add_header Cache-Control public, immutable; access_log off; # 可选关闭此类静态资源的访问日志减少磁盘IO } ... }6. 实现 HTTPS 加密与安全加固如今HTTPS 已是网站标配。它通过 SSL/TLS 协议对传输数据进行加密防止窃听和篡改。我们可以使用 Let‘s Encrypt 提供的免费证书。6.1 使用 Certbot 获取免费 SSL 证书Certbot 是 Let‘s Encrypt 官方推荐的自动化证书管理工具。安装前确保server_name已配置为你的域名并且该域名的 A 记录已正确解析到你的服务器 IP。安装 Certbot 和 Nginx 插件以 CentOS 8 为例需先启用 EPEL 仓库sudo dnf install epel-release -y sudo dnf install certbot python3-certbot-nginx -y运行 Certbot 获取并自动配置证书sudo certbot --nginx -d www.yourdomain.com将www.yourdomain.com替换为你的实际域名。按照交互提示操作主要是提供邮箱同意服务条款。Certbot 会自动修改你的 Nginx 配置文件添加 SSL 相关配置并设置自动续期任务。6.2 理解 Certbot 生成的配置Certbot 修改后你的myproject.conf会多出一个监听 443 端口的server块类似这样server { listen 443 ssl http2; # 监听443启用SSL和HTTP/2 server_name www.yourdomain.com; ssl_certificate /etc/letsencrypt/live/www.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.yourdomain.com/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; root /var/www/myproject; ... } server { listen 80; server_name www.yourdomain.com; return 301 https://$server_name$request_uri; # 将HTTP请求永久重定向到HTTPS }可以看到它创建了两个server块一个处理 HTTPS443另一个监听 HTTP80并将所有请求重定向到 HTTPS强制使用安全连接。6.3 额外的安全头部配置在 HTTPSserver块或http块中可以添加一些安全相关的 HTTP 响应头进一步增强安全性add_header X-Frame-Options SAMEORIGIN always; # 防止页面被嵌入iframe点击劫持 add_header X-Content-Type-Options nosniff always; # 禁止浏览器MIME类型嗅探 add_header Referrer-Policy strict-origin-when-cross-origin always; # 控制Referer信息 # 注意在生产环境配置CSPContent-Security-Policy需要非常谨慎避免阻断正常资源加载。7. 进阶实战配置反向代理与负载均衡Nginx 作为反向代理是其最强大的功能之一。它接收客户端请求然后根据规则转发给后端的应用服务器如 Node.js, Tomcat, Gunicorn Django/Flask 等并将结果返回给客户端。这对于前后端分离架构或微服务架构至关重要。7.1 反向代理基础配置假设你有一个运行在服务器本地 3000 端口的 Node.js 应用。你想让用户通过www.yourdomain.com/app来访问它。在你的myproject.conf的 HTTPSserver块内添加location /app/ { proxy_pass http://localhost:3000/; # 注意结尾的斜杠很重要 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_set_header X-Forwarded-Proto $scheme; }proxy_pass指定后端应用服务器的地址。proxy_set_header将原始请求的一些信息如客户端真实 IP、协议传递给后端服务器否则后端应用看到的请求可能全部来自 Nginx 的 IP127.0.0.1。第三个实操心得proxy_pass 结尾斜杠的玄机这是反向代理配置中最容易出错的地方之一。proxy_pass http://backend/;有斜杠会将/app/api转发为/api。而proxy_pass http://backend;无斜杠则会转发为/app/api。务必根据你的后端应用路由需求谨慎配置。7.2 负载均衡配置当你的应用流量增大需要多台应用服务器共同承担时负载均衡就派上用场了。Nginx 支持多种负载均衡算法轮询、权重、IP哈希等。首先在http块内定义一个上游服务器组upstreamhttp { ... upstream backend_servers { # 默认是轮询round-robin server 192.168.1.101:8080 weight2; # weight 设置权重权重越高分配请求越多 server 192.168.1.102:8080; server 192.168.1.103:8080 backup; # backup 标记为备份服务器只有其他都不可用时才启用 # ip_hash; # 启用IP哈希算法同一客户端IP固定访问同一后端可用于会话保持 } ... }然后在server块的location中使用这个上游组location /api/ { proxy_pass http://backend_servers; # ... 其他proxy_set_header等配置 }这样所有到达/api/的请求就会被均匀地分发到backend_servers定义的三台服务器上。8. 日志分析与日常维护清晰的日志是运维的“眼睛”。Nginx 的访问日志和错误日志能帮你分析流量、排查问题。8.1 访问日志格式定制默认的访问日志格式可能信息不全。我们可以在http块中定义一个更丰富的日志格式并在server或location中使用它。http { log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for rt$request_time uct$upstream_connect_time uht$upstream_header_time urt$upstream_response_time; access_log /var/log/nginx/access.log main; }这个main格式包含了客户端 IP、时间、请求、状态码、响应大小、来源、用户代理、真实 IP经过代理时以及几个关键时间指标$request_time请求总处理时间$upstream_response_time后端应用处理时间。这对于性能分析极其有用。8.2 使用工具分析日志实时监控tail -f /var/log/nginx/access.log查看错误grep error /var/log/nginx/error.log统计状态码awk {print $9} /var/log/nginx/access.log | sort | uniq -c | sort -rn统计最频繁的访问IPawk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20分析慢请求awk ($(NF-1) 1){print $7, $(NF-1)} /var/log/nginx/access.log | sort -k2 -rn | head -20假设request_time是倒数第二个字段且大于1秒的请求8.3 日志轮转与清理日志文件会不断增长需要定期轮转和清理。幸运的是通过包管理器安装的 Nginx 通常已经配置了logrotate。你可以查看/etc/logrotate.d/nginx文件它定义了如何压缩旧日志、保留多少份、何时触发轮转等。一般不需要手动干预系统会每天自动执行。9. 常见问题排查与调试技巧实录即使配置再小心问题也难免出现。这里记录几个我踩过的坑和排查思路。9.1 问题一访问返回 403 Forbidden这是最常见的权限问题。排查步骤检查网站根目录的权限ls -ld /var/www/myproject。确保 Nginx 用户通常是nginx对目录有执行权x对文件有读取权r。可以用sudo -u nginx cat /var/www/myproject/index.html模拟 Nginx 用户读取文件。检查 SELinux如果目录权限正确但在 RHEL/CentOS 上仍报 403很可能是 SELinux 在阻止。临时放行sudo chcon -Rt httpd_sys_content_t /var/www/myproject。永久修改需要调整 SELinux 策略或布尔值但对于 Web 目录上述命令通常是正确做法。检查nginx.conf中的user指令是否正确。9.2 问题二配置修改后重载失败nginx -t报错典型错误nginx: [emerg] unknown directive proxy_pass in ...原因proxy_pass指令通常位于location块内如果你把它写在了server块外层或http块内就会报错。检查配置块的层级关系。典型错误nginx: [emerg] invalid number of arguments in listen directive ...原因listen指令语法错误。例如listen 80;是正确的listen 80 443;是错误的。每个server块可以有多个listen指令但不能合并写。通用排查sudo nginx -t会告诉你错误发生在哪个文件的哪一行。仔细检查那一行及其附近的语法特别是分号;是否遗漏花括号{}是否匹配。9.3 问题三反向代理后后端应用获取不到客户端真实 IP现象后端应用日志中所有请求的 IP 都是127.0.0.1。解决方案确保在location块中正确设置了proxy_set_header特别是X-Real-IP和X-Forwarded-For。同时后端应用需要配置为信任这些头部。例如在 Node.js Express 中可能需要设置trust proxy。9.4 问题四上传大文件失败现象上传文件时连接被中断Nginx 错误日志出现client intended to send too large body。解决方案在http、server或location块中增加client_max_body_size指令例如client_max_body_size 50m;将其设置为大于你上传文件的大小。9.5 调试利器Nginx 调试日志当遇到诡异问题时可以开启调试日志获取更详细信息。在nginx.conf的main或events层级注意不是http块内添加error_log /var/log/nginx/debug.log debug;然后sudo systemctl reload nginx并重现问题。查看/var/log/nginx/debug.log里面会有非常详细的处理过程记录。切记调试完成后务必关闭因为该日志会产生大量数据。搭建一个生产可用的 Nginx Web 服务器从安装、配置、优化到排错是一个系统工程。它没有太多“黑科技”更多的是对细节的把握和对原理的理解。从最简单的静态站点开始逐步尝试反向代理、HTTPS、负载均衡每走一步都去理解其背后的配置指令和网络原理这样积累下来的经验才是最扎实的。配置文件就是你的蓝图日志就是你的仪表盘多读多试这个强大的工具会逐渐成为你手中驯服自如的利器。