别盲目信任 AI:我用 AI 部署服务器踩的 3 个大坑

别盲目信任 AI:我用 AI 部署服务器踩的 3 个大坑

上篇文章讲了用 AI 写爬虫很爽,但也提到了 AI 写代码不代表它能帮你搞定一切。这篇分享我用 AI 辅助部署服务器时踩的 3 个大坑——每一个都让我浪费了好几个小时返工。


一、背景:为什么让 AI 辅助部署?

部署服务器的流程并不复杂,但每一步都充满了容易出错的细节:

常规部署流程: 1. 准备云服务器(买机器、选系统) 2. SSH 连接服务器 3. 安装运行环境(Node.js / Python / Nginx) 4. 配置环境变量 5. 部署应用代码 6. 配置 Nginx 反向代理 7. 配置 SSL 证书(HTTPS) 8. 配置防火墙和安全组 9. 测试验证

每一步 AI 都可以帮忙——但也可能帮倒忙。

我的经验是:AI 对第 3-5 步(环境安装、代码部署)基本靠谱,但第 6-8 步(Nginx 配置、SSL、防火墙)是翻车重灾区。


二、第一个坑:Nginx 配置反向代理,AI 给的规则能用,但不全对

场景

我有一个 Vue 前端项目和一个 Node.js API 后端,要部署在同一台服务器上:

域名: api.example.com → 前端访问: / → Nginx 转发到本地 80 端口(Vue 打包产物) → API 访问: /api → Nginx 转发到 3000 端口(Node.js 后端)

我告诉 AI 需求后,它给了我这样的 Nginx 配置:

