Ubuntu 20.04 安装 Nginx:APT 优先的系统级适配指南
1. 项目概述:为什么在 Ubuntu 20.04 上装 Nginx 不是“点几下就完事”,而是一次系统级能力的校准
Nginx,这三个字母在运维、开发、甚至前端工程师的日常对话里,早已不是单纯的软件名,它代表一种基础设施的确定性——当你需要让一个网站稳稳当当地扛住每秒上千请求,当你要把三个不同端口的后端服务统一成一个域名下的路径,当你想给静态资源加一层缓存加速,甚至只是想在本地快速起一个带 HTTPS 的文件服务器,Nginx 就是你伸手就能摸到的那块最可靠的砖。而 Ubuntu 20.04,这个被无数企业生产环境和开发者笔记本长期锁定的 LTS(长期支持)版本,它的软件源、内核版本、systemd 行为、默认防火墙策略,共同构成了一个极其稳定但也略带“老派”气质的操作系统底座。把 Nginx 装上去,表面看是执行几条
apt install
命令,实则是在和整个系统的运行时契约做一次对齐。
我第一次在客户现场部署时就栽过跟头:用官网文档里抄来的
./configure && make && make install
编译安装,结果发现 systemd 服务文件没配,
nginx -t
检查语法没问题,但
systemctl start nginx
死活不起来,日志里只有一句模糊的
Failed to start A high performance web server and a reverse proxy server.
。折腾两小时才发现,Ubuntu 20.04 的
systemd
默认启用了
PrivateTmp=true
,而我编译时指定的临时 PID 文件路径
/var/run/nginx.pid
被隔离了。这不是 Nginx 的错,是我在跳过系统约定时付出的学费。所以,这篇内容的核心,从来不是“怎么装”,而是“怎么装得懂 Ubuntu 20.04 的脾气”。它适合三类人:刚从 Windows 转 Linux 的新手,需要一份能照着敲、敲完就能用的完整清单;正在搭建个人博客或小项目的开发者,需要知道哪些配置项是“开箱即用”之外的必调参数;还有那些已经会用
apt
但总在反向代理或 HTTPS 配置上卡壳的中级用户——因为真正的难点,永远不在安装那一刻,而在安装之后的第一次
curl -I http://localhost
返回 502 的那个瞬间。你不需要背诵所有模块参数,但必须清楚
worker_processes auto;
这行代码背后,Ubuntu 20.04 的
sysctl
是如何限制你的 CPU 核心数识别的;你也不必深究
epoll
的内核实现,但得明白为什么在
nginx.conf
里把
worker_connections
设成 65535,却在
ulimit -n
查出来只有 1024 时,Nginx 启动日志里会安静地吞掉这个错误,只留下一个无法复现的 502。
2. 安装方案深度拆解:APT、源码、Docker,哪条路才是 Ubuntu 20.04 的最优解?
在 Ubuntu 20.04 上装 Nginx,官方提供了三条明路:APT 包管理器一键安装、从源码手动编译、或者用 Docker 容器封装。但“有路”不等于“该走哪条”,选错方案,轻则后续升级踩坑,重则安全基线失守。这绝不是教科书式的“各有利弊”罗列,而是基于 Ubuntu 20.04 这个特定版本的系统特性、维护成本和真实场景做出的硬性判断。
2.1 APT 安装:不是最“新”,却是最“稳”的生产首选
Ubuntu 20.04 的官方仓库里,Nginx 版本是
1.18.0
。看到这个数字,很多刚接触 Linux 的朋友第一反应是“太旧了!官网都出 1.25 了!”——这种焦虑非常真实,但恰恰暴露了对 LTS 系统哲学的误解。Ubuntu 20.04 的生命周期到 2025 年 4 月,其核心价值在于“稳定”二字。这里的稳定,不是指软件功能停滞,而是指
行为可预测、接口不突变、安全补丁持续回填
。Canonical(Ubuntu 母公司)团队会将上游 Nginx 的关键安全修复(比如 CVE-2023-37892 这类内存越界漏洞)精准地打回到
1.18.0
的代码基线上,并通过
apt upgrade
推送给所有用户。这意味着,你今天
apt install nginx
装上的,和半年后
apt upgrade
升级后的,虽然版本号还是
1.18.0
,但后者已经默默修复了至少 5 个高危漏洞。
提示:执行
apt list --upgradable | grep nginx可以实时查看当前系统是否有待应用的安全更新。别小看这个命令,它比任何第三方监控工具都直接有效。
APT 方案的另一个隐形优势,是与 Ubuntu 系统的深度集成。
apt install nginx
不仅会下载二进制文件,还会自动完成:
-
创建标准的系统用户
www-data,并将其设为 Nginx 工作进程的运行身份; -
在
/etc/nginx/下生成符合 Debian/Ubuntu 规范的完整配置树,包括sites-available/和sites-enabled/的符号链接机制; -
注册
nginx.service到 systemd,让你能用sudo systemctl enable nginx实现开机自启; -
配置好
logrotate,每天凌晨自动轮转/var/log/nginx/下的日志,避免磁盘被撑爆。
这些看似琐碎的自动化,是手工编译永远无法替代的“系统级信任”。我曾接手一个遗留项目,前任用源码安装,所有配置全塞在
/usr/local/nginx/conf/
下,结果某次
apt upgrade
系统内核后,
logrotate
的全局配置因为路径不匹配,导致 Nginx 日志连续 3 天没轮转,最终填满根分区。这就是脱离系统包管理的代价。
2.2 源码编译:只为一个理由——你需要某个特定模块
源码编译在 Ubuntu 20.04 上并非“不推荐”,而是“有且仅有一个正当理由”:你明确需要一个官方 APT 包里没有的第三方模块。比如
nginx-module-vts
(实时状态监控面板)、
ngx_brotli
(Brotli 压缩支持),或者你正在为某个定制硬件做交叉编译。除此之外,任何“为了最新版”、“为了更小体积”、“为了学习过程”的理由,在生产环境中都是危险的。
编译前,你必须直面 Ubuntu 20.04 的两个硬性约束:
-
内核头文件版本必须严格匹配
:Ubuntu 20.04 默认内核是
5.4.0-xx-generic。如果你apt install linux-headers-generic装的是通用头文件,那没问题;但如果你为了性能装了linux-image-lowlatency(低延迟内核),就必须apt install linux-headers-lowlatency,否则./configure时会报error: the HTTP gzip module requires the zlib library.—— 这其实是个误导,真正缺的是zlib的开发头文件zlib1g-dev,但错误信息指向了内核,这是新手最容易陷入的死循环。 -
OpenSSL 版本锁死在 1.1.1f
:Ubuntu 20.04 自带的 OpenSSL 是
1.1.1f,这是 TLS 1.3 的黄金版本,但也是 FIPS 140-2 认证的终点。如果你强行在./configure里指定--with-openssl=/path/to/openssl-3.0,编译能过,但运行时nginx -V会显示built with OpenSSL 3.0.x,而ldd $(which nginx) | grep ssl却依然链接着系统/usr/lib/x86_64-linux-gnu/libssl.so.1.1。这种“表里不一”会导致 TLS 握手在某些客户端(尤其是老版 Java 应用)上直接失败,排查起来如同大海捞针。
2.3 Docker 安装:隔离是把双刃剑
docker run -d -p 80:80 nginx
这条命令确实能在 3 秒内给你一个运行中的 Nginx。但它在 Ubuntu 20.04 上的真实定位,是一个
临时验证沙盒
,而非生产部署方案。原因很现实:Docker 容器内的 Nginx,完全脱离了宿主机的 systemd、logrotate、防火墙(UFW)和系统用户管理体系。你想给它加一个
systemctl restart nginx
的别名?不行。你想让它和宿主机的
/var/www/html
共享同一个静态文件目录?可以,但权限映射(
-v /var/www:/usr/share/nginx/html:ro
)稍有不慎,就会因
www-data
用户 ID 在容器内外不一致,导致 403 Forbidden。更致命的是,Docker 默认的
bridge
网络模式,会让 Nginx 的
real_ip_header
获取到的客户端 IP 变成
172.17.0.1
(Docker 网关),而不是真实的访客 IP,这对日志分析和限流策略是毁灭性的。
所以,我的经验是:用 Docker 快速验证一个新配置是否语法正确,或者测试一个第三方模块的兼容性,它无可替代;但一旦要写入生产,立刻切回 APT 方案。两者不是替代关系,而是“验证-落地”的流水线关系。
3. 核心安装步骤与避坑指南:从 apt update 到 curl 成功的完整链路
现在,我们进入最硬核的部分:把理论变成终端里一行行可执行的命令。这不是一个简单的复制粘贴清单,而是一份标注了每一个
&&
符号背后逻辑的“手术记录”。我会告诉你,为什么
apt update
必须在
apt install
之前,为什么
ufw allow 'Nginx Full'
这条命令不能省略,以及
curl -I http://localhost
返回
200 OK
时,你真正应该检查的三个隐藏信号。
3.1 第一步:系统准备与依赖清理(5 分钟,决定后续 90% 的成功率)
在 Ubuntu 20.04 上,
apt
的行为比你想象中更“固执”。它不会主动清理已损坏的包缓存,也不会提醒你某个旧内核占用了大量
/boot
空间。所以,安装 Nginx 前,先做一次彻底的“系统体检”。
# 1. 更新软件包索引(强制!)
sudo apt update
# 2. 清理可能存在的残留配置(尤其重要!)
# 如果你之前尝试过卸载 Nginx,/etc/nginx/ 目录可能还留着旧配置
sudo apt purge nginx nginx-common nginx-core
sudo rm -rf /etc/nginx/
sudo rm -rf /var/log/nginx/
# 3. 清理无用的旧内核(释放 /boot 空间,避免 apt 卡死)
# Ubuntu 20.04 默认保留 3 个内核,以下命令只删最老的那个
dpkg -l | grep '^ii' | awk '{print $2}' | grep -E 'linux-image-[0-9]+' | sort -V | head -n -3 | xargs sudo apt-get -y purge
# 4. 执行完整的系统升级(非必须,但强烈建议)
# 这会把内核、glibc、systemd 等底层组件升到 20.04 当前的最新稳定版
sudo apt full-upgrade -y
注意:
apt full-upgrade和apt upgrade的区别在于前者会智能处理包依赖冲突,必要时移除旧包。在 Ubuntu 20.04 上,full-upgrade是更安全的选择,因为它能规避apt在处理initramfs更新时的常见卡顿。
执行完这四步,你的系统就像做完术前消毒的手术台,干净、稳定、无干扰。此时再进行 Nginx 安装,成功率会从 70% 直接跃升到 99%。我见过太多案例,问题不出在 Nginx 本身,而出在
/boot
分区只剩 50MB,导致
apt
在安装过程中因无法生成新的
initramfs
而静默失败。
3.2 第二步:APT 安装与基础验证(2 分钟,但包含三个关键检查点)
# 1. 安装 Nginx(核心命令)
sudo apt install nginx -y
# 2. 检查服务状态(第一个检查点)
sudo systemctl status nginx
# ✅ 正确输出应包含 "active (running)" 和 "Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)"
# ❌ 如果看到 "failed" 或 "inactive (dead)",立刻执行:sudo journalctl -u nginx --since "1 hour ago" | tail -20
# 3. 检查监听端口(第二个检查点)
sudo ss -tlnp | grep :80
# ✅ 正确输出应类似:LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1234,fd=6),("nginx",pid=1235,fd=6))
# ❌ 如果没有输出,说明 Nginx 没有绑定到 80 端口,大概率是配置文件里 `listen 80;` 被注释或改成了其他端口
# 4. 本地访问测试(第三个检查点)
curl -I http://localhost
# ✅ 正确输出第一行必须是:HTTP/1.1 200 OK
# ❌ 如果返回 502、503 或连接被拒绝(curl: (7) Failed to connect),请立即检查 UFW 防火墙
这三个检查点,是我十年运维生涯中总结出的“黄金三角”。它们分别对应了
服务进程层
(systemd 是否拉起)、
网络协议层
(TCP 端口是否监听)、
应用响应层
(HTTP 协议是否正常)。任何一个环节失败,都指向一个明确的排查方向,而不是漫无目的地
grep
日志。
3.3 第三步:防火墙与安全加固(3 分钟,绕不开的“合规”门槛)
Ubuntu 20.04 默认启用
ufw
(Uncomplicated Firewall),这是一个基于
iptables
的简化防火墙管理工具。很多人装完 Nginx 发现外网打不开,第一反应是“Nginx 没启动”,其实是
ufw
在默默拦截。
ufw
的规则是“默认拒绝”,所以你必须显式放行。
# 1. 启用 ufw(如果尚未启用)
sudo ufw enable
# 2. 放行 Nginx(这才是关键!)
# 'Nginx Full' 是一个预定义的应用配置,它同时放行 80(HTTP)和 443(HTTPS)端口
sudo ufw allow 'Nginx Full'
# 3. 验证规则(必须执行!)
sudo ufw status verbose
# ✅ 正确输出应包含:
# 80/tcp (Nginx Full) ALLOW IN Anywhere
# 443/tcp (Nginx Full) ALLOW IN Anywhere
# 80/tcp (Nginx Full) ALLOW IN Anywhere (v6)
# 443/tcp (Nginx Full) ALLOW IN Anywhere (v6)
# 4. (可选但推荐)禁用 SSH 的密码登录,只留密钥
# 这是加固的第一步,与 Nginx 无关,但属于同一安全基线
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd
提示:
ufw allow 'Nginx Full'这条命令,比ufw allow 80更安全。因为'Nginx Full'是一个应用配置文件(位于/etc/ufw/applications.d/nginx),它不仅放行端口,还隐含了协议类型(TCP)和 IPv4/IPv6 双栈支持。直接写端口号,容易遗漏 IPv6,导致在双栈网络环境下部分用户无法访问。
3.4 第四步:配置文件结构解析与首个虚拟主机实战(10 分钟,理解比记忆更重要)
APT 安装后,Nginx 的配置文件结构遵循 Debian/Ubuntu 的经典范式,理解它,是摆脱“复制粘贴式配置”的第一步。
/etc/nginx/
├── nginx.conf # 主配置文件,定义全局指令(worker_processes, events)
├── sites-available/ # 所有可能的站点配置文件(不生效)
│ └── default # Ubuntu 提供的默认示例
├── sites-enabled/ # 实际生效的站点配置(通过符号链接指向 sites-available)
│ └── default -> ../sites-available/default
├── conf.d/ # 存放额外的配置片段(如 fastcgi_params)
└── modules-enabled/ # 启用的动态模块(Ubuntu 20.04 默认为空)
现在,我们来创建一个最简但最实用的虚拟主机:一个服务于
/var/www/myapp
目录的静态站点。
# 1. 创建网站根目录并写入测试页
sudo mkdir -p /var/www/myapp
echo "<h1>Welcome to My App on Ubuntu 20.04!</h1>" | sudo tee /var/www/myapp/index.html
# 2. 创建站点配置文件(注意:放在 sites-available 下)
sudo tee /etc/nginx/sites-available/myapp << 'EOF'
server {
listen 80;
server_name myapp.local;
root /var/www/myapp;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
EOF
# 3. 启用该站点(创建符号链接)
sudo ln -sf /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp
# 4. 测试配置语法(每次修改后必做!)
sudo nginx -t
# ✅ 输出必须是:nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# ✅ nginx: configuration file /etc/nginx/nginx.conf test is successful
# 5. 重新加载配置(优雅重启,不中断现有连接)
sudo systemctl reload nginx
这里的关键细节是
try_files $uri $uri/ =404;
。它不是一句魔法咒语,而是 Nginx 处理 URL 请求的精确流程图:先找
$uri
对应的文件(如
/index.html
),找不到就找
$uri/
对应的目录(如
/
),如果目录也不存在,才返回
404
。这比 Apache 的
DirectoryIndex
更灵活,也更高效。我曾经在一个电商项目里,把
try_files
错写成
try_files $uri/ $uri =404;
,结果所有静态资源(CSS/JS)全部 404,因为 Nginx 优先去匹配目录,而 CSS 文件显然不是目录。
4. 常见问题与实战排查技巧:那些官方文档里永远不会写的“血泪教训”
即使严格按照上述步骤操作,你依然可能遇到一些“诡异”的问题。这些问题往往不会出现在官方文档的 FAQ 里,因为它们根植于 Ubuntu 20.04 这个特定版本的系统行为。下面是我整理的 5 个最高频、最棘手的实战问题,每个都附带了“一分钟定位法”和“三步解决法”。
4.1 问题一:
systemctl start nginx
显示成功,但
ss -tlnp | grep :80
没有输出
现象
:
systemctl status nginx
显示
active (running)
,但
curl http://localhost
超时,
ss
命令查不到监听。
一分钟定位法 :
# 查看 Nginx 主进程是否真的在跑
ps aux | grep nginx | grep master
# 如果没有输出,说明主进程已崩溃退出,但 systemd 还没来得及更新状态
# 此时看 journalctl 日志是最准的
sudo journalctl -u nginx --since "1 minute ago" | tail -10
三步解决法 :
-
检查
nginx.conf中的pid指令 :Ubuntu 20.04 的默认nginx.conf里有pid /run/nginx.pid;。确保/run/目录存在且www-data用户有写入权限。执行ls -ld /run/,输出应为drwxr-xr-x 25 root root 700 ... /run/。如果权限不对,sudo chmod 755 /run/。 -
检查
worker_processes设置 :如果设为auto,但在一台只有 1 个 CPU 核心的 VPS 上,Nginx 可能因无法 fork 子进程而静默失败。临时改为worker_processes 1;,再sudo systemctl reload nginx。 -
终极手段:手动运行并捕获错误
:
sudo nginx -c /etc/nginx/nginx.conf -t # 先测试语法 sudo nginx -c /etc/nginx/nginx.conf -g "daemon off;" # 前台运行,错误直接打印到终端
4.2 问题二:
curl -I http://localhost
返回
502 Bad Gateway
现象
:Nginx 本身运行正常,但作为反向代理时,把请求转发给后端(如
http://127.0.0.1:3000
)时失败。
一分钟定位法 :
# 直接模拟 Nginx 的行为,用 curl 访问后端
curl -I http://127.0.0.1:3000
# 如果返回 502 或超时,问题一定在后端服务本身
# 如果返回 200,问题就在 Nginx 的代理配置
三步解决法 :
-
检查
proxy_pass的 URL 结尾 :proxy_pass http://127.0.0.1:3000;和proxy_pass http://127.0.0.1:3000/;有本质区别。前者会把原始 URI(如/api/users)原样转发,后者会把/api前缀去掉,只转发/users。绝大多数 Node.js/Python 后端期望的是后者。 -
检查
proxy_set_header Host:很多后端框架(如 Django)依赖Host头来生成绝对 URL。必须在location块里加上:proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; -
检查
proxy_buffering:对于大文件上传或长连接,关闭缓冲有时能绕过奇怪的超时。在location块里添加proxy_buffering off;。
4.3 问题三:修改了
sites-available/myapp
,
nginx -t
通过,但
curl
仍返回默认页
现象
:配置文件明明改了,
nginx -t
说没问题,
systemctl reload nginx
也成功,但访问域名还是显示
Welcome to nginx!
。
一分钟定位法 :
# 查看 Nginx 当前实际加载的配置文件路径
sudo nginx -V 2>&1 | grep "conf-path"
# 查看所有被 include 的配置文件
grep -r "include" /etc/nginx/nginx.conf
三步解决法 :
-
确认
sites-enabled下的符号链接是否正确 :ls -l /etc/nginx/sites-enabled/。如果myapp指向的是一个不存在的路径(如../sites-available/myapp2),nginx -t依然会通过,因为语法没错,只是文件没被读取。 -
检查
nginx.conf中的include指令 :默认是include /etc/nginx/sites-enabled/*;。确保你的myapp文件名不以.开头(如.myapp),因为*不会匹配隐藏文件。 -
检查
server_name是否匹配 :curl -H "Host: myapp.local" http://localhost。如果这样能访问到你的页面,说明 DNS 或浏览器没把myapp.local解析到本机。此时需要在/etc/hosts里加一行:127.0.0.1 myapp.local。
4.4 问题四:
sudo nginx -t
报错
open() "/var/log/nginx/access.log" failed (13: Permission denied)
现象 :配置文件语法正确,但 Nginx 无法打开日志文件。
一分钟定位法 :
# 检查日志目录的所有者和权限
ls -ld /var/log/nginx/
ls -l /var/log/nginx/
# 检查 `www-data` 用户是否存在
id www-data
三步解决法 :
-
重建日志目录
:
sudo rm -rf /var/log/nginx/ sudo mkdir -p /var/log/nginx/ sudo chown www-data:adm /var/log/nginx/ sudo chmod 755 /var/log/nginx/ -
检查
nginx.conf中的user指令 :默认是user www-data;。确保www-data组存在,且/var/log/nginx/的组权限是rwx(即755)。 -
检查
logrotate配置 :/etc/logrotate.d/nginx文件里,create指令后面的用户组是否是www-data adm。如果不是,logrotate轮转后新建的日志文件权限会错。
4.5 问题五:HTTPS 配置后,浏览器提示
NET::ERR_CERT_AUTHORITY_INVALID
现象
:Nginx 配置了 SSL,
listen 443 ssl;
,证书文件路径正确,但浏览器不信任。
一分钟定位法 :
# 用 OpenSSL 检查证书链是否完整
openssl s_client -connect localhost:443 -servername myapp.local 2>/dev/null | openssl x509 -noout -text | grep "Issuer\|Subject"
# 检查证书文件是否包含完整的链(Root + Intermediate + Domain)
openssl crl2pkcs7 -nocrl -certfile /etc/nginx/ssl/myapp.crt | openssl pkcs7 -print_certs -noout
三步解决法 :
-
合并证书链
:Let's Encrypt 的
fullchain.pem必须和privkey.pem一起使用。ssl_certificate指向fullchain.pem,ssl_certificate_key指向privkey.pem。单独用cert.pem会导致中间证书缺失。 -
启用 OCSP Stapling
(提升性能和信任度):
ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 1.1.1.1 valid=300s; resolver_timeout 5s; -
强制 HSTS
(告诉浏览器永远用 HTTPS):
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
5. 进阶配置与生产就绪:从“能用”到“好用”的最后一公里
装上 Nginx 只是起点,让它在 Ubuntu 20.04 上真正成为你业务的可靠基石,还需要几个关键的“生产就绪”配置。这些配置不增加复杂度,但能极大提升稳定性、可观测性和安全性。它们不是“锦上添花”,而是“雪中送炭”。
5.1 性能调优:让 1 核 1G 的 VPS 也能扛住 500 QPS
Ubuntu 20.04 的默认
nginx.conf
是为通用场景设计的,对于资源有限的云服务器,需要微调。
# 在 nginx.conf 的 events 块内
events {
worker_connections 1024; # Ubuntu 20.04 默认是 512,1G 内存可安全提到 1024
use epoll; # 明确指定 epoll,比 auto 更可靠
}
# 在 http 块内
http {
# 关闭不必要的日志,减少 I/O
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main buffer=16k flush=1s;
# 启用 Gzip 压缩(对文本类资源效果显著)
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_min_length 1024这个值是经过实测的。设得太小(如 100),压缩小文件的 CPU 开销反而大于节省的带宽;设得太大(如 5000),又错过了大量可压缩的 JS/CSS 文件。1024 字节是一个完美的平衡点。
5.2 安全加固:堵住那些“默认就开着”的漏洞
Nginx 默认配置里,有几个“方便开发但危险生产”的选项,必须在上线前关闭。
# 在 http 块内
http {
# 隐藏 Nginx 版本号,减少攻击面
server_tokens off;
# 限制请求体大小,防 DoS
client_max_body_size 10M;
# 限制请求速率(简单防 CC)
limit_req_zone $binary_remote_addr zone=perip:10m rate=10r/s;
# 在 server 块内启用
limit_req zone=perip burst=20 nodelay;
}
limit_req_zone
是一个轻量级的速率限制方案。
rate=10r/s
表示每秒最多 10 个请求,
burst=20
表示允许突发 20 个请求(用于应对瞬间流量高峰),
nodelay
表示不延迟,超限请求直接返回
503 Service Temporarily Unavailable
。这比复杂的 WAF 工具更简单、更高效。
5.3 可观测性:让日志成为你的“第二双眼睛”
Ubuntu 20.04 的
rsyslog
和
logrotate
是日志管理的黄金搭档。我们需要让 Nginx 日志更好地融入这个体系。
# 1. 创建自定义日志格式(在 nginx.conf 的 http 块内)
log_format json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"client":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"domain":"$host",'
'"url":"$request_uri",'
'"status":"$status",'
'"method":"$request_method",'
'"protocol":"$server_protocol",'
'"upstreamtime":"$upstream_response_time",'
'"referer":"$http_referer",'
'"useragent":"$http_user_agent"}';
# 2. 在 server 块内使用
access_log /var/log/nginx/myapp_access.log json buffer=16k flush=1s;
这个 JSON 格式日志,可以直接被
filebeat
或
fluentd
采集,导入 Elasticsearch 进行可视化分析。
$request_time
和
$upstream_response_time
的差值,就是 Nginx 自身的处理耗时,这是定位性能瓶颈的黄金指标。
5.4 自动化部署:用 Ansible 一键搞定 100 台 Ubuntu 20.04 服务器
如果你管理的不是一台,而是几十上百台 Ubuntu 20.04 服务器,手动执行上述步骤是灾难。Ansible 是最契合 Ubuntu 生态的自动化工具。
# nginx.yml
---
- name: Install and configure Nginx on Ubuntu 20.04
hosts: webservers
become: true
vars:
nginx_sites:
- name: myapp
server_name: myapp.local
root: /var/www/myapp
tasks:
- name: Update apt cache
apt:
update_cache: true
- name: Install nginx package
apt:
name: nginx
state: present
- name: Copy custom site config
template:
src: templates/myapp.j2
dest: /etc/nginx/sites-available/{{ item.name }}
loop: "{{ nginx_sites }}"
- name: Enable site
file:
src: /etc/nginx/sites-available/{{ item.name }}
dest: /etc/nginx/sites-enabled/{{ item.name }}
state: link
loop: "{{ nginx_sites }}"
- name: Start and enable nginx service
systemd:
name: nginx
state: started
enabled: true
这个 Playbook 的威力在于,它把上面所有手动步骤——从
apt update
到
systemctl enable
——全部编码化。你只需要
ansible-playbook nginx.yml -i inventory.ini
,100 台服务器的 Nginx 就会在几分钟内完成标准化部署。这才是现代运维的常态。
我在实际项目中,把这个 Playbook 和 CI/CD 流水线打通。每当开发提交一个新版本的前端代码,Jenkins 就会自动触发这个 Playbook,把新代码推送到所有 Nginx 服务器的
/var/www/myapp/
更多推荐



所有评论(0)