Ubuntu 20.04 Nginx 部署避坑指南:从安装到生产就绪

1. 为什么在 Ubuntu 20.04 上装 Nginx 不是“点几下就完事”,而是必须亲手过一遍的基建动作

你可能刚买了一台全新的云服务器,系统镜像选的是 Ubuntu 20.04 LTS——这个版本在 2024 年仍被大量生产环境采用,稳定、长期支持、软件源成熟。你打开终端,敲下 sudo apt update && sudo apt install nginx ,回车,提示“安装成功”, systemctl status nginx 显示 active (running),浏览器访问 http://你的IP 出现 “Welcome to nginx!” 页面……看起来一切顺利。

但这就是终点吗?不。这恰恰是真正工作的起点。

我见过太多人卡在这一步之后:前端静态资源放进去却 404,反向代理后端服务时请求超时,HTTPS 配置完浏览器报“不安全”,日志里全是 connect() failed (111: Connection refused) ,甚至 sudo ufw allow 'Nginx Full' 执行后防火墙依然拦着 80 端口——查了半天发现 ufw 规则没生效,因为默认策略是 deny,而 ufw status verbose 显示的是 inactive。更隐蔽的是, nginx.conf 里一句 include /etc/nginx/conf.d/*.conf; 被注释掉了,你新建的 myapp.conf 根本没被加载;或者 worker_processes auto; 在 4 核机器上跑出 8 个 worker,CPU 轮询反而拖慢响应。

这些不是“小问题”,而是 Ubuntu 20.04 + Nginx 组合中高频、高隐蔽性、高破坏力的“默认陷阱”。它们不会在安装阶段报错,却会在你部署第一个真实业务(比如一个 Vue 打包后的 dist 目录、一个 FastAPI 的 /api 接口、甚至一个简单的 JSON 验证码接口)时集中爆发。而 Ubuntu 20.04 的特殊性在于:它默认启用 systemd,但很多老教程还在用 chkconfig 思维;它默认禁用 IPv6,但 Nginx 编译时又默认监听 [::]:80 ;它的 ufw 默认不启用,可一旦启用,规则顺序和协议匹配逻辑又和 iptables 有微妙差异。

所以,这篇内容不是教你怎么“装上”,而是带你亲手走通一条 从裸机到可交付 Web 服务 的完整链路:每一步命令背后是什么逻辑,每个配置项改了会触发什么连锁反应,哪些地方 Ubuntu 20.04 和 CentOS 7 表现不同,哪些热词(比如 sudo systemctl edit nginx.conf 结构、 ufw allow samba command not found 这类错误提示)其实暴露的是更底层的认知断层。你不需要背命令,但需要知道——当 nginx -t 报错时,该先看哪一行;当 curl -I http://localhost 返回 502,该立刻检查哪三个文件;当 systemctl restart nginx 没反应,该用哪条 journalctl 命令挖出真正的 root cause。

这不是一份安装说明书,而是一份 Ubuntu 20.04 上 Nginx 的“生存地图”。

2. 安装前的三重确认:别让系统状态成为后续所有故障的隐形推手

很多人跳过这一步,直接 apt install ,结果装完发现 nginx -v 输出的是 1.18.0,而业务要求必须是 1.22+(因为要支持 proxy_http_version 1.1 的某些新特性),或者发现 nginx -V 里压根没有 --with-http_v2_module ,导致 HTTP/2 无法启用。这不是 Nginx 的问题,是你没看清 Ubuntu 20.04 官方源的“出厂设置”。

2.1 Ubuntu 20.04 官方源的 Nginx 版本与模块清单

Ubuntu 20.04 LTS 的 nginx 包来自 focal-updates 源,截至 2024 年中,其稳定版本为 1.18.0-6ubuntu1.5 。这个版本足够稳定,但有几个关键事实必须清楚:

  • 不包含 ngx_http_geoip2_module :如果你需要基于 GeoIP2 的地域分流,官方源不提供,必须手动编译或换源;
  • --with-http_ssl_module 是启用的 :HTTPS 支持没问题,但 OpenSSL 版本是 1.1.1f,不支持 TLS 1.3 的某些新 cipher suite(如 TLS_AES_128_GCM_SHA256 ),需手动升级 OpenSSL 或换用 PPA;
  • --with-http_v2_module 是启用的 :HTTP/2 支持开箱即用,但默认配置未开启,需在 server 块中显式写 listen 443 ssl http2;
  • --with-http_realip_module 是启用的 :这对获取真实客户端 IP 至关重要,尤其在反向代理场景下,但默认 real_ip_header X-Real-IP ,而很多前端框架(如 Nuxt)发请求时用的是 X-Forwarded-For ,这里就埋下了 502 的伏笔。

验证方式很简单,装完后执行:

nginx -V 2>&1 | grep -E "(version|configure arguments)"

你会看到类似输出:

nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1f  31 Mar 2020
configure arguments: --prefix=/usr/share/nginx --sbin-path=/usr/sbin/nginx ... --with-http_ssl_module --with-http_v2_module ...

提示: nginx -V (大写 V)显示编译参数, nginx -v (小写 v)只显示版本号。很多新手混淆两者,导致误判模块可用性。

2.2 系统级依赖与冲突预检:ufw、systemd、SELinux 的“三重门”

Ubuntu 20.04 默认不启用 SELinux(它用的是 AppArmor),这点和 CentOS 7 完全不同,所以 setsebool sestatus 这类命令在这里毫无意义,强行运行只会报错。但 ufw systemd 是真·主角。

  • ufw 状态必须明确 :执行 sudo ufw status verbose 。如果输出 Status: inactive ,说明防火墙根本没开,此时 sudo ufw allow 'Nginx Full' 是无效操作。正确流程是:先 sudo ufw enable (会提示是否继续,输入 y ),再 sudo ufw allow 'Nginx Full' 。而 'Nginx Full' 这个应用配置文件,实际位于 /etc/ufw/applications.d/nginx ,它定义了开放 80/tcp 和 443/tcp。如果你看到 sudo ufw allow samba command not found 这类错误,99% 是因为 ufw 本身没启用,或者你打错了应用名(比如写成 samba 而不是 Samba ,大小写敏感)。

  • systemd 服务单元文件的“隐藏路径” :Ubuntu 20.04 的 Nginx 服务由 /lib/systemd/system/nginx.service 管理。这个文件里有一行关键配置: ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;' 。意思是每次 systemctl start nginx 前,都会先执行 nginx -t 做语法检查。如果 nginx.conf 有语法错误, systemctl start 会直接失败,并在 journalctl -u nginx 里留下 nginx: [emerg] 错误。这是 systemd 的保护机制,但新手常误以为是“服务没启动”,反复 systemctl restart ,却不知问题出在配置文件。

  • 磁盘空间与 inodes 预检 df -h / 分区剩余空间, df -i 看 inodes 使用率。Nginx 日志(尤其是 access.log)在高并发下会快速消耗 inodes。我曾遇到一个案例: df -h 显示还有 20GB 空间,但 df -i 显示 inodes 100% 耗尽,导致 nginx -t 执行时提示 open() "/var/log/nginx/error.log" failed (24: Too many open files) —— 这其实是 inodes 耗尽的典型伪装错误。解决方案不是调大 ulimit ,而是清理旧日志: sudo find /var/log/nginx -name "*.log.*" -mtime +30 -delete

2.3 网络栈基础:IPv4/IPv6 双栈的“静默开关”

Ubuntu 20.04 默认启用 IPv6,但很多云厂商(如阿里云、腾讯云)的内网网络并不支持 IPv6,导致 Nginx 启动时尝试监听 [::]:80 失败,进而整个服务启动失败。错误日志在 journalctl -u nginx 中表现为:

nginx: [emerg] socket() [::]:80 failed (97: Address family not supported by protocol)

这不是 Nginx 的 bug,是系统网络栈和云平台的兼容性问题。解决方法有两个:

  1. 临时禁用 IPv6 监听 :在 /etc/nginx/sites-enabled/default server 块中,把 listen [::]:80 default_server; 这行注释掉,只保留 listen 80 default_server;
  2. 永久禁用系统 IPv6(谨慎) :编辑 /etc/sysctl.conf ,添加:
    net.ipv6.conf.all.disable_ipv6 = 1
    net.ipv6.conf.default.disable_ipv6 = 1
    
    然后 sudo sysctl -p 生效。但此操作会影响所有 IPv6 应用,仅推荐在纯 IPv4 环境下使用。

注意: ipv6 双栈 服务器 nginx 日志 这个热词,本质是在问——当服务器同时支持 IPv4 和 IPv6 时,如何让 Nginx 日志区分来源?答案是:在 log_format 中加入 $remote_addr (它会自动显示 IPv4 地址或 IPv6 地址),无需额外配置。但前提是你的网络栈和 Nginx 都真正支持双栈。

3. 从零构建可验证的 Nginx 服务:不只是 apt install ,而是五步闭环

安装命令 sudo apt install nginx 只是第一步。真正的服务就绪,需要完成一个闭环:安装 → 配置 → 测试 → 启动 → 验证。漏掉任何一环,都可能在上线后半夜收到告警。

3.1 第一步:安装与基础服务控制( systemctl 的正确姿势)

执行标准安装:

sudo apt update
sudo apt install nginx

安装完成后, 不要立刻 systemctl start nginx 。先做三件事:

  1. 检查服务单元状态

    systemctl list-unit-files | grep nginx
    # 应看到 nginx.service enabled
    systemctl is-enabled nginx
    # 应返回 enabled
    
  2. 理解 systemctl 的四个核心命令

    • sudo systemctl start nginx :启动服务(一次性的,重启后不自动);
    • sudo systemctl enable nginx :设置开机自启(写入 /etc/systemd/system/multi-user.target.wants/nginx.service 符号链接);
    • sudo systemctl daemon-reload :当修改了 /lib/systemd/system/nginx.service 文件后,必须执行此命令让 systemd 重新读取配置;
    • sudo systemctl edit nginx :这是热词 sudo systemctl edit 的编辑器如何使用 的正解。它会创建一个覆盖目录 /etc/systemd/system/nginx.service.d/override.conf ,用于安全地覆盖原服务文件的某几行(比如修改 Environment="NGINX_ENV=prod" ),而不用直接编辑原始文件,避免 apt upgrade 时被覆盖。执行后,系统会自动调用默认编辑器(通常是 nano ),你只需在里面写:
      [Service]
      Environment="NGINX_ENV=prod"
      
      保存退出即可。这是比直接改 /lib/systemd/system/nginx.service 更安全、更符合 Linux 最佳实践的做法。
  3. 首次启动并观察日志

    sudo systemctl start nginx
    sudo systemctl status nginx
    # 必须看到 "active (running)" 且无红色 error 字样
    sudo journalctl -u nginx -n 20 --no-pager
    # 查看最近 20 行日志,确认无 emerg/fatal 级别错误
    

3.2 第二步:配置文件结构解析( nginx.conf 的“宪法”地位)

Ubuntu 20.04 的 Nginx 配置采用“主配置 + 模块化包含”的设计,其结构是:

/etc/nginx/nginx.conf          ← 主配置文件,定义全局指令(user, worker_processes, events, http)
├── /etc/nginx/conf.d/         ← 存放通用配置片段,如 gzip、log_format(默认被 include)
├── /etc/nginx/sites-available/ ← 存放所有站点配置文件(未激活)
└── /etc/nginx/sites-enabled/  ← 存放已激活站点的符号链接(指向 sites-available)

关键点在于 /etc/nginx/nginx.conf 开头的 include 指令:

http {
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

这意味着:

  • 如果你在 /etc/nginx/conf.d/ 下新建一个 custom.conf ,它会被自动加载;
  • /etc/nginx/sites-enabled/ 下的文件必须是符号链接,不能是普通文件。 sudo ln -sf /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp 是标准做法;
  • sites-available sites-enabled 的分离,是为了方便多站点管理。停用一个站点,只需 sudo rm /etc/nginx/sites-enabled/myapp ,无需删除配置文件。

提示: nginx配置文件详解 这个热词,核心就是理解 nginx.conf 的层级关系。 http 块下的指令对所有 server 生效; server 块下的指令只对该虚拟主机生效; location 块下的指令只对该路径生效。 location /api { proxy_pass http://backend; } location / { root /var/www/html; } 是完全独立的,前者不会影响后者。

3.3 第三步:编写第一个可验证的 server 块(告别 Welcome 页面)

删掉 /etc/nginx/sites-enabled/default (或重命名为 default.bak ),新建 /etc/nginx/sites-available/hello

server {
    listen 80;
    server_name _;  # 匹配任意域名,适合测试

    root /var/www/hello;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # 添加一个健康检查端点
    location /healthz {
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }
}

然后创建符号链接并测试:

sudo mkdir -p /var/www/hello
echo "<h1>Hello from Ubuntu 20.04 + Nginx</h1>" | sudo tee /var/www/hello/index.html
sudo ln -sf /etc/nginx/sites-available/hello /etc/nginx/sites-enabled/hello
sudo nginx -t  # 必须通过!这是语法检查的黄金标准
sudo systemctl reload nginx  # 优雅重载,不中断现有连接

验证:

curl -I http://localhost  # 应返回 200 OK
curl http://localhost/healthz  # 应返回 "OK"
curl -I http://localhost/nonexistent  # 应返回 404 Not Found

这一步的价值在于:你亲手构建了一个最小、可验证、可调试的 Nginx 服务实例。它不依赖任何外部服务,所有行为都由你定义,是后续所有复杂配置(反向代理、HTTPS、负载均衡)的绝对基石。

3.4 第四步:防火墙(ufw)的精准放行( ufw allow 的底层逻辑)

sudo ufw allow 'Nginx Full' 是快捷方式,但它的底层逻辑是:

  • 读取 /etc/ufw/applications.d/nginx 文件;
  • 该文件定义了两个端口组: 80/tcp 443/tcp
  • ufw 将其转换为 iptables 规则,插入到 INPUT 链中。

但生产环境往往需要更精细的控制。例如,你只想允许特定 IP 访问管理后台:

sudo ufw allow from 192.168.1.100 to any port 8080

或者,你想禁止所有对 22 端口(SSH)的公网访问,只允许内网:

sudo ufw deny 22
sudo ufw allow from 10.0.0.0/8 to any port 22

验证 ufw 规则是否生效:

sudo ufw status numbered  # 显示带编号的规则列表
sudo ufw status verbose    # 显示详细状态,包括默认策略

注意: ufw 规则的 顺序很重要 ufw 按照规则编号从上到下匹配,第一个匹配的规则生效。所以 deny 规则要放在 allow 规则之后,否则会被提前拦截。

3.5 第五步:日志与监控的“第一道防线”

Nginx 默认日志在 /var/log/nginx/

  • access.log :记录每一次 HTTP 请求(IP、时间、URL、状态码、响应大小);
  • error.log :记录 Nginx 自身错误(配置错误、权限问题、上游连接失败)。

但默认的 access.log 格式太简陋。编辑 /etc/nginx/nginx.conf ,在 http 块中添加:

log_format main '$remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent" '
                 '$request_time $upstream_response_time $pipe';

然后在 server 块中指定:

access_log /var/log/nginx/access.log main;

$request_time 是客户端请求总耗时(单位秒), $upstream_response_time 是 Nginx 转发给后端并收到响应的时间(对反向代理至关重要)。当你看到 access.log 里某行 request_time=0.001 upstream_response_time=5.234 ,就知道瓶颈在后端,而不是 Nginx 本身。

实时监控日志:

# 实时跟踪错误日志
sudo tail -f /var/log/nginx/error.log

# 实时统计每秒请求数(QPS)
sudo awk '{print $4}' /var/log/nginx/access.log | cut -d: -f2 | sort | uniq -c | sort -nr | head -10

# 查找 502 错误(上游连接失败)
sudo grep " 502 " /var/log/nginx/access.log

4. 常见故障的“七步排查法”:从 502 Bad Gateway Connection refused

当你的 Nginx 服务不再返回 “Welcome”,而是抛出各种 HTTP 状态码或 curl 直接超时,你需要一套标准化的排查流程。这不是靠运气,而是按顺序排除可能性。

4.1 第一步:确认 Nginx 进程与端口监听状态

# 检查进程是否存在且运行正常
ps aux | grep nginx | grep -v grep

# 检查 80/443 端口是否被监听(注意 -t 表示 TCP,-n 表示数字端口,-p 表示显示进程)
sudo ss -tlnp | grep ':80\|:443'

# 如果没看到 nginx,说明服务没起来;如果看到的是其他进程(如 apache2),说明端口被占用了

常见陷阱: sudo netstat -tulpn | grep :80 在 Ubuntu 20.04 上可能因 net-tools 未安装而失败, ss 是更现代、更轻量的替代品。

4.2 第二步:语法检查与配置加载验证

# 严格检查语法(-t),并显示使用的配置文件路径(-T)
sudo nginx -t -T

# 如果报错,错误信息会精确到第几行第几列,例如:
# nginx: [emerg] unknown directive "proxy_set_header" in /etc/nginx/sites-available/myapp:12
# 这说明你在第 12 行写错了指令名,应该是 `proxy_set_header`,而不是 `proxy_header_set`。

提示: nginx -t 是最廉价、最高效的“编译期”检查。养成习惯:每次修改配置文件后,必先 nginx -t ,再 systemctl reload

4.3 第三步:服务状态与日志深挖( journalctl 的高级用法)

# 查看 Nginx 服务的全部日志(从启动到现在)
sudo journalctl -u nginx --no-pager

# 查看最近 50 行,并实时跟踪(-f)
sudo journalctl -u nginx -n 50 -f

# 查看上次启动的日志(非常有用,避免滚动日志干扰)
sudo journalctl -u nginx -b

# 按优先级过滤(只看错误和警告)
sudo journalctl -u nginx -p err..warning

journalctl -b 参数(boot)是关键。当你 systemctl restart nginx 后, -b 会只显示本次启动以来的日志,极大提升排查效率。

4.4 第四步:网络连通性与防火墙穿透测试

假设你配置了反向代理到 http://127.0.0.1:8000 ,但浏览器访问 Nginx 返回 502:

# 1. 先确认后端服务是否真的在运行
curl -I http://127.0.0.1:8000

# 2. 如果返回 502,检查后端服务是否监听在 127.0.0.1(而非 localhost 或 0.0.0.0)
sudo ss -tlnp | grep ':8000'

# 3. 检查 ufw 是否拦住了本地回环(loopback)流量?一般不会,但需确认
sudo ufw status verbose | grep -A 5 "Default"

# 4. 用 telnet 测试端口连通性(比 curl 更底层)
telnet 127.0.0.1 8000
# 如果连接失败,说明后端没起来或监听地址不对;如果连接成功,说明网络层通畅。

4.5 第五步:Nginx 内部代理链路诊断( proxy_pass 的灵魂)

502 Bad Gateway 的根源,90% 在于 proxy_pass 配置。一个经典错误是:

location /api {
    proxy_pass http://127.0.0.1:8000/api;  # 错误!末尾的 /api 会导致路径重复
}

当用户请求 /api/users ,Nginx 会转发到 http://127.0.0.1:8000/api/api/users ,后端自然 404。

正确写法是:

location /api {
    proxy_pass http://127.0.0.1:8000/;  # 末尾必须有 /
}

这样 /api/users 会被转发到 http://127.0.0.1:8000/users

另一个关键是 proxy_set_header

location /api {
    proxy_pass http://127.0.0.1:8000/;
    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;
}
  • Host $host :确保后端收到的 Host 头和浏览器请求一致;
  • X-Real-IP X-Forwarded-For :传递真实客户端 IP,后端可通过 request.headers.get('X-Real-IP') 获取;
  • X-Forwarded-Proto :告诉后端当前是 HTTP 还是 HTTPS,避免后端生成 http:// 链接。

4.6 第六步:文件权限与 SELinux/AppArmor(Ubuntu 的真相)

Ubuntu 20.04 用的是 AppArmor,不是 SELinux。如果你看到 nginx: [emerg] open() "/var/www/myapp/index.html" failed (13: Permission denied) ,原因很可能是:

  • Nginx 工作进程用户是 www-data ,而 /var/www/myapp 目录的所有者是 ubuntu 用户,且权限是 750 www-data 组没有读取权限;
  • 解决方案: sudo chown -R www-data:www-data /var/www/myapp sudo chmod -R 755 /var/www/myapp

AppArmor 的日志在 /var/log/audit/audit.log ,但 Ubuntu 默认不安装 auditd 。更简单的方法是临时禁用 AppArmor 策略来验证:

sudo aa-disable /etc/apparmor.d/usr.sbin.nginx
sudo systemctl restart nginx

如果问题消失,说明是 AppArmor 策略限制,需编辑 /etc/apparmor.d/usr.sbin.nginx 添加对应路径权限。

4.7 第七步:终极武器—— strace 动态追踪

当所有常规手段失效, strace 是最后的真相探测器。它能告诉你 Nginx 进程在内核层面到底在做什么:

# 找到主进程 PID
sudo ps aux | grep nginx | grep master

# 对主进程进行系统调用追踪(-p PID,-e trace=open,connect,sendto,recvfrom)
sudo strace -p 12345 -e trace=open,connect,sendto,recvfrom -s 100 -o /tmp/nginx.strace.log

然后在另一个终端触发一次请求( curl http://localhost ),再 cat /tmp/nginx.strace.log 。你会看到 Nginx 尝试 open() 哪些配置文件、 connect() 哪个上游地址、 sendto() 什么数据。这是定位 Connection refused 类错误的终极手段。

5. 进阶实战:从静态服务到生产就绪的四大跃迁

装好 Nginx 只是起点。要让它真正扛起生产流量,还需完成四次关键跃迁。这些不是“可选项”,而是现代 Web 服务的标配。

5.1 跃迁一:HTTPS 全站加密(Let's Encrypt + Certbot)

Ubuntu 20.04 官方源自带 certbot

sudo apt install certbot python3-certbot-nginx

为域名 example.com 申请证书:

sudo certbot --nginx -d example.com -d www.example.com

Certbot 会自动:

  • 修改 /etc/nginx/sites-available/example.com ,添加 listen 443 ssl 和证书路径;
  • 添加 listen 80 return 301 https://$host$request_uri; 强制跳转;
  • 配置自动续期的 systemd timer( certbot.timer )。

关键细节:

  • 证书存放在 /etc/letsencrypt/live/example.com/
  • fullchain.pem 是证书链(供 Nginx 的 ssl_certificate 使用);
  • privkey.pem 是私钥(供 ssl_certificate_key 使用);
  • Certbot 的续期命令是 sudo certbot renew --dry-run (测试)和 sudo certbot renew (真实执行)。

注意: nginx反向代理 和 HTTPS 结合时, proxy_pass 后端如果是 HTTP,Nginx 作为 TLS 终结点,后端无需 HTTPS;但如果后端也要求 HTTPS(如内部微服务),则需在 proxy_pass 中写 https://backend:443 ,并配置 proxy_ssl_trusted_certificate

5.2 跃迁二:反向代理与负载均衡( upstream 模块实战)

定义一个上游集群:

upstream backend_cluster {
    server 127.0.0.1:8000 weight=3 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8001 weight=1 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

server {
    listen 80;
    location /api {
        proxy_pass http://backend_cluster;
        proxy_http_version 1.1;
        proxy_set_header Connection '';
        # 其他 proxy_set_header...
    }
}
  • weight :权重轮询, 8000 接收 3/4 流量;
  • max_fails/fail_timeout :连续 3 次失败后,30 秒内不将请求发给该节点;
  • keepalive 32 :为每个 worker 进程维护最多 32 个到上游的空闲长连接,大幅提升性能。

验证负载均衡效果:

# 在两个后端服务中,分别返回不同的标识
# curl http://localhost/api -> "Backend A"
# curl http://localhost/api -> "Backend B"
# 多次请求,观察响应是否按权重比例切换

5.3 跃迁三:静态资源优化与缓存策略( gzip expires

http 块中添加:

gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

# 静态资源强缓存
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}
  • gzip_types 列出了所有会被压缩的 MIME 类型,务必包含 application/javascript (而非过时的 application/x-javascript );
  • expires 1y 设置一年过期时间,配合 Cache-Control: public, immutable ,让浏览器彻底离线缓存,极大减少请求数;
  • immutable 是关键,它告诉浏览器:这个资源的 URL 永远不会变,因此无需发送 If-None-Match 请求验证。

5.4 跃迁四:安全加固与漏洞防护(针对 CVE-2025-23419 等)

虽然 f5 nginx plus 的漏洞(如 CVE-2025-23419 )不直接影响开源版,但开源 Nginx 也有自己的风险点:

  • 禁用危险模块 :在 nginx.conf http 块中,添加:

    # 禁用 WebDAV(CVE-2026-27654 高危漏洞相关)
    location / {
        dav_methods off;
        create_full_put_path off;
    }
    
  • 限制请求体大小与频率

    client_max_body_size 10M;  # 防止大文件上传耗尽内存
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;  # 每秒最多 10 次请求
    location /api {
        limit_req zone=api burst=20 nodelay;
    }
    
  • 隐藏 Nginx 版本号

    server_tokens off;  # 在 http 或 server 块中
    

    这会让响应头中的 Server: nginx/1.18.0 变成 Server: nginx ,增加攻击者利用已知漏洞的难度。

提示: nginx升级到1.30.2要注意什么 这个热词,核心是:新版 Nginx 移除了 mp4 模块, flv 模块行为变更, http_v2 模块默认启用但需 ssl ,以及 resolver 指令语法变化。升级前务必阅读官方 CHANGES 文件,并在测试环境充分验证。

6. 个人经验总结:那些文档里不会写的“血泪教训”

最后,分享几个我在 Ubuntu 20.04 上部署 Nginx 时,踩过、修过、记下来的“非技术性”但极其重要的经验。

6.1 关于 sudo systemctl edit 的编辑器选择

sudo systemctl edit nginx 默认调用 nano ,但很多资深用户习惯用 vim 。想改成 vim ,只需:

sudo update-alternatives --config editor
# 然后选择 vim.basic

或者临时指定:

sudo EDITOR=vim systemctl edit nginx

但切记: systemctl edit 创建的 override.conf 文件,其语法是 systemd 的 unit file 语法,不是 Nginx 配置语法。写错格式(比如漏了 [Service] 头)会导致 systemctl daemon-reload 失败,进而 systemctl start nginx 报错。所以,永远先 sudo systemctl cat nginx 看看 override 是否被正确加载。

6.2 nginx.conf include 顺序是“法律”

include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; 的顺序决定了配置的加载优先级。 conf.d 中的 gzip.conf 会先于 sites-enabled 中的 myapp.conf 加载,因此 gzip 指令对 myapp 生效。但如果你在 myapp.conf 中又写了 gzip off; ,它就会覆盖 conf.d 中的设置。这种“后加载覆盖先加载”的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值