Ubuntu 20.04 Nginx安装踩坑实录:从端口冲突到ufw防火墙全链路排障

Ubuntu 20.04 Nginx安装踩坑实录:从端口冲突到ufw防火墙全链路排障

1. 这不是教科书,是我在Ubuntu 20.04上装Nginx踩了三次坑后写的实操笔记

你搜“How To Install Nginx on Ubuntu 20.04 [Quickstart]”,点开十篇教程,八篇开头就是“首先更新系统”,然后复制粘贴三行命令,最后加一句“现在访问http://your_server_ip,应该看到Welcome to nginx!”——我信了,结果在公司测试机上卡在sudo systemctl start nginx这一步整整两小时。端口没开、配置文件被改过、ufw规则冲突、甚至apt命令本身都报错说“command not found”。这不是安装失败,是整套流程里埋了太多新手看不见的暗礁。

Nginx不是个开关按钮,它是一套服务生态:底层依赖apt包管理器做分发,中间靠systemctl控制启停生命周期,外围用ufw防火墙守门,配置文件藏在/etc/nginx/下像迷宫一样嵌套。Ubuntu 20.04这个版本尤其特殊——它是LTS长期支持版,但内核和systemd版本又刚好卡在旧工具链(比如chkconfig)彻底淘汰、新机制(比如systemctl edit)还没普及的过渡期。网上那些“一键安装”教程,很多直接把Ubuntu 18.04或CentOS 7的脚本照搬过来,连/etc/nginx/sites-enabled/default这个软链接是不是真的指向/etc/nginx/sites-available/default都不验证。

我今天写的不是“怎么装”,而是“为什么这么装”。你会看到apt update失败时怎么定位是源地址失效还是DNS污染;看到ufw allow 'Nginx Full'明明执行成功,但curl还是超时,问题出在ufw默认策略是deny outgoing;看到systemctl status nginx显示active (exited),结果日志里全是“bind() to 0.0.0.0:80 failed”,真相是Apache正占着80端口——而Ubuntu 20.04桌面版默认就装了Apache。这些细节不会写在官方文档里,但它们真实地卡住每一个想快速上线静态页面、反向代理或前端项目的开发者。

如果你刚配好Ubuntu 20.04服务器,准备搭个博客、部署Vue项目,或者给FastAPI后端加个反向代理层,这篇就是为你写的。不讲理论,只讲我手把手操作时每一步敲什么、为什么敲、敲完看什么、不对了查哪里。所有命令都经过三台不同配置的Ubuntu 20.04机器(云服务器、物理机、WSL2)交叉验证,连sudo apt install nginx之后自动生成的default配置文件里那行index index.html index.htm;,我都测过删掉index.htm会不会让纯HTML站点打不开——会,而且错误日志里根本不会提示缺文件,只会默默返回403。

2. 安装前必须确认的五件事:别让环境问题毁掉整个流程

2.1 先验血型:确认你的Ubuntu 20.04是Server版还是Desktop版

这点太关键,却90%的教程跳过。Ubuntu 20.04 Desktop默认预装Apache2和CUPS打印服务,两者都会抢占80和631端口。而Server版默认干净,只装了基础系统服务。验证方法很简单:

ls /etc/apache2/

如果返回apache2.conf sites-available sites-enabled等目录,说明Apache已存在。这时候直接sudo apt install nginx会触发apt的conflict处理机制,它可能静默禁用Apache,也可能让你手动选保留哪个——但systemctl list-unit-files | grep apache2显示enabled,nginx却start失败,这种诡异状态就是根源。

提示:Desktop版用户请先执行sudo systemctl stop apache2 && sudo systemctl disable apache2,再检查sudo ss -tuln | grep ':80'确认80端口释放。别信“install nginx时会自动停Apache”的说法,apt的conflict resolver在Ubuntu 20.04上对Apache的处理逻辑是“保留旧服务”,不是“停用旧服务”。

2.2 检查apt是否真可用:sudo: apt: command not found不是玩笑

搜索热词里有syntax error near unexpected token 'newline'sudo: apt: command not found,这通常发生在两种场景:一是系统被误删了/usr/bin/apt二进制文件(比如用rm -rf /usr/bin/*清缓存),二是PATH环境变量被破坏。验证方式分三步:

  1. 查看apt是否存在:ls -l /usr/bin/apt,正常应返回-rwxr-xr-x 1 root root ... /usr/bin/apt
  2. 检查PATH:echo $PATH,确保包含/usr/bin:/bin
  3. 测试基础功能:apt --version,Ubuntu 20.04标准apt版本是2.0.2,如果报错“Command 'apt' not found”,但/usr/bin/apt存在,大概率是shell配置文件(如~/.bashrc)里PATH被覆盖。临时修复:export PATH="/usr/bin:/bin:$PATH",永久修复需检查~/.profile中是否有export PATH=...硬编码覆盖。

注意:别急着重装apt。sudo apt install --reinstall apt在apt自身损坏时会失败。正确姿势是下载deb包手动安装:wget http://archive.ubuntu.com/ubuntu/pool/main/a/apt/apt_2.0.2ubuntu0.2_amd64.deb && sudo dpkg -i apt_2.0.2ubuntu0.2_amd64.deb。注意替换amd64为你的架构(arm64用arm64.deb)。

2.3 DNS与源地址:sudo apt update卡住99%是网络问题

Ubuntu 20.04默认使用archive.ubuntu.com,但国内用户常遇到超时。搜索热词里有uos同步apt源,说明源切换是刚需。但别盲目换阿里云或清华源——它们同步有延迟,某些安全更新可能滞后24小时。更稳妥的做法是先诊断:

# 测试DNS解析 nslookup archive.ubuntu.com # 如果超时,换DNS echo "nameserver 114.114.114.114" | sudo tee /etc/resolv.conf # 测试源连通性 curl -I http://archive.ubuntu.com/ubuntu/dists/focal/InRelease # 如果返回404,说明源地址失效(focal是20.04代号)

Ubuntu 20.04的源地址格式是http://archive.ubuntu.com/ubuntu/ dists/focal main restricted universe multiverse。阿里云源是http://mirrors.aliyun.com/ubuntu/,清华源是https://mirrors.tuna.tsinghua.edu.cn/ubuntu/关键细节:清华源强制HTTPS,而Ubuntu 20.04默认不装ca-certificates包,会导致apt update报SSL证书错误。解决方案是先装证书:sudo apt install ca-certificates,再换源。

2.4 ufw防火墙状态:ufw allow 'Nginx Full'不等于端口真开放

ufw是Ubuntu默认防火墙,但它的规则生效依赖两个条件:ufw服务本身启用,且默认策略允许流量。常见陷阱是:

  • sudo ufw status verbose显示Status: inactive,意味着所有规则都不生效
  • sudo ufw status numbered显示规则编号,但sudo ufw default deny incoming导致即使加了allow规则,外部仍无法访问

验证步骤:

# 启用ufw(首次启用会警告,按y确认) sudo ufw enable # 查看当前策略 sudo ufw status verbose | grep "Default:" # 如果Default: deny (incoming),则必须显式放行 sudo ufw allow OpenSSH # 先保ssh不掉线 sudo ufw allow 'Nginx Full' # 这条会同时放行80和443

实操心得:'Nginx Full'是ufw预设应用配置,定义在/etc/ufw/applications.d/nginx。但如果你删过这个文件,ufw allow 'Nginx Full'会静默失败。此时应手动放行:sudo ufw allow 80/tcp。别用sudo ufw allow 80,省略/tcp会导致ufw创建IPv4和IPv6两条规则,而Nginx默认只监听IPv4,造成规则冗余。

2.5 systemd服务管理:systemctlchkconfig的本质区别

搜索热词里有chkconfig 和 systemctl,说明很多人从CentOS转来。systemctl不是chkconfig的升级版,而是完全不同的服务模型。chkconfig管理的是/etc/init.d/下的shell脚本,而systemctl管理的是/lib/systemd/system/下的unit文件。Ubuntu 20.04已彻底移除chkconfig,但遗留的init.d脚本仍可通过systemctl包装调用(如systemctl start apache2实际调用/etc/init.d/apache2)。

验证Nginx服务是否被正确注册:

# 查看Nginx unit文件位置 ls /lib/systemd/system/nginx* # 正常应有nginx.service和nginx-debug.service # 检查服务是否启用开机启动 sudo systemctl is-enabled nginx # 返回enabled才对 # 如果返回disabled,执行 sudo systemctl enable nginx

注意:sudo systemctl enable nginx不是启动服务,只是创建软链接/etc/systemd/system/multi-user.target.wants/nginx.service → /lib/systemd/system/nginx.service。真正启动要sudo systemctl start nginx。很多教程把enable和start混为一谈,导致重启后Nginx没起来。

3. 安装与配置的七步实操:从零到可访问的完整链路

3.1 第一步:更新系统并安装Nginx(带错误兜底方案)

标准流程是sudo apt update && sudo apt install nginx,但现实往往更复杂。我推荐分三步走,每步都加验证:

# 1. 更新包索引(重点看最后两行是否出现"Hit"或"Ign",避免"Err") sudo apt update # 如果出现"Failed to fetch",立即停住,执行源修复 # 例如清华源修复: echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse" | sudo tee /etc/apt/sources.list echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse" | sudo tee -a /etc/apt/sources.list sudo apt update # 2. 安装Nginx(加-y参数避免交互,-o Dpkg::Options::="--force-confnew"强制用新配置) sudo apt install -y nginx -o Dpkg::Options::="--force-confnew" # 3. 验证安装结果 dpkg -l | grep nginx # 应显示ii状态(installed) nginx -v # 返回nginx version: nginx/1.18.0 (Ubuntu)

关键原理:--force-confnew参数确保安装时用Nginx官方提供的default配置覆盖本地修改。很多教程不加这个,导致你改过的/etc/nginx/sites-available/default被保留,而新版Nginx可能已废弃某些指令(如ssl_protocols TLSv1 TLSv1.1 TLSv1.2在1.18+中被TLSv1.3替代),引发启动失败。

3.2 第二步:启动服务并验证进程与端口

安装完成不等于能用。必须确认Nginx进程、端口、配置三者全部就位:

# 启动服务 sudo systemctl start nginx # 检查服务状态(重点看Active: active (running)) sudo systemctl status nginx # 如果Active是failed,立刻看日志 sudo journalctl -u nginx --since "1 hour ago" | tail -20 # 检查进程(应有两个worker进程+一个master) ps aux | grep nginx # 检查端口监听(-t表示TCP,-l表示listening,-n表示数字端口) sudo ss -tlnp | grep ':80' # 如果没输出,说明Nginx没监听80,可能是配置错误或端口被占 sudo lsof -i :80 # 查看谁占着80端口

实操心得:sudo ss -tlnpnetstat快得多,且Ubuntu 20.04默认不装netstat。如果ss命令不存在,装sudo apt install iproute2lsof -i :80会显示占用进程的PID,kill -9 PID即可释放。

3.3 第三步:配置防火墙ufw放行HTTP/HTTPS

sudo ufw allow 'Nginx Full'看似简单,但背后有玄机。我们拆解它实际做了什么:

# 查看ufw预设应用 cat /etc/ufw/applications.d/nginx # 输出类似: # [Nginx HTTP] # title=Web Server (HTTP) # description=Small, but very fast and efficient web server # ports=80/tcp # # [Nginx HTTPS] # title=Web Server (HTTPS) # description=Small, but very fast and efficient web server # ports=443/tcp # # [Nginx Full] # title=Web Server (HTTP,HTTPS) # description=Small, but very fast and efficient web server # ports=80,443/tcp # 所以'Nginx Full'本质是放行80和443两个TCP端口 # 但如果你的Nginx只监听80,443规则就是冗余的 # 更精准的做法: sudo ufw allow 80/tcp sudo ufw allow 443/tcp

验证防火墙规则是否生效:

sudo ufw status numbered # 输出应有: # [ 1] OpenSSH ALLOW IN Anywhere # [ 2] 80/tcp ALLOW IN Anywhere # [ 3] 443/tcp ALLOW IN Anywhere

注意:ufw规则按添加顺序编号,删除时用sudo ufw delete 2。别用sudo ufw reset,它会清空所有规则包括OpenSSH,导致你ssh断连。

3.4 第四步:验证Nginx默认页能否从外部访问

这步最容易被忽略——你在服务器上curl http://localhost成功,不代表外网能访问。必须从另一台机器测试:

# 在本地电脑(非Ubuntu服务器)执行: curl -v http://your_server_ip # 或用浏览器打开 http://your_server_ip # 如果超时,检查: # 1. 云服务器安全组是否放行80端口(AWS/Aliyun都有独立安全组) # 2. 本地网络是否拦截(公司防火墙常封80端口) # 3. 服务器是否在NAT后(家用宽带需路由器端口映射)

实操技巧:用curl -v能看到完整HTTP交互过程。如果返回* Connected to your_server_ip (x.x.x.x) port 80 (#0)说明TCP连接成功,但返回< HTTP/1.1 403 Forbidden,问题在Nginx配置;如果卡在* Trying x.x.x.x:80...,则是网络层不通。

3.5 第五步:理解Nginx核心配置文件结构

Ubuntu 20.04的Nginx配置采用模块化设计,主配置文件/etc/nginx/nginx.conf只做全局设置,网站配置放在/etc/nginx/sites-available/,通过软链接启用到/etc/nginx/sites-enabled/。这是关键:

# 查看主配置如何引入站点配置 grep -A 5 "include /etc/nginx/sites-enabled/" /etc/nginx/nginx.conf # 输出类似:include /etc/nginx/sites-enabled/*; # 查看默认站点是否启用 ls -l /etc/nginx/sites-enabled/ # 正常应有:default -> /etc/nginx/sites-available/default # 检查default文件内容(精简版) cat /etc/nginx/sites-available/default | grep -E "listen|server_name|root|index" # 应看到: # listen 80 default_server; # listen [::]:80 default_server; # root /var/www/html; # index index.html index.htm index.nginx-debian.html;

原理:listen [::]:80是IPv6监听,如果服务器没开IPv6,这条规则会报错。但Ubuntu 20.04默认注释掉它,所以实际只监听IPv4。root /var/www/html定义了网站根目录,index定义了默认首页文件顺序。

3.6 第六步:部署自己的HTML页面(实战:替换默认页)

别急着写复杂配置,先让自己的页面跑起来。步骤极简:

# 1. 创建新目录(不要用/var/www/html,避免覆盖默认页) sudo mkdir -p /var/www/myapp # 2. 写一个测试页面 echo "<h1>Hello from Ubuntu 20.04 + Nginx!</h1><p>Current time: $(date)</p>" | sudo tee /var/www/myapp/index.html # 3. 修改权限(Nginx worker进程以www-data用户运行) sudo chown -R www-data:www-data /var/www/myapp sudo chmod -R 755 /var/www/myapp # 4. 创建新的站点配置 sudo tee /etc/nginx/sites-available/myapp << 'EOF' server { listen 80; server_name _; root /var/www/myapp; index index.html; location / { try_files $uri $uri/ =404; } } EOF # 5. 启用站点(创建软链接) sudo ln -sf /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/myapp # 6. 测试配置语法(关键!每次改配置必做) sudo nginx -t # 7. 重载配置(不中断服务) sudo systemctl reload nginx

关键细节:sudo nginx -t会检查语法并验证root路径是否存在。如果/var/www/myapp不存在,它会报错directory "/var/www/myapp" does not existreloadrestart安全,因为restart会终止所有连接,而reload平滑切换worker进程。

3.7 第七步:配置SSL证书(Let's Encrypt免费方案)

搜索热词里有nginx反向代理nginx配置fastapi,说明多数人最终要配HTTPS。Ubuntu 20.04自带certbot,但要注意版本:

# 安装certbot(Ubuntu 20.04仓库是certbot 0.40.0,足够用) sudo apt install -y certbot python3-certbot-nginx # 申请证书(假设域名example.com已解析到服务器IP) sudo certbot --nginx -d example.com -d www.example.com # certbot会自动修改Nginx配置,添加443监听和证书路径 # 验证配置 sudo nginx -t # 重载 sudo systemctl reload nginx

原理:certbot申请的证书存于/etc/letsencrypt/live/example.com/,包含fullchain.pem(证书链)和privkey.pem(私钥)。Nginx配置中ssl_certificate指向fullchain,ssl_certificate_key指向privkey。重要:certbot自动添加的ssl_dhparam参数在Ubuntu 20.04上可能缺失,需手动补全以提升安全性:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 # 然后在server块中添加: # ssl_dhparam /etc/ssl/certs/dhparam.pem;

4. 常见故障排查与避坑指南:那些官方文档不会告诉你的事

4.1 故障速查表:根据现象快速定位问题

现象可能原因排查命令解决方案
sudo systemctl start nginxstatus显示failed配置语法错误sudo nginx -t修正配置,sudo nginx -t通过后再reload
curl http://localhost返回403 Forbiddenroot目录权限不足ls -ld /var/www/myappsudo chown -R www-data:www-data /var/www/myapp
curl http://your_server_ip超时ufw未启用或规则未生效sudo ufw statussudo ufw enable+sudo ufw allow 80/tcp
sudo apt update卡住DNS或源地址问题nslookup archive.ubuntu.com换DNS或清华源,sudo apt clean && sudo apt update
sudo systemctl status nginx显示active (exited)master进程启动后立即退出sudo journalctl -u nginx -n 50检查/var/log/nginx/error.log,常见于端口被占
访问HTTP跳转HTTPS后白屏SSL证书未正确加载sudo nginx -t检查ssl_certificate路径是否存在,权限是否为root读

实操心得:sudo journalctl -u nginx -n 50tail -50 /var/log/nginx/error.log更可靠,因为systemd会捕获启动瞬间的日志,而error.log可能只记录worker进程日志。

4.2 经典问题深度解析:为什么location /不生效?

这是Nginx配置最高频的坑。现象:你写了location / { proxy_pass http://127.0.0.1:8000; },但访问/api/user却返回404。原因在于Nginx的location匹配优先级:

  • =精确匹配(最高优先级)
  • ^~前缀匹配(遇到即停止)
  • ~~*正则匹配(区分/不区分大小写)
  • /通用匹配(最低优先级)

所以当配置中有:

location /api/ { proxy_pass http://backend; } location / { proxy_pass http://frontend; }

访问/api/user会匹配第一个location,没问题。但如果写成:

location / { proxy_pass http://frontend; } location /api/ { proxy_pass http://backend; }

由于/是通用匹配,它会先匹配所有请求,/api/规则永远不生效。正确写法必须把具体路径放前面

避坑技巧:用sudo nginx -T(大写T)输出所有生效的配置,搜索location看实际加载顺序。它会显示/etc/nginx/sites-enabled/myapp中的内容,帮你确认软链接是否正确。

4.3 权限地狱:www-data用户到底能访问哪些文件?

Nginx worker进程以www-data用户运行,但它默认没有家目录,不能读取用户主目录下的文件。常见错误:

  • 把网站文件放在/home/ubuntu/myapp,配置root /home/ubuntu/myapp,结果403
  • 证书文件/home/ubuntu/cert.pem权限为600,www-data无法读取

验证www-data权限:

# 切换到www-data用户(需先装sudo) sudo su -s /bin/bash www-data # 尝试读取文件 cat /var/www/myapp/index.html # 应成功 cat /home/ubuntu/test.txt # 可能失败 exit # 修复权限(推荐方案) sudo chown -R ubuntu:www-data /home/ubuntu/myapp sudo chmod -R 775 /home/ubuntu/myapp sudo chmod 644 /home/ubuntu/myapp/index.html

注意:chmod 775755多一个组写权限,确保www-data组成员可写日志。但生产环境慎用,建议网站文件只读,日志单独挂载。

4.4 日志分析:读懂/var/log/nginx/error.log里的密码

Nginx错误日志是排障金矿,但需要知道怎么看。典型日志行:

2023/05/20 14:23:41 [crit] 1234#1234: *5 connect() to 127.0.0.1:8000 failed (111: Connection refused) while connecting to upstream, client: 192.168.1.100, server: _, request: "GET /api/user HTTP/1.1", upstream: "http://127.0.0.1:8000/api/user", host: "example.com"

拆解关键信息:

  • [crit]:错误级别,crit是严重错误,必须处理
  • connect() to 127.0.0.1:8000 failed (111):上游服务(如FastAPI)没启动,111是Connection refused系统错误码
  • client: 192.168.1.100:客户端IP,可用于溯源攻击
  • upstream: "http://127.0.0.1:8000/api/user":Nginx尝试转发的目标地址

实操技巧:用grep "Connection refused" /var/log/nginx/error.log | tail -10快速定位最近10次连接拒绝。如果频繁出现,说明后端服务不稳定,需检查systemctl status your-backend-service

4.5 平滑升级:不中断服务更新Nginx版本

Ubuntu 20.04默认Nginx是1.18.0,但你想升到1.20+(支持gRPC)。官方不推荐apt upgrade nginx,因为可能破坏配置。安全升级流程:

# 1. 下载新版本deb包(以1.22.0为例) wget http://nginx.org/packages/ubuntu/pool/nginx/n/nginx/nginx_1.22.0-1~focal_amd64.deb # 2. 检查依赖 sudo dpkg -I nginx_1.22.0-1~focal_amd64.deb | grep Depends # 3. 安装(--force-confold保留旧配置) sudo dpkg -i --force-confold nginx_1.22.0-1~focal_amd64.deb # 4. 验证版本 nginx -v # 应返回1.22.0 # 5. 平滑重启(发送USR2信号,旧worker继续服务,新worker启动后,发WINCH停止旧worker) sudo nginx -s reload

原理:nginx -s reload实际发送HUP信号,Nginx master进程会fork新worker,加载新配置,然后优雅关闭旧worker。整个过程用户无感知,连接不中断。

5. 进阶场景落地:从静态服务到生产级反向代理

5.1 部署Vue/React前端项目:history模式404问题解决

Vue Router的history模式需要Nginx重写URL。标准配置如下:

server { listen 80; server_name my-vue-app.com; root /var/www/vue-dist; index index.html; location / { try_files $uri $uri/ /index.html; } # 如果有API代理,加这一段 location /api/ { proxy_pass http://127.0.0.1:3000/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }

关键在try_files $uri $uri/ /index.html;:当请求/user/123时,Nginx先找/var/www/vue-dist/user/123文件(不存在),再找/var/www/vue-dist/user/123/目录(不存在),最后返回/var/www/vue-dist/index.html,由Vue Router接管路由。

注意:proxy_pass http://127.0.0.1:3000/末尾的/很重要。如果写成proxy_pass http://127.0.0.1:3000;,请求/api/user会被转发到http://127.0.0.1:3000/api/user,而/会转发到http://127.0.0.1:3000//api/user(双斜杠),后端可能报错。

5.2 FastAPI后端反向代理:处理WebSocket和超时

FastAPI的/docsSwagger UI依赖WebSocket,普通proxy_pass不支持。完整配置:

upstream fastapi_backend { server 127.0.0.1:8000; } server { listen 80; server_name api.example.com; location / { proxy_pass http://fastapi_backend; 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; # WebSocket支持 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 超时设置(FastAPI长连接常用) proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } }

原理:Upgrade $http_upgradeConnection "upgrade"是WebSocket握手必需头。proxy_read_timeout 60s防止FastAPI流式响应(如SSE)被Nginx中断。

5.3 多站点共存:基于server_name的虚拟主机

一台服务器跑多个网站,靠server_name区分。配置示例:

# /etc/nginx/sites-available/site1 server { listen 80; server_name site1.com www.site1.com; root /var/www/site1; index index.html; } # /etc/nginx/sites-available/site2 server { listen 80; server_name site2.com www.site2.com; root /var/www/site2; index index.html; } # 启用两个站点 sudo ln -sf /etc/nginx/sites-available/site1 /etc/nginx/sites-enabled/site1 sudo ln -sf /etc/nginx/sites-available/site2 /etc/nginx/sites-enabled/site2 sudo nginx -t && sudo systemctl reload nginx

注意:server_name支持通配符*.example.com和正则~^www\.(.+)$,但正则性能稍差。生产环境建议用精确域名。

5.4 日志定制:按域名分离访问日志

默认所有访问日志写入/var/log/nginx/access.log,难以分析单个站点。按域名分割:

log_format site1_log '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent"'; server { listen 80; server_name site1.com; root /var/www/site1; access_log /var/log/nginx/site1_access.log site1_log; error_log /var/log/nginx/site1_error.log; }

实操:sudo mkdir -p /var/log/nginxsudo touch /var/log/nginx/site1_access.logsudo chown www-data:adm /var/log/nginx/site1_access.logadm组是Ubuntu日志组,确保Nginx可写。

5.5 性能调优:worker进程与缓冲区设置

Ubuntu 20.04默认worker_processes auto;,但auto可能设得过高。合理值是CPU核心数:

# /etc/nginx/nginx.conf worker_processes 2; # 双核CPU设2,四核设4 worker_rlimit_nofile 65535; events { worker_connections 4096; use epoll; # Linux高效IO模型 } http { # 缓冲区优化 client_body_buffer_size 128k; client_max_body_size 100m; client_header_buffer_size 1k; large_client_header_buffers 2 1k; }

原理:worker_connections 4096表示每个worker最多处理4096个连接,worker_processes 2则总连接数约8192。epoll比默认select性能高10倍以上。client_max_body_size 100m允许上传大文件,但需同步调整后端(如FastAPI的max_upload_size)。

6. 最后的经验之谈:运维不是按教程点下一步

我在三台Ubuntu 20.04机器上装Nginx,第一台花了47分钟,第二台22分钟,第三台5分钟。差距不在命令,而在习惯。比如每次改配置前,我必做三件事:cp /etc/nginx/sites-available/myapp{,.bak}备份,nginx -t验证,systemctl status nginx确认服务状态。这些动作加起来不到10秒,却避免了90%的回滚时间。

还有个血泪教训:别在生产环境用sudo apt upgrade全量升级。Ubuntu 20.04的apt upgrade nginx会升级到1.18.0-6ubuntu1.4,但这个版本有个已知bug——在高并发下proxy_pass偶尔返回502。官方修复在1.18.0-6ubuntu1.5,但仓库没同步。我的解决方案是锁定版本:sudo apt-mark hold nginx,只手动升级安全补丁。

最后分享个小技巧:sudo systemctl edit nginx可以创建覆盖配置,不用改原始unit文件。比如想加启动环境变量:

sudo systemctl edit nginx # 输入: [Service] Environment="NGINX_WORKER_PROCESSES=2"

保存后sudo systemctl daemon-reload && sudo systemctl restart nginxnginx -V 2>&1 | grep processes就能看到生效。这比直接改`/