我用微信遥控 AI 给服务器装软件:一次真实的环境搭建记录
前言
前段时间我在腾讯云上跑了个 OpenClaw(一个开源的 AI Agent 框架),然后把它接进了微信——通过 ClawBot 组件,我可以在微信里直接跟它对话,让它去操作服务器。
这篇文章记录了一个晚上的完整对话过程:
- 让它自检新买的轻量服务器
- 把
next.top上的 WordPress 和几个 Node 服务迁过来 - 收拾迁移遗留的三个坑(进程管理、明文密码、目录混乱)
- 按需装一整套安全工具
- 顺手搞定了 Clash 代理
全程我基本只发中文短句,它在服务器上敲命令、读输出、自己排错。
一、第一句:「你是谁」
刚接上微信,我试探性地问了一句。
我: 你是谁
ClawBot:
⚠️ Missing API key for provider "openai". Run `openclaw doctor --fix`
to repair stale OpenAI model/session routes...
开局就翻车——Provider 配置里残留了 OpenAI 的模型路由,但没有 API key。这算是 OpenClaw 部署时的经典坑:改了模型但没清旧路由。
修掉之后,它自我介绍:
我是 OpenClaw,跑在这个腾讯云轻量服务器上的一个 AI agent。我的名字还没起好呢(IDENTITY.md 还是空的 😅)……现在是 DeepSeek 的模型在驱动我。
IDENTITY.md 是 OpenClaw 的身份文件——空的就说明还没赋予人格设定。这个细节后面用上了。
二、第一项任务:自检 + 迁移规划
我: 请自检一下当前主机,另外远程我还有一台主机 next.top,我想迁移该机的 WordPress 和一些 nodejs 服务。
它很快给出了自检报告:
| 项目 | 状态 |
|---|---|
| 系统 | Ubuntu 24.04 LTS, KVM, 腾讯云 CVM |
| 内存 | 3.6G 总量,已用 1G,可用 2.6G ✅ |
| 磁盘 | 59G 总量,已用 18G(31%),剩余 40G ✅ |
| Swap | 9.9G,未使用 ✅ |
| Node.js | v22.23.1 ✅ |
| npm | 10.9.8 ✅ |
| PM2 / Nginx / MySQL / PHP / Docker | ❌ 全部未安装 |
| 监听端口 | 22(SSH), 53(DNS), 36877(OpenClaw), 9222(Chrome调试) |
结论:主机很健康,但除了 Node.js 和 OpenClaw,是个「裸机」。
然后它反问我要 next.top 的 SSH 信息——这是对的,不该瞎猜。
💡 这里有个值得学习的点:它没有一上来就
apt install nginx mysql php,而是先摸清现状、再问清需求。先勘察,后动工——这是运维的基本素养,很多"智能"工具反而会跳过这一步。
三、配 SSH 免密:连踩两次坑
我告诉它:主机名更正为 itnext.top,SSH 端口 1024,root 已配好免密。
它先把自己的公钥报出来让我去加:
ssh-ed25519 AAAAC...zne9n4XLZm/ujUR4j/a ubuntu@VM-0-6-ubuntu
我: 已添加过
结果它连接失败:
⚠️ ssh -o ConnectTimeout=5 ... @itnext.top -p 1024 failed
它给出了三条排查思路(很标准):
- 公钥是否放到了
/root/.ssh/authorized_keys(注意是 root 用户) sshd_config是否禁用了PubkeyAuthentication/root/.ssh目录权限(chmod 700/600)
⚠️ SSH 免密排查清单(我后来整理了一下):
# 服务端检查三连 ls -ld ~/.ssh && ls -l ~/.ssh/authorized_keys # 700 / 600 grep -E "PubkeyAuthentication|AuthorizedKeysFile" /etc/ssh/sshd_config tail -f /var/log/auth.log # 看实时拒绝原因
那次我是真的没加对,后来直接换了台机器。这段流程本身没毛病。
四、中途插入:给 AI 起名
我: 你就叫超人吧,我叫超哥……你帮我自主命名一下(其他 Agent)
它当场把身份体系建好了:
🦸 超人 总指挥官
🛡️ 钢骨 安全 Agent
⚡ 闪电 IoT Agent
🧬 铁匠 DevOps Agent
🔍 哨兵 信息 Agent
🏥 神医 医工 Agent
🧠 智库 知识管理 Agent
🎯 猎手 漏洞挖掘 Agent
从技术角度看,这段其实很重要:IDENTITY.md 一旦写入,后续所有会话的系统提示词里都会带上这个身份——它会持续影响 AI 的语气、自我认知和任务分工方式。
📌 实践建议:给长期使用的 Agent 写
IDENTITY.md/SOUL.md,比每次对话里重复交代背景高效得多。这就是"提示词工程"落到文件系统上的形态。
五、迁移已完成,那就接手收尾
我: 哦,那个我用你们网站的 OrcaTerm 啥的 web 客户端聊,已迁移好了,目前 itnext.top 对应就是你所在的主机了,你可再自检一下。
(迁移过程是另一次操作,见后续文章)
它重新自检,这次全貌清楚多了:
Web 服务:
| 服务 | 状态 | 端口 |
|---|---|---|
| Nginx | ✅ | 80/443 |
| MySQL 8.0 | ✅ | 3306 |
| PHP 8.3-FPM | ✅ | Unix socket |
| Redis | ✅ | 6379 |
| WordPress | ✅ | /usr/share/nginx/html/ |
| Certbot | ✅ | /opt/certbot |
Node.js 应用(/opt/nodeapp/):
| 应用 | 启动文件 | 备注 |
|---|---|---|
| auth_server | app.js | 认证服务 |
| authsever | app.js | 认证服务(另一版) |
| exoapi | app.js | API 服务 |
| exoapinew | app.js / app_3010.js | API 新版(双端口?) |
| jpapp | app.js | 日语学习 App |
其他服务: RustDesk Server、frp、dnslog、ModSecurity WAF
它主动指出了三个问题:
- 没有进程管理器 —— Node 服务都是
nohup裸跑的,进程崩了就没人拉起来,重启服务器更是一起没 - MySQL 的 wordpress 用户是明文密码
MM3XXXXX - WordPress 装在默认目录
/usr/share/nginx/html/,和一堆accesslog*.txt日志混在一起
我: 你帮我把那三个问题处理一下吧
六、三件事一次干完
1️⃣ PM2 接管 Node 服务
npm install -g pm2
pm2 startup && pm2 save
cd /opt/nodeapp/auth_server && pm2 start app.js --name auth_server
cd /opt/nodeapp/exoapi && pm2 start app.js --name exoapi
cd /opt/nodeapp/exoapinew && pm2 start app.js --name exoapinew
cd /opt/nodeapp/jpapp && pm2 start app.js --name jpapp
结果:
auth_server :3000 ✅ online
exoapi :3001 ✅ online
exoapinew :3010 ✅ online
jpapp :9000 ✅ online ← 原本端口被占用
jpapp 有个坑:9000 端口被一个幽灵 node 进程(PID 152140)占着,导致服务起不来。杀掉之后正常。
💡 排查端口占用:
ss -tlnp | grep :9000 # 谁在监听 ps -p <PID> -o pid,ppid,cmd # 这进程什么来路迁移场景里,"服务起不来"十有八九是端口被旧进程占着,先查这个比看日志快。
同时修了两个服务的 MySQL 连接问题(用户权限 + 认证插件不匹配)。
2️⃣ WordPress 数据库密码加固
明文密码 → 随机强密码,同步更新 wp-config.php。
它特别提示了一点:
注意:WordPress 用的是 MySQL 的
caching_sha2_password而不是mysql_native_password。
这个提示很关键。MySQL 8.0 默认用 caching_sha2_password,而老版本 PHP 的 mysqli/pdo_mysql 扩展可能不支持,会报:
The server requested authentication method unknown to the client
遇到就改回来:
ALTER USER 'wordpress'@'localhost'
IDENTIFIED WITH mysql_native_password BY '新密码';
FLUSH PRIVILEGES;
3️⃣ 迁移 WordPress 目录
# 从 /usr/share/nginx/html/ 迁到 /var/www/wordpress/
sudo mkdir -p /var/www/wordpress
sudo rsync -a /usr/share/nginx/html/ /var/www/wordpress/
然后改 Nginx 配置:
server {
listen 80;
server_name itnext.top www.itnext.top;
root /var/www/wordpress;
index index.php index.html;
location / {
try_files uriuri/ /index.php?args;
}
location ~ \.php {
include snippets/fastcgi-php.conf;
fastcgi_pass 127.0.0.1:81; # PHP-FPM 改到 TCP 81
}
}
为什么把 PHP-FPM 从 socket 改到 TCP 81? 因为原配置可能被其他站点共用,改 TCP 端口能让 WordPress 独立走一个 FPM 池,避免相互影响。
⚠️ 迁移后必查:
nginx -t && systemctl reload nginx curl -I http://127.0.0.1/ # 本地通了没 curl -I http://itnext.top/ # 域名通了没
它顺手还发现:authsever 目录里有个跟 auth_server 同端口冲突的旧版本,没启动,等我决定。这种"多留一手但先不动"的处理方式很稳。
七、再搬一个服务:exoapinew
我: author* server 我做测试的,可先不管,exoapinew 在源主机上,IP 为 106.53.105.153,这边 root 可以 ssh 过去,要不你帮我迁移一下?
又是免密的问题。这次我直接把密码给了它:
我: 你帮我加一下吧,root 密码为 TXXXXXX
它自己把公钥写上去了,然后完成迁移:
| 项目 | 源 (106.53.105.153) | 目标(本机) |
|---|---|---|
| 源码 | /home/larkin/exoapinew/ |
/opt/nodeapp/exoapinew/ |
| 数据库 | exopro_db |
exopro_db ✅ 已导入 |
| 服务 | node 裸跑 | PM2 管理,端口 3010 |
| MySQL | root / MMXXXXXX |
root / 已重置 |
🔐 安全提醒:明文密码通过聊天传输是有风险的,事后我把相关密码全部轮换了。更好的做法是用 SSH 密钥 +
ssh-copy-id,或者临时开一个受限账号。
Node 服务迁移的标准四步(我总结的):
# 1. 搬源码(保留权限,排除 node_modules —— 到目标机重装更可靠)
rsync -av --exclude node_modules /home/larkin/exoapinew/ \
root@目标IP:/opt/nodeapp/exoapinew/
# 2. 搬数据库
ssh root@源IP "mysqldump -u root -p'密码' exopro_db" > exopro_db.sql
mysql -u root -p'新密码' exopro_db < exopro_db.sql
# 3. 装依赖(在目标机,保证二进制兼容)
cd /opt/nodeapp/exoapinew && npm install --production
# 4. 纳入 PM2 并开机自启
pm2 start app.js --name exoapinew && pm2 save
八、装安全工具:别装整套 Kali
我: 我原来在本地做网络安全工作是用 Kali 系统,你这边已是 Ubuntu 系统,你有啥好的建议,工具要怎样装最好?
它给了三个方案,推荐第一个:
🥇 方案一:按需安装(推荐)
# 核心必装
sudo apt install -y nmap netcat-openbsd dirb gobuster hydra sqlmap nikto \
masscan whatweb wafw00f wfuzz tcpdump proxychains4
# Python 生态
pip3 install impacket bloodhound adidnsdump certipy-ad
# Go 生态(现代信息收集主力)
go install github.com/projectdiscovery/httpx/cmd/httpx@latest
go install github.com/tomnomnom/assetfinder@latest
🥈 方案二:Docker 跑 Kali 容器
docker run -it --network host -v /opt/kali-shared:/shared \
kalilinux/kali-rolling bash
# 进去后
apt update && apt install -y kali-linux-headless metasploit-framework burpsuite
🥉 方案三:Proot 容器(最轻量,偏玩具)
它的建议理由很中肯:
- 不冗余 —— 只装真正要用的,不装 8GB 的
kali-linux-large - 保持系统干净 —— Ubuntu 原生包管理,升级维护省心
- 资源友好 —— 2C/3.6G 跑完整 Kali 桌面会很卡,但跑工具绰绰有余
🎯 我的实际感受:这个判断是对的。Kali 的价值在于"开箱即用",而不在于"必须用 Kali"。真正高频的工具就那么二十来个,在 Ubuntu 上用
apt+go+pip装完,比拖一个 8GB 的发行版轻快得多。而且本地 Ubuntu 环境更贴近真实的服务器环境——毕竟你要打的靶子大多是 Linux 服务器,不是 Kali。
九、Clash 代理:服务器出墙的正确姿势
我: 另外可能要安装一个 clash 代理,你先试试,代理配置告诉我如何配置。
它先报告了一个现实问题:这台腾讯云服务器访问不了 GitHub(被墙了)。于是给了三个方案:
- 方案 A:我本地跑 Clash,服务器通过
proxychains4走我的代理 → 但我本地没有公网地址 - 方案 B:在能出墙的源主机上装好,编译静态二进制传过来 ✅
- 方案 C:其他
我说走方案 B。最后它搞定了:
🌐 mihomo (Clash Meta) 已安装
版本: v1.19.28
HTTP 代理: 7890
SOCKS 代理: 7891
启动: sudo mihomo-up
停止: sudo mihomo-down
proxychains4 已指向 mihomo
需要你自己做的:编辑 /etc/mihomo/config.yaml 填入节点信息,重启 mihomo。
# 配置好之后验证
sudo mihomo-up
proxychains4 curl -s https://api.github.com | head -5
/etc/proxychains4.conf 里对应的配置:
[ProxyList]
socks5 127.0.0.1 7891
💡 一个小坑:
proxychains4默认走socks4 127.0.0.1 9050(Tor 的端口),一定要改成 mihomo 的 7891,否则会一直超时。
十、当晚完成汇总
🔧 系统
itnext.top 自检完成(Ubuntu 24.04, 2C/3.6G/40G 空闲)
WordPress: /usr/share/nginx/html/ → /var/www/wordpress/
exoapinew: 106.53.105.153 → 本机,PM2 管理 :3010
MySQL root 密码已重置
📦 PM2 管理(开机自启)
auth_server :3000 exoapi :3001
exoapinew :3010 jpapp :9000
🛡️ 安全工具
nmap masscan gobuster dirb sqlmap hydra nikto
whatweb wafw00f wfuzz tcpdump impacket proxychains4
🌐 mihomo (Clash Meta) v1.19.28
HTTP :7890 SOCKS :7891
十一、复盘:这种用法到底靠不靠谱
一个晚上把迁移收尾 + 环境搭建全干完,效率确实高。但我总结了几条边界:
✅ 它擅长什么
- 勘察与汇总 —— 一条命令读一堆系统信息,整理成表格,比人敲得快
- 标准化操作 —— 装包、改配置、迁移目录、配 PM2,套路固定,出错率低
- 串联排错 —— 报错 → 猜测 → 验证 → 修正,这个循环它跑得很顺
- 文档沉淀 —— 顺手就把过程写成了报告
⚠️ 什么必须自己盯着
- 明文密码 —— 全程所有密码我都事后轮换了一遍。别在聊天里长期保存密码
- 目录迁移这类"不可逆"操作 —— 迁移前一定要有备份,
rsync之后别急着rm源目录 - 生产环境改动 —— 域名解析、证书、防火墙规则这些,改之前确认影响面
- 权限边界 —— 给它 root 就等于给了它整台机器,风险自担
🧠 最值得借鉴的两点
第一,先勘察后动手。 上面每一次操作,它都是先 ls / ss / cat 摸清现状,再动手改。这个习惯比任何工具都值钱。
第二,身份与记忆写进文件。 IDENTITY.md / SOUL.md / MEMORY.md 这一套文件化的上下文,让"每次对话都是新开始"这种问题被大幅缓解——这也是这类 Agent 框架跟普通 ChatBot 的核心区别。