本地开发完一个网站,兴致勃勃准备上线,结果在云服务器上折腾一下午,不是缺依赖就是端口不通,最后发现是防火墙没放行——这种经历我猜干过的人都懂。我自己折腾过好几次,踩坑踩到怀疑人生之后,慢慢总结出一套比较顺的流程。这阵子一直在用 Claude Code 和 Kimi 这类 AI 编程助手来辅助日常的开发部署工作,确实省了不少事,今天就拿我自己的一次真实经历,把“用 Claude Code 和 Kimi,把本地网站部署到阿里云服务器”这件事从头到尾捋一遍。
这篇文章适合谁看?如果你手头有一个本地已经跑起来的网站(不管是静态博客、Vue/React 打包后的前端项目,还是带后端的 Node/Python 应用),想把它放到阿里云 ECS 上让公网能访问,但又不确定具体步骤和容易出问题的地方,那这篇文章就是给你写的。我会把我实际操作中的命令、配置、排查思路,以及哪些地方可以放心甩给 AI 工具、哪些地方必须自己把关,全部讲清楚。
1. 为什么本地跑得好好的网站,一上服务器就各种报错
先别急着敲命令,我见过太多人(包括曾经的我自己)上来就装环境、传代码,结果被一堆莫名其妙的报错淹没。这里面的核心原因,其实是“本地环境”和“服务器环境”之间的差异。
1.1 环境差异:这是最容易被忽略的隐形杀手
本地开发的时候,你的电脑上大概率已经装了一堆东西:Node.js 版本可能是 18 或 20,Python 可能是 3.10,MySQL 可能是 8.0 还顺手装了 Homebrew 帮你管理好了一切依赖。但阿里云上新开的 ECS 是一台“干净得像白纸”的服务器,里面除了系统自带的东西可能什么都没有。
举几个我真实遇到过的例子:
- 本地 Node 版本是 20,服务器上默认的 Node 是 10,代码里用了
?.可选链和fetchAPI,结果一启动直接语法报错。 - 本地用的 SQLite 文件数据库,复制到服务器后权限是 root 所有,导致运行用户(比如
www-data)根本没有读写权限,网站能打开首页但一提交表单就 500。 - 本地测试时用的端口是 3000,浏览器里直接
localhost:3000访问,根本没想过服务器上需要让 80/443 端口对外开放,也不知道需要配 Nginx 反向代理。
这些问题的本质,都是“本地能跑”不等于“环境一致”。所以部署的第一步,不是急着上传代码,而是先在服务器上把运行环境“对齐”到和本地一致。
1.2 部署不是复制粘贴,它是一套完整流程
很多人以为部署就是“把文件夹传到服务器上”。这句话只对了一半。对于纯静态网站(全是 HTML/CSS/JS 文件),确实可以简单用 Nginx 指向目录就行。但只要项目里有后端服务、数据库、定时任务、环境变量,事情就变成了下面这套流程:
- 服务器环境准备(系统更新、安装运行时)
- 代码传输(git clone 或者 scp/rsync 上传)
- 依赖安装(npm install / pip install / composer install)
- 配置环境变量(数据库连接、密钥、运行端口)
- 启动服务(并确保进程守护,比如 systemd、pm2)
- 配置反向代理(Nginx 将域名/端口转发到本地服务端口)
- 防火墙与安全组放行
- 测试与验证
每一步都有各自的“坑”,但也正因为这套流程相对固定,非常适合让 Claude Code 和 Kimi 这类工具来辅助生成命令、检查配置、解释报错。
1.3 我的建议:先定位项目类型,再决定部署方案
在动手之前,花两分钟搞清楚你的网站属于哪一类型,部署策略完全不同:
| 项目类型 | 典型技术栈 | 部署策略 |
|---|---|---|
| 纯静态站点 | HTML/CSS/JS、Hexo、Vue/React 打包后的静态文件 | 直接 Nginx 指向目录,最简单 |
| 前端 + 后端分离 | Vue/React + Node/Java/Python API | 前端静态部署 + 后端 API 进程守护 + 反向代理 |
| 单体后端应用 | Express/Koa/Django/Flask/Spring Boot | 需要运行时环境 + 进程守护 + 反向代理 |
| 需要数据库的应用 | MySQL/PostgreSQL/Redis | 还要安装数据库,配置远程连接或本地连接 |
我当时要部署的,是一个前后端分离的小项目:前端是 Vue 打包出来的静态文件,后端是一个 Node.js 写的 API 服务,数据库用的 SQLite。整体不算复杂,但恰好每一类需求都沾一点,用来举例子再合适不过。
2. 开工前的两张清单:服务器选型与本地环境检查
部署这件事,“预则立,不预则废”这句话真是至理名言。在我开始实际操作之前,先把两件事敲定了:服务器买多大的、本地的代码和环境到底什么状态。
2.1 服务器选型的几个判断维度
阿里云的 ECS(弹性云服务器)选择很灵活,对于个人网站和小型项目来说,选错了配置就是浪费钱,选低了又容易卡。我个人总结的判断维度如下:
第一是地域。国内访问就选华北、华东这些区域,离你的目标用户越近越好。我当时选的是华东一(杭州),因为主要用户在国内,而且阿里云默认配的域名备案流程也和服务器地域关联,后面如果要绑域名,地域选错会比较麻烦。
第二是规格。个人网站、博客、小型 API 服务,2核2G 一般够用,跑 Node 或者 Python 服务加一个 Nginx 完全没问题。如果你的应用比较吃内存(比如 Java 系、跑 Docker 容器比较多的),就上 4G。不过说实话,初期 2核2G 或 2核4G 是性价比比较高的区间,真扛不住了再升级也不迟。
第三是操作系统。我强烈建议选 Ubuntu Server。为什么?因为社区资料最多,遇到问题百度/搜索引擎一搜一大把,而且 Claude Code 和 Kimi 对 Ubuntu 的命令掌握最扎实,生成的命令基本不会出错。相比之下,CentOS 虽然经典,但阿里云上很多新用户的系统镜像已经不默认提供 CentOS 8 了,还得处理换源的问题,没必要给新手增加负担。我这次选的就是 Ubuntu 22.04。
第四是带宽。个人网站 3Mbps 起步就够,等访问量真的大了再临时升级带宽。这里有个小常识:云服务器的计费模式是“按固定带宽”和“按使用流量”两种,个人项目我建议按固定带宽,省钱且心理踏实。
2.2 本地环境检查:把家底盘清楚再出门
在碰服务器之前,先在本地把下面这些信息整理好:
- 项目用什么语言和框架,有哪些关键依赖(看 package.json / requirements.txt / pom.xml)
- 本地开发时用的端口号(来源端口)
- 域名有没有,如果有,DNS 解析是否已经指向云服务器公网 IP(没有域名也可以先用 IP 访问)
- 服务器上需要放哪些文件,代码应该用 Git 管理还是直接压缩上传
我自己的习惯是,先把本地项目跑一遍,确认功能正常,然后把依赖清单和启动命令记录下来。比如我这个项目,启动命令是npm start,监听 3000 端口,数据库文件在data/sqlite.db。知道了这些关键信息,后面不管是自己配置还是让 AI 工具生成部署方案,效率都会高很多,也可以避免反复沟通中产生歧义。
2.3 本地安装并准备好 Claude Code 和 Kimi 的工作环境
既然这篇文章的主角是 Claude Code 和 Kimi,这里就多说一句这俩工具在我的工作流里扮演什么角色。
Claude Code 是 Anthropic 出的一个命令行编程助手,可以直接在终端里调用,它能读项目文件、执行命令、解释报错信息,也能根据你的要求生成修改文件。和直接通过网页聊天相比,在服务器部署这种场景下最大的好处是:你可以在本地项目里直接问它“帮我生成一份部署到 Ubuntu 的步骤清单”,它会结合你的项目文件内容给出更贴合实际的指令,而不是泛泛而谈。
Kimi 的话,我也用来做部署方案的讨论和二次确认。遇到拿不准的命令,或者想快速了解某个服务配置的模板写法,用 Kimi 查一下效率很高。Claude Code 和 Kimi 各有特点,实操中我的用法是:Claude Code 帮我干执行层面的活(读文件、写文件、跑命令),Kimi 帮我干答疑和方案梳理层面的活。两个搭配着来,效果最好。
这里顺便把一个常见误解澄清一下:AI 编程助手不是帮你“一键部署”的魔法棒,它们不能替你点击阿里云控制台,也不能替你在服务器上执行命令(除非你在服务器上配置并运行它)。它们真正擅长的是:生成命令、解释报错、帮你设计 Nginx 配置、写 systemd 服务文件。理解这一点,你就不会对它们有错误期待,用起来反而更顺手。
2.4 用 AI 快速生成部署草案
这一步我在实际操作中觉得特别值。不用一上来就在网页搜索框里大海捞针找教程,而是把本地项目的基本信息整理好,直接问 Kimi 或 Claude Code:
“我有一个 Vue 前端项目,打包产物是 dist 目录;还有一个 Node.js 后端,使用 Express,端口 3000,数据库用 SQLite。想部署到阿里云 Ubuntu 22.04 ECS 上,没有域名,打算用 IP 访问。请给出完整部署步骤和关键命令。”
两个工具都能给出比较完整的回答,Kimi 的回答比较条理清晰,Claude Code 则更偏向在项目目录上下文里给你具体建议。我会把回答里的关键步骤保存下来,对照我自己的经验,把不靠谱的地方筛选掉,再动手执行。这一步看似浪费时间,其实能避免很多“做了一半才发现方案不对”的情况。
3. 服务器初始化:从控制台开始的关键配置
买了 ECS 之后,很多人的第一反应是“赶紧 SSH 连上去敲命令”。别急,控制台里还有几个地方必须提前设置好,不然后面会到处碰壁。
3.1 安全组放行端口:最容易忽略的第一步
阿里云 ECS 默认的安全组策略是只放行 22 端口(SSH)和 3389 端口(Windows 远程桌面),80 和 443 默认是不通的。就算你在服务器里装好了 Nginx,公网照样访问不了。
我之前就有过一次非常丢人的经历:Nginx 装好了,配置文件也检查了三遍没问题,本地 curl localhost 有响应,但手机浏览器一打开就是超时。后来才想起来,压根没去配安全组。所以这里要郑重提醒:服务器系统的防火墙(比如 ufw)要放行,阿里云控制台的安全组也要放行,两边都要配置,缺一不可。
操作路径:阿里云控制台 -> ECS 实例 -> 安全组 -> 配置规则 -> 入方向 -> 手动添加。
我一般这样配:
| 协议类型 | 端口范围 | 授权对象 | 说明 |
|---|---|---|---|
| TCP | 80 | 0.0.0.0/0 | HTTP 访问 |
| TCP | 443 | 0.0.0.0/0 | HTTPS 访问(如果后面配证书) |
| TCP | 22 | 你家的公网 IP/32 | SSH 管理(限制来源更安全) |
这里有个小心得:22 端口如果完全不限制来源,服务器容易被各种扫描工具盯上。虽然设置了强密码或密钥后风险可控,但能做到最小授权就尽量最小授权。
3.2 SSH 连接到服务器,用密钥登录而不是密码
拿到服务器公网 IP 之后,我是用终端(macOS/Linux 自带 Terminal,Windows 用 PowerShell 或 Windows Terminal)直接 SSH 连接的。
如果你还没配置过 SSH 密钥,我建议趁这次部署一次性搞定。阿里云控制台创建实例的时候,可以选择“密钥对”方式;如果当时选了密码,也可以登录后自己配置密钥。原因很简单:密码登录容易被暴力破解,而且每次连接都要敲密码,配合 AI 工具执行命令时也比较麻烦。
在我这次部署过程中,Claude Code 生成的命令会频繁要求连接服务器,虽然也可以在我的 Mac 终端里先把命令拷贝过来执行,但用密钥登录验证后,整个步骤会舒服很多。配置完密钥后,SSH 连接就变成一行命令:
ssh ubuntu@你的服务器公网IP如果是 root 用户登录,阿里云的 Ubuntu 镜像默认禁用了 root 远程登录,需要用 ubuntu 用户登录。我建议就用这个 ubuntu 用户,命令前面加sudo来执行需要权限的操作。
3.3 系统基础配置:更新、换时区、装常用工具
第一次登录服务器后,我习惯先跑一套“初始化三连”:
sudo apt update && sudo apt upgrade -y sudo timedatectl set-timezone Asia/Shanghai sudo apt install -y curl git unzip vim更新系统包是为了解决软件源里的安全漏洞,换时区是为了让日志里的时间和你本地一致,不然排查问题的时候看着 UTC 时间能把你绕晕。这步做完,服务器的基础状态就算准备好了。
4. 环境安装的取舍:让 AI 给命令,但决定权在自己
接下来是安装运行时环境。我这个项目需要 Node.js,而服务器默认的 apt 源里的 Node 版本往往偏低,所以我选择用 nvm(Node Version Manager)来安装指定版本的 Node。
4.1 为什么用 nvm 而不是直接 apt install nodejs
直接sudo apt install nodejs虽然省事,但默认版本可能和你本地开发用的版本不一致;而用 nvm 的好处是:
- 可以在用户级别自由切换 Node 版本,不需要全局权限
- 版本升级、回退都很方便
- 避免“本地用一个版本,服务器用另一个版本”这种环境不一致问题
安装 nvm 的官方命令是:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash装完后执行source ~/.bashrc激活,然后就可以安装了:
nvm install 20 nvm use 20 node -v这些事情我自己做也可以,但现在有了 Claude Code 和 Kimi,我会把“安装 Node.js 20”这个需求抛给它们,让它们给我生成详细的命令。不过这里我要强调一个原则:AI 给的命令,每次都要自己先看一眼再执行。毕竟服务器上跑的是你的真实业务,不是测试环境。
4.2 用 AI 生成部署步骤,而不是盲目照搬教程
这里分享一个我平时用的比较多的提示词,把本地项目的信息说清楚,然后要求它输出“部署步骤清单”:
“我在本地有一个项目,技术栈是:Vue 3 + Vite,build 后生成 dist 目录;后端是 Node.js + Express,端口 3000,使用 SQLite 数据库。需要部署到阿里云 Ubuntu 22.04 服务器,用 Nginx 做静态文件托管和 API 反向代理,没有域名,使用 IP 访问。请输出完整部署步骤,包括:1. 服务器环境准备;2. 前端构建与上传;3. 后端依赖安装与启动;4. Nginx 配置;5. 测试验证。每个步骤给出具体命令。”
Claude Code 和 Kimi 都能给出不错的回答。我通常会把回答当作“参考答案”,再结合我对项目的理解进行调整。比如 AI 可能会默认用npm run build,但如果你本地项目里有特殊的构建参数,就需要自己注意同步过来。
4.3 代码上传:用 Git 最省心,scp 应急也行
代码传到服务器上有两种主流方式:Git 和 scp/rsync。
- 有 Git 仓库的项目,直接到服务器上
git clone或git pull,好处是以后更新代码特别方便,一条命令搞定。 - 没有用 Git 管理的项目,可以用
scp -r或rsync把整个目录传到服务器。
我当时这个项目是有 Git 仓库的,所以流程很清晰:
# 在本地把代码推到远程仓库(GitHub/Gitee/云效都行) git add . git commit -m "prepare for deployment" git push origin main # 在服务器上拉取代码 cd ~/projects git clone 你的仓库地址.git my-site这里有个新手容易踩的坑:不要把 Google Drive/百度网盘这些网盘上的压缩包下载到服务器上解压作为部署方式,不仅速度慢,而且解压后的文件权限经常有问题。Git 是最好的方式。
5. Nginx 站点配置:静态文件托管与反向代理一次讲明白
Nginx 是个轻量级但功能强大的 Web 服务器,个人项目部署几乎都绕不开它。静态文件托管和反向代理这两个核心场景,搞明白一个 Nginx 配置文件就够了。
5.1 安装 Nginx 并启动
sudo apt install nginx -y sudo systemctl start nginx sudo systemctl enable nginxenable是设置开机自启,千万别漏。跑完这两条命令后,浏览器直接访问服务器 IP,如果能看到 Nginx 的欢迎页,说明 Nginx 本身工作正常。
5.2 静态文件托管配置:把 Vue 的 dist 目录交给 Nginx
前端项目构建后,生成的其实是纯静态文件:
cd ~/projects/my-site npm install npm run build构建成功后会生成dist目录。接下来要配置 Nginx,让它把这个目录作为网站根目录。
Nginx 的站点配置文件一般放在/etc/nginx/sites-available/下,启用则在/etc/nginx/sites-enabled/下创建一个软链接。Ubuntu 上的默认配置会在/etc/nginx/sites-enabled/default里有内容,我一般会为每个站点单独建一个配置文件,这样逻辑清晰,也方便后续维护。
新建配置文件/etc/nginx/sites-available/my-site:
server { listen 80; server_name _; root /home/ubuntu/projects/my-site/dist; index index.html; location / { try_files $uri $uri/ /index.html; } }这里最关键的其实是try_files $uri $uri/ /index.html;这一行。它的作用是:当用户访问一个前端路由(比如/about)时,Nginx 先去查看有没有对应的静态文件,没有的话就回退到index.html,交给前端路由去处理。如果你部署的是 Vue/React 这类单页应用,没有这行配置,刷新子页面的时候就会 404。
检查配置是否正确,然后重新加载:
sudo nginx -t sudo systemctl reload nginx这一步搞定后,你的前端页面已经可以通过http://服务器IP访问了。
5.3 反向代理配置:把 API 请求转发到 Node 服务
光有前端页面不够,后端 API 服务也要能被公网访问到。通常我不会直接暴露 Node 监听的 3000 端口(一方面是端口显得乱,另一方面是想利用 Nginx 代理的灵活性和日志能力),而是通过 Nginx 把/api路径的请求转发给本地的 3000 端口。
在同一个 Nginx 配置文件里加一个 location 块:
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; }这里要注意proxy_pass http://127.0.0.1:3000/;结尾的斜杠。有斜杠表示把/api前缀去掉了再转发,比如请求/api/users,转发到后端时变成/users;没有斜杠则保留完整路径/api/users。到底用哪种,取决于你后端的路由设计。
改完配置后同样执行:
sudo nginx -t sudo systemctl reload nginx5.4 结合 AI 工具快速排查 Nginx 配置问题
Nginx 配置写错是家常便饭,这时候我会把报错信息直接丢给 Claude Code 或者 Kimi。有一次我的代理配置导致页面能打开但接口 404,我把 Nginx 配置和 Node 服务的路由代码一起给了 Claude Code,它很快就指出是proxy_pass的斜杠问题。这种“多文件上下文关联分析”的能力,比在搜索框里复制粘贴报错要高效得多。
当然,你也可以把sudo nginx -t的输出拿给 Kimi 看,它能不能准确报出第几行有问题,帮我快速定位。
6. 后端服务守护:让 Node 进程持续稳定运行
后端服务部署完成、手动node server.js能跑起来之后,还有一个很重要的问题:关掉 SSH 终端,服务会不会也停掉?
会。原因很简单:直接在终端里启动的进程,是当前 SSH 会话的子进程,会话一断开,进程就会被系统杀掉。所以我们需要一个进程守护工具。
6.1 用 pm2 还是 systemd?我的选择与理由
对于 Node.js 项目,社区最常用的守护方案是 pm2,我这次也用的是 pm2。它的优势是:
- 使用门槛低,几行命令搞定
- 自带日志查看、进程监控、重启策略
- 如果项目是 Python/Java 等其他语言,pm2 也能用,但更“原生”的选择是 systemd
当然,不依赖 pm2 直接配置 systemd 服务文件也可以,我有段时间特意用 systemd,因为系统自带、不吃额外资源。但对个人项目来说,pm2 确实更省心。如果你愿意,也可以问 Kimi 或者 Claude Code 要一份 systemd 服务文件模板,我自己的经验是写成下面这样(仅供参考):
[Unit] Description=My Node.js App After=network.target [Service] ExecStart=/home/ubuntu/.nvm/versions/node/v20.x.x/bin/node /home/ubuntu/projects/my-site/server.js Restart=always User=ubuntu Environment=NODE_ENV=production [Install] WantedBy=multi-user.target不过这次我还是用 pm2 演示,因为它对新手更友好、日志更直观。
6.2 pm2 安装与使用要点
安装 pm2 全局工具:
npm install -g pm2在项目目录里启动服务:
cd ~/projects/my-site NODE_ENV=production pm2 start server.js --name my-api pm2 save pm2 startup这里有两个关键命令:
pm2 save保存当前进程列表,让 pm2 重启后能恢复pm2 startup生成开机自启脚本,确保服务器重启后 pm2 自动启动并拉起服务
用 pm2 之后,查看日志很方便:
pm2 logs my-api服务崩了怎么办?pm2 默认会自动重启,比裸跑命令要稳得多。
6.3 环境变量的迁移与保护
之前本地开发时,项目里可能写了一些环境变量(数据库地址、密钥等)。部署到生产环境时,这些不应该直接硬编码在代码里。我这里用 SQLite 相对简单,不需要配置远程数据库账号,但如果是 MySQL/PostgreSQL,就需要在服务器上创建数据库和账号,并把连接串配置到环境变量里。
pm2 支持通过 ecosystem 配置文件管理环境变量。我一般会创建一个ecosystem.config.js:
module.exports = { apps: [ { name: 'my-api', script: 'server.js', env: { NODE_ENV: 'production', PORT: 3000, DATABASE_PATH: '/home/ubuntu/projects/my-site/data/sqlite.db' } } ] };然后用pm2 start ecosystem.config.js启动。这里务必注意:包含敏感信息的配置文件不要提交到 Git 仓库里,可以放在服务器本地,用.gitignore忽略掉。
7. 部署时的常见坑与完整排查思路
这一节我把自己在部署过程中踩过、或者指导别人时看到的典型坑整理出来,并且展示完整的排查链路,而不是直接甩答案。
7.1 现象:网站打不开,Nginx 却显示“Welcome to nginx”
很多人刚配完安全组、装好 Nginx,打开浏览器发现看到的是 Nginx 默认欢迎页,而不是自己的网站。这时候说明 Nginx 在运行,但它的默认配置优先级更高,或者你没有把站点配置文件启用。
排查链路:
- 执行
ls -l /etc/nginx/sites-enabled/,看看是不是有一个default软链接指向默认配置。如果有,而且和你的站点配置冲突,需要先删掉默认软链接:sudo rm /etc/nginx/sites-enabled/default - 确认你的站点配置文件已经链接到 sites-enabled:
sudo ln -s /etc/nginx/sites-available/my-site /etc/nginx/sites-enabled/my-site - 重新加载 Nginx,再刷新浏览器。
7.2 现象:刷新前端子页面出现 404
前端单页应用配置完成后,如果location /里没有try_files $uri $uri/ /index.html;,直接访问http://IP/about会得到 404。这个问题我前面已经讲到了,这里再补一句:如果你把配置给 Claude Code 看,它还会提醒你检查是否把前端路由模式(history 还是 hash)考虑进去。我一直用的是 history 模式,所以必须加try_files。
7.3 现象:API 接口返回 502 Bad Gateway
502 表示 Nginx 作为反向代理时,连接不到后端服务。后端服务没启动、端口不对、进程挂了是最常见的原因。
排查链路:
- 先看后端进程是否在跑:
如果列表里没有 my-api 或者状态为 errored,先看日志:pm2 listpm2 logs my-api - 在服务器上本地测试后端服务是否通:
如果本地 curl 有响应,说明后端正常,问题出在 Nginx 代理配置;如果本地也没响应,说明后端服务本身没跑起来。curl http://127.0.0.1:3000/ - 检查 Nginx 配置文件里的
proxy_pass指向的端口是否和后端实际监听端口一致。有时候是 3000,但配置里写成了 3001。
7.4 现象:接口能通,但页面请求时有跨域报错
如果你没有配置反向代理,而是直接在静态页面里用http://服务器IP:3000来请求后端接口,浏览器就会出现跨域报错。解决思路一般有两种:
- 后端代码里开启 CORS(在 Express 里可以用
cors中间件,其他框架也有类似支持) - 或者像我前面说的,用 Nginx 把
/api代理到后端,这样前端页面和接口在同一个源下,就没有跨域问题了
我强烈推荐第二种,因为 Nginx 反向代理是成熟的标准做法,既解决跨域,又能给后端服务提供一层缓冲。
7.5 现象:数据库文件无法写入
如果你用的是 SQLite 或服务需要写文件,很容易遇到权限问题。比如我在部署时,data目录的所有者是 root,但服务是用 ubuntu 用户启动的(pm2 默认继承当前用户身份),所以服务一尝试写数据库就报SQLITE_CANTOPEN错误。
解决方式:
cd ~/projects/my-site sudo chown -R ubuntu:ubuntu data/这个问题的深层原因是 Linux 的文件权限模型:Nginx 的 worker 进程通常以www-data用户运行,后端进程如果没有特殊配置,可能也是www-data或当前登录用户。写文件时,操作系统会检查“运行进程的用户”是否对“目标文件/目录”有写权限。所以遇到权限问题,先确认进程用户和目标目录的属主,然后chown或chmod调整。
7.6 现象:启动时端口被占用
服务器上如果有多个 Node 进程占用同一个端口,新进程会启动失败。排查用:
sudo lsof -i :3000或者:
sudo ss -tlnp | grep 3000如果端口被旧进程占用,可以先停掉旧进程再重启新的。
8. 把 AI 工具用在工作流的正确姿势
说了这么多,有读者可能会问:既然步骤这么多,坑也这么多,是不是可以让 Claude Code 和 Kimi 全程指挥,自己什么都不用管?
我的答案很明确:不能,也不应该。AI 工具是很好的副驾驶,但方向盘必须握在自己手里。
8.1 什么任务适合交给 AI,什么不适合
我来做一个比较清晰的划分:
| 适合交给 AI 的任务 | 不适合交给 AI 的任务 |
|---|---|
| 生成 Linux 命令、Nginx 配置模板、systemd 服务文件 | 服务器安全策略决策(比如密钥权限收紧) |
| 解释报错日志、分析配置文件语法问题 | 判断服务器的实际负载容量 |
| 梳理部署步骤、对比不同技术方案 | 操作阿里云控制台(比如修改安全组) |
| 帮你写 pm2、Docker、Git 相关命令 | 财务相关的资源规格选择 |
| 快速检索某个服务的最佳实践 | 对生产事故的直接决策和回滚操作 |
尤其是在涉及安全、账号、密钥的场景,我会把 AI 当作“顾问”而不是“执行者”。它给我建议,我做最终决定。比如它告诉我chmod 600 ~/.ssh/id_rsa,我会自己确认一下再做。
8.2 实际协作中一份高效的“对话模板”
这是我整理的一套和 AI 协作部署的高效沟通模板,照着套就能少走弯路:
角色设定:“你是一个有 5 年经验的 DevOps 工程师,我正在部署一个生产环境应用,需要你提供准确、可直接执行的命令。”
上下文信息:
- 服务器系统、配置
- 项目技术栈和目录结构
- 已经完成到哪一步
- 当前遇到的具体报错(完整复制,不要概括)
明确输出格式:“请分步骤列出命令,并标注每一条命令的作用,便于我确认后再执行。”
举个例子,我当时的提问是:
“我的服务器是 Ubuntu 22.04,已经安装了 Nginx 和 Node.js 20。我有一个 Vue 项目构建后的 dist 目录,以及一个 Express 后端服务(监听 3000 端口)。请帮我写一份 Nginx 配置文件,要求:静态文件托管 dist 目录,/api 路径反向代理到 127.0.0.1:3000,并解释 try_files 的作用。”
Claude Code 和 Kimi 都能给出基本可用的回答。这比自己现学 Nginx 配置要快不少,但前提是你对配置的大致结构有概念,不然连哪里写错了都看不懂。
8.3 让 AI 帮忙“事后复盘”
部署成功后,我还会让 Claude Code 帮我检查一下配置和潜在风险点。比如把sudo nginx -T的输出给它看,问有没有不合理的地方;把pm2 status给它看,问有没有需要优化的参数。这种“事后的二次审视”能发现很多自己没注意到的小问题。
有一次它提醒我,Nginx 默认的client_max_body_size是 1m,如果网站允许用户上传大文件,这个限制会导致上传失败。我虽然当时用不到,但记下了这个点,后来项目果然遇到了上传图片的需求,直接就在配置里加上了:
client_max_body_size 20m;这就是 AI 工具的价值——它可能不如资深运维全面,但至少比普通开发者的知识覆盖面广,能帮你提前避坑。
9. 部署完成后要做的几件小事
网站终于跑起来了,但事情还没结束。有几件“小事”决定了这个线上环境能稳定跑多久,强烈建议你在部署完成后尽快处理。
9.1 设置 Nginx 和服务的日志轮转与查看习惯
Nginx 默认的访问日志和错误日志在/var/log/nginx/下,pm2 的日志在~/.pm2/logs/下。时间一长,日志文件会越来越大,占用磁盘空间。系统自带的logrotate一般会对 Nginx 日志做轮转,pm2 我则是手动定期清理:
pm2 flush日常排查问题的时候,养成先看日志的习惯:
sudo tail -f /var/log/nginx/error.log pm2 logs my-api这两个命令能解决 90% 的线上问题诊断。
9.2 备份策略:交互式数据必须定期备份
如果你的网站有用户注册、文章发布等写操作,数据备份不是“要不要”的问题,而是“丢了后你能不能接受”的问题。SQLite 是一个单文件数据库,备份最简单,直接用 cp 或 rsync 到另一台机器/对象存储就行。我一般写一个简单的 cron 任务,每天凌晨打包整个项目目录(包含 sqlite 文件)传到阿里云 OSS:
0 2 * * * tar -czf /tmp/my-site-backup-$(date +\%Y\%m\%d).tar.gz /home/ubuntu/projects/my-site/data && ...具体推送 OSS 的命令每个项目的密钥不同,这里不展开,但请务必把“备份”纳入常规开发流程。
9.3 HTTPS:有域名就尽快上
如果只是用 IP 访问,HTTPS 暂时可以不考虑,但如果你绑定了域名,强烈建议上 HTTPS。阿里云提供免费证书申请,也可以用 Let's Encrypt 的 certbot 自动配置。这个主题比较大,这里不详细展开,但方向先告诉大家。
9.4 记录部署文档
最后一步,也是最容易被忽略的一步:写部署文档。不要觉得“反正以后部署也走同样的流程,记在脑子里就行”。人的记忆会骗人,三个月之后你很可能忘掉某个环境变量、某个 Nginx 特殊配置的原因。
我在项目根目录放了DEPLOY.md,把部署步骤、常用命令、常见问题都写了进去。这份文档不仅对我自己有用,以后如果有新的协作者加入项目,也能快速上手。
10. 我这次部署的整体回顾与一些真心建议
最后聊一点个人体会。
把本地网站部署到阿里云服务器,说难不算难,说简单也不是一蹴而就。核心要点其实就三条:环境对齐、流程清晰、工具好用。Claude Code 和 Kimi 在整个过程中帮了不少忙,但它们更像“经验丰富的队友”,而不是“自动化的黑箱”。真正决定部署成不成、稳不稳的,还是你对项目本身的理解、对每一步操作背后原理的掌握。
如果你现在还处在“本地开发完成,准备第一次上服务器”的阶段,我给你的建议是:
- 不要急着买最高配置的服务器,先搞清楚自己的项目类型和访问量预期
- 每一步操作前想清楚“为什么这么做”,把命令背后的原理弄明白
- 大胆把重复性操作和排查工作交给 AI 工具,但每条命令过自己的眼睛
- 养成部署完成后立刻写文档和做备份的习惯
这次部署只是第一步。后面你可能会遇到流量上来后的优化、HTTPS 证书配置、用 Docker 统一环境、甚至搞一套 CI/CD 自动部署流程。这些方向我都试过,每次都是在这次部署的基础上一点点扩展出来的。希望这篇文章能帮你把第一步走得稳一点,少踩一些我当年踩过的坑。