server { listen 80; server_name api.example.com; location / { root /var/www/myapp/dist; index index.html; } location /api { proxy_pass http://127.0.0.1:3000; } }

看起来没啥问题?但我nginx -s reload之后访问页面就报 404。

AI 没说出来的关键细节

AI 给的 Nginx 配置有三个致命问题:

问题 1:Vue History 模式需要 fallback

# AI 给的(不完整) location / { root /var/www/myapp/dist; index index.html; } # 正确的(加上了 history 模式 fallback) location / { root /var/www/myapp/dist; index index.html; try_files $uri $uri/ /index.html; # ← 这句最关键 }

不加try_files,你刷新任何一个二级页面(比如/dashboard),Nginx 直接返回 404,因为文件系统里根本没有/dashboard这个文件。

问题 2:proxy_pass 路径处理不对

# AI 给的:proxy_pass 后面带了 /api location /api { proxy_pass http://127.0.0.1:3000/api; # ← 注意末尾的 /api } # 问题:当你请求 /api/users 时,Nginx 会转发到 3000/api/api/users # 你的后端收到的是 /api/api/users,当然 404

正确的做法取决于你的后端 API 设计:

# 如果你的后端路由是以 /api 开头的: location /api { proxy_pass http://127.0.0.1:3000/api; # 保留 /api 前缀 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 如果你的后端路由不带 /api 前缀: location /api { proxy_pass http://127.0.0.1:3000; # 去掉 /api 前缀 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }

问题 3:缺少 proxy_set_header

# AI 完全没提: 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;

没有这些 header,你的后端就拿不到用户的真实 IP,日志记录全是你服务器的内网 IP,OAuth 回调域名也对不上。

最终正确的配置

server { listen 80; server_name api.example.com; # 前端静态资源 location / { root /var/www/myapp/dist; index index.html; 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; 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"; } # 限制请求体大小(上传文件用) client_max_body_size 10M; }

这个坑教会我一个教训:Nginx 配置看似简单,但细节很多。AI 能给你框架,但「try_files」和「proxy_set_header」这类容易被忽略的细节必须额外确认。


三、第二个坑:SSL 证书,AI 教你用 Let’s Encrypt 是对的,但脚本顺序全错

场景

我想给站点加上 HTTPS。AI 推荐了 Let’s Encrypt + Certbot,这个选择本身是对的。

但我按 AI 给的步骤操作,遇到了各种问题。

AI 给的步骤

# 1. 安装 Certbotsudoaptupdate&&sudoaptinstallcertbot-y# 2. 申请证书sudocertbot--nginx-dapi.example.com# 3. 自动续期sudocrontab-e# 添加:0 3 * * * certbot renew --quiet

看起来很简洁?但实际上第 2 步在我这台服务器上一直报错

IMPORTANT NOTES: - The following errors were reported by the server: Domain: api.example.com Type: connection Detail: Connection refused

为什么报错?

AI 省略了关键前置条件:

前置条件 1:80 端口必须开放

云服务器(无论是阿里云、腾讯云还是 AWS)都有一个「安全组」的概念。你服务器上的防火墙(ufw/firewalld)只是第一层,云厂商的安全组是第二层。

# 检查本地防火墙sudoufw status# 必须允许 80 和 443sudoufw allow80/tcpsudoufw allow443/tcp# 但这还不够!# 你还得去云控制台 -> 安全组 -> 添加入站规则:# 协议: TCP, 端口: 80, 来源: 0.0.0.0/0# 协议: TCP, 端口: 443, 来源: 0.0.0.0/0

很多人只配了服务器防火墙,忘了配安全组——Certbot 的 HTTP-01 挑战需要从外网访问你的 80 端口,安全组没开就永远过不去。

前置条件 2:域名 A 记录必须正确指向服务器 IP

# DNS 记录应该是: A api.example.com → 1.2.3.4 (你的服务器公网 IP)

DNS 生效后才能验证域名所有权。如果你在本地 hosts 文件上测试,Certbot 是不认的。

前置条件 3:Nginx 必须先跑起来

Certbot 会启动一个临时的 Nginx 配置来处理 HTTP-01 挑战。如果你的主配置里 80 端口已经被占用了(比如你已经配了一个 listen 80 的 server block),可能会冲突。

正确的完整流程

# 1. 确认域名解析已生效digapi.example.com +short# 应该返回你的服务器公网 IP# 2. 开放防火墙sudoufw allow80/tcpsudoufw allow443/tcp# 3. 确认 Nginx 正在运行sudonginx-t&&sudosystemctl restart nginx# 4. 安装 Certbotsudoaptupdatesudoaptinstallcertbot python3-certbot-nginx-y# 5. 申请证书(Certbot 会自动修改 Nginx 配置)sudocertbot--nginx-dapi.example.com# 6. 测试自动续期sudocertbot renew --dry-run# 7. 配置 cron 定时任务(如果第 5 步没自动添加的话)echo"0 3 * * * certbot renew --quiet --post-hook\"systemctl reload nginx\""|sudotee/etc/crontab.d/certbot-renew

还有一个 AI 经常忘的

自动续期后 reload Nginx!证书续期了但 Nginx 还在用旧证书,等于白续。

# 正确的 crontab 条目应该包含 --post-hook03* * * certbot renew--quiet--post-hook"systemctl reload nginx"

教训:AI 给的步骤通常「大致正确」,但云服务器的安全组、DNS 生效时间、Nginx 前置条件这些「坑」,AI 要么没说、要么一笔带过。


四、第三个坑:环境变量,AI 写配置文件时最爱用的「魔法值」

场景

我用 AI 帮我配置一个 Node.js 后端的生产环境。代码里有这几个配置项需要用到环境变量:

// 原始代码(开发环境写法)constDB_HOST='localhost'constDB_PORT=3306constDB_NAME='myapp'constDB_USER='root'constDB_PASS='admin123'constJWT_SECRET='mysecretkey'constREDIS_URL='redis://localhost:6379'

我让 AI 帮我改成生产环境配置。AI 给我的方案:

// AI 给的(直接写死在代码里了)constDB_HOST=process.env.DB_HOST||'production-db.internal'constDB_PORT=process.env.DB_PORT||3306constDB_PASS=process.env.DB_PASS||'Pr0duct10n_DB_P@ss!'

看起来用了环境变量?但注意最后那个默认值——AI 直接把数据库密码硬编码在代码里了。

更大的问题

更危险的是,AI 还会建议你用下面的方式初始化 Docker 容器:

# AI 给的 Dockerfile(错误示范) FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . # ❌ 把环境变量写在 Dockerfile 里! ENV DB_HOST=production-db.internal ENV DB_PASS=Pr0duct10n_DB_P@ss! ENV JWT_SECRET=my-jwt-secret-key EXPOSE 3000 CMD ["node", "server.js"]

这等于把数据库密码写在了镜像层里。任何人只要拉了你的镜像,就能反编译拿到所有密码。

正确的做法

1. 环境变量只通过.env文件或外部注入,绝不写死

// ✅ 正确的写法:所有变量都从环境变量读取,无默认值或安全的默认值constconfig={db:{host:process.env.DB_HOST,// 必须有值,无默认port:parseInt(process.env.DB_PORT||'3306',10),name:process.env.DB_NAME,// 必须有值,无默认user:process.env.DB_USER,// 必须有值,无默认password:process.env.DB_PASS,// 必须有值,无默认},jwt:{secret:process.env.JWT_SECRET,// 必须有值,无默认},redis:{url:process.env.REDIS_URL,// 必须有值,无默认},port:parseInt(process.env.PORT||'3000',10),// 端口可以有默认值};// 启动时校验关键变量constrequiredVars=['DB_HOST','DB_NAME','DB_USER','DB_PASS','JWT_SECRET'];for(constvofrequiredVars){if(!process.env[v]){thrownewError(`Missing required environment variable:${v}`);}}

2. 使用 .env.production 文件(不包含在版本控制中)

# .env.production(加入 .gitignore!)DB_HOST=production-db.internalDB_PORT=3306DB_NAME=myapp_prodDB_USER=db_userDB_PASS=v3ry_Str0ng_P@ssw0rd!JWT_SECRET=a2f8d91e7b3c5a6f4d8e9b0c1a2d3e4f56789abcdefREDIS_URL=redis://redis:6379/0PORT=3000

3. Docker 中通过 docker-compose 或运行时传入

# docker-compose.ymlversion:'3.8'services:app:build:.ports:-"3000:3000"env_file:-.env.production# ← 从这里读环境变量environment:-NODE_ENV=production
# Dockerfile(不要写 ENV) FROM node:18-alpine WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY . . EXPOSE 3000 CMD ["node", "server.js"]

教训:AI 对「安全性」的理解很差。它觉得把默认值写在代码里「方便」,但安全上这是大忌。关键配置(密码、密钥)必须是「没有就不启动」。


五、用 AI 部署服务器时,你必须额外确认的 5 件事

AI 能帮你完成 80% 的工作,但剩下 20% 往往是决定成败的关键。以下是我必须额外确认的事项:

事项AI 通常会你需要确认
Nginxtry_files不提History 模式需要 fallback
SSL 前置条件不提安全组、DNS、端口都得先配好
环境变量注入可能写死密钥绝对不能出现在代码或 Dockerfile
日志轮转不提Nginx 日志不限制大小会撑爆磁盘
进程守护不提挂了谁帮你重启?需要 PM2/systemd

补充:日志轮转

# /etc/logrotate.d/nginx/var/log/nginx/*.log{daily rotate14compress delaycompress notifempty create 0640 www-data adm sharedscripts postrotate[-f/var/run/nginx.pid]&&kill-USR1$(cat/var/run/nginx.pid)endscript}

不加 logrotate,Nginx 的 access.log 和 error.log 会一天天增大,直到磁盘满了服务全挂。

补充:进程守护

# 不要用 pm2 start server.js 就完事了# 要配置 systemd 服务,确保服务器重启后自动拉起sudotee/etc/systemd/system/myapp.service>/dev/null<<EOF [Unit] Description=My App After=network.target [Service] Type=simple User=root WorkingDirectory=/var/www/myapp Environment=NODE_ENV=production ExecStart=/usr/bin/node server.js Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOFsudosystemctl daemon-reloadsudosystemctlenablemyappsudosystemctl start myapp

六、AI 辅助部署的正确姿势

总结出一个工作流:

第 1 步:让 AI 生成基础配置 → Nginx 配置、Dockerfile、部署脚本 第 2 步:逐行审查 AI 的输出 → 有没有硬编码的密码? → 有没有遗漏的反向代理细节? → 有没有忘记的前置条件? 第 3 步:先在本地或测试环境验证 → nginx -t 测试配置 → 用 docker run -d 测试容器 → curl localhost 测试连通 第 4 步:灰度发布到生产 → 先在测试域名的子域名上跑 → 确认没问题再切主域名 第 5 步:配置监控和告警 → 服务器磁盘使用率 → 应用存活状态 → SSL 证书到期时间

核心理念:AI 是执行者,你是审核者。AI 写代码很快,但你得有足够的眼光看出来它写对了还是写错了。


七、写在最后

AI 确实能帮你省下很多部署时间——但前提是你对部署流程本身有足够的理解。

如果你连 Nginx 是什么、反向代理是干嘛的都不清楚,那 AI 给你的任何配置你都看不懂是对是错。这就是最大的风险。

学会用 AI 辅助部署,前提是你自己先要「懂部署」。AI 加速的是实现过程,替代不了理解过程。


下一篇预告

《AI 辅助写作的 10 个常见坑和对应解法》

AI 写文章确实快,但如果你不注意方法,写出来的东西要么太水、要么太 AI、要么根本不能用。这篇总结我踩过的坑和对应的解法。


如果你也有用 AI 部署踩坑的经历,欢迎留言分享。你最离谱的一次翻车是什么?