从本地到云:一个 OpenClaw 玩家的迁移踩坑实录
本文是「OpenClaw 云上实战指南」系列第 5 篇(完结篇)
我在 Mac 上跑了两周龙虾(OpenClaw 🦞),合盖断了 3 次之后决定搬到云上。
头一次断是周五下班,合上 MacBook 就走了------周末两天 Slack 消息没人回、RSS 抓取全停了、cron 任务挂了一地。第二次是出门开会,4G 热点一断龙虾直接掉线。第三次更离谱:macOS 系统更新自动重启,我回来一看 openclaw gateway 进程没了,session 文件还锁着。
三次之后我不想再赌了。合盖断线这事在本地部署是个无解的结构性问题------你不可能要求笔记本永远开着不动。
刚好第 1 篇讲过 Lightsail 一键部署、第 3 篇讲过龙虾自动开 EC2------云端实例不存在"合盖"这个概念,启动之后就一直跑着。搬家本身不难,但坑全藏在迁移过程里。
这篇文章记录我从本地 Mac 迁到亚马逊云科技 EC2 实例的完整过程,包括迁移清单、实际命令、4 个踩过的坑和解法,以及搬完之后的真实体感对比。如果你也受够了笔记本合盖断线,这篇能帮你少走弯路。
搬什么?迁移清单
先搞清楚龙虾的"家当"有哪些。在本地 Mac 上跑一下 tree,看看 ~/.openclaw 目录结构:
bash
~/.openclaw/
├── openclaw.json # 核心配置(模型、渠道、心跳)
├── workspace/ # 工作区(SOUL.md、skills/、memory/ 等)
│ ├── SOUL.md
│ ├── USER.md
│ ├── MEMORY.md
│ ├── memory/
│ │ ├── 2026-02-25.md
│ │ ├── 2026-02-26.md
│ │ └── ...
│ ├── skills/
│ │ ├── content-watcher/
│ │ └── rss-ai-reader/
│ └── articles/
├── sessions/ # 聊天历史
├── .secrets/ # 本地密钥(迁移后用 IAM 替代)
└── crontab.json # 定时任务
一共 5 类东西需要考虑:
| 文件/目录 | 重要程度 | 说明 |
|---|---|---|
openclaw.json |
必须搬 | 核心配置,但到云上要改(见坑 1) |
workspace/ |
必须搬 | 龙虾的"灵魂"------人格、记忆、技能全在这里 |
sessions/ |
建议搬 | 聊天历史,丢了不影响功能但龙虾会"失忆" |
.secrets/ |
不要搬 | 本地密钥文件,到了云上用 IAM 角色替代,更安全 |
crontab.json |
必须搬 | 定时任务配置,但时区需要调整(见坑 3) |
其中 workspace/ 是重中之重。里面的 SOUL.md 定义了龙虾的性格,memory/ 存着它的日常记忆,skills/ 是你装的各种能力插件。这些丢了龙虾就不是"你的龙虾"了------它虽然还能跑,但会变成一只陌生的新龙虾。
动手搬家:4 条命令
云端实例我已经按第 1 篇的方案 B 开好了------一台 t4g.medium ARM 实例,挂了 IAM 角色,Bedrock 权限就位。
1. 打包本地文件
bash
# 本地 Mac 上执行
cd ~/.openclaw
tar czf ~/openclaw-backup.tar.gz \
openclaw.json \
workspace/ \
sessions/ \
crontab.json
看看包有多大:
bash
$ ls -lh ~/openclaw-backup.tar.gz
-rw-r--r-- 1 bill staff 4.2M 3 8 14:32 openclaw-backup.tar.gz
跑了两周,4MB 多------主要是 session 历史。
2. 传到云端
bash
# rsync 增量传输,比 scp 断点续传更靠谱
rsync -avzP ~/openclaw-backup.tar.gz \
ubuntu@<EC2-IP>:~/
输出:
bash
sending incremental file list
openclaw-backup.tar.gz
4,398,080 100% 12.35MB/s 0:00:00 (xfr#1, to-chk=0/1)
3. 云端解压
bash
# SSH 到 EC2
ssh ubuntu@<EC2-IP>
# 解压到 ~/.openclaw
mkdir -p ~/.openclaw
cd ~/.openclaw
tar xzf ~/openclaw-backup.tar.gz
4. 启动前先改配置
别直接启动------配置文件还是本地版本的,直接跑会炸。改什么见下面的坑 1。
坑 1:API Key → IAM 角色------配置文件要改
这是我踩的头号坑。本地 Mac 上用的是 Anthropic 官方 API Key,配置长这样:
jsonc
// 本地版 openclaw.json
{
"llm": {
"provider": "anthropic",
"model": "claude-sonnet-4-20250514",
"apiKey": "sk-ant-api03-xxxxxxxxxxxxx"
}
}
搬到 EC2 后要换成 Bedrock + IAM,不需要任何密钥 (第 1 篇详细讲过原理):
jsonc
// 云端版 openclaw.json
{
"llm": {
"provider": "amazon-bedrock",
"model": "anthropic.claude-sonnet-4-20250514",
"region": "us-east-1"
}
}
用 diff 看一下改了什么:
diff
{
"llm": {
- "provider": "anthropic",
- "model": "claude-sonnet-4-20250514",
- "apiKey": "sk-ant-api03-xxxxxxxxxxxxx"
+ "provider": "amazon-bedrock",
+ "model": "anthropic.claude-sonnet-4-20250514",
+ "region": "us-east-1"
}
}
三行改动,API Key 直接删掉。EC2 实例通过 IAM 角色自动获取临时凭证,不需要配置文件里写任何密钥。
验证方法:
bash
# 确认 IAM 角色已绑定
$ curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/
OpenClawBedrockRole
# 确认 Bedrock 可调用
$ aws bedrock-runtime invoke-model \
--model-id anthropic.claude-sonnet-4-20250514 \
--region us-east-1 \
--body '{"anthropic_version":"bedrock-2023-05-31","max_tokens":10,"messages":[{"role":"user","content":"ping"}]}' \
/dev/stdout 2>/dev/null | jq -r '.content[0].text'
Pong!
看到 Pong! 就说明模型调用链路通了。整个过程不需要管密钥轮换、不需要担心 Key 泄露------IAM 角色的临时凭证由亚马逊云科技自动管理,每小时刷新一次。
💡 如果之前本地用的是其他模型(比如 OpenAI),Bedrock 上也有 Claude、Nova、DeepSeek 等多种选择,改
model字段就行。第 4 篇会详细讲 Nova 模型的切换实战。具体支持列表见 Bedrock 模型页面。
坑 2:Session 历史路径变了------龙虾"失忆"
把 sessions/ 目录搬过去之后,启动龙虾,发现它完全不记得之前的对话。
检查 session 文件:
bash
$ ls sessions/
main.json slack-C07XXXXXX.json telegram-123456789.json
$ head -5 sessions/main.json
{
"id": "main",
"createdAt": "2026-02-22T06:30:00.000Z",
"homedir": "/Users/bill/.openclaw",
"messages": [
问题在 homedir 字段------还指向 /Users/bill/.openclaw(macOS 路径),但云端是 /home/ubuntu/.openclaw。OpenClaw 用这个路径解析 workspace 里的相对引用。
修复:批量替换路径
bash
# 一行搞定
cd ~/.openclaw/sessions
sed -i 's|/Users/bill/.openclaw|/home/ubuntu/.openclaw|g' *.json
验证:
bash
$ grep homedir main.json
"homedir": "/home/ubuntu/.openclaw",
重启 gateway,龙虾恢复记忆------之前的对话上下文全回来了。
bash
$ openclaw gateway restart
Gateway restarted. Sessions loaded: 3
踩坑教训 :迁移完启动前,养成习惯先 grep 一遍旧路径,确认没有残留:
bash
$ grep -r '/Users/' ~/.openclaw/sessions/ | wc -l
0 # 确认没有残留的 macOS 路径
⚠️ 如果你的 session 文件特别大(几十 MB),也可以选择不迁移------龙虾会从
MEMORY.md和memory/目录重建上下文。丢的是逐条对话记录,不是"人格"。人格在SOUL.md,记忆在memory/,这些都在 workspace 里。
坑 3:定时任务时区差 8 小时------凌晨 3 点推送日报
本地 Mac 时区是 Asia/Shanghai(UTC+8),我设了一个每天早上 9 点抓 RSS 并推送摘要的 cron:
jsonc
// crontab.json(本地版)
{
"jobs": [
{
"name": "daily-rss-digest",
"schedule": "0 9 * * *",
"task": "抓取 RSS 订阅,生成今日摘要,推送到 Slack"
}
]
}
搬到 EC2 后没改,结果------凌晨 1 点(UTC 9:00 = 北京时间 17:00?不对,UTC 9:00 = 北京 17:00)。
等等,我之前设的是"本地 9:00",本地是 UTC+8,所以实际是 UTC 1:00。到了 EC2 上系统时区是 UTC,cron 读的是 UTC 时间,0 9 * * * 就变成了 UTC 9:00 = 北京 17:00。
总之时间全乱了。
解法:统一用 UTC 思维
jsonc
// crontab.json(云端版,UTC 时间)
{
"jobs": [
{
"name": "daily-rss-digest",
"schedule": "0 1 * * *",
"task": "抓取 RSS 订阅,生成今日摘要,推送到 Slack"
}
]
}
0 1 * * * = UTC 01:00 = 北京时间 09:00。搬家时脑子里要装一个公式:北京时间减 8 小时 = UTC 时间。
转换速查表(北京时间 → UTC cron 表达式):
| 你想要的北京时间 | cron 里写的 UTC |
|---|---|
| 08:00 | 0 0 * * * |
| 09:00 | 0 1 * * * |
| 12:00 | 0 4 * * * |
| 18:00 | 0 10 * * * |
| 22:00 | 0 14 * * * |
或者直接让龙虾帮你算------在 Slack 里跟它说"帮我把所有 cron 任务从北京时间转成 UTC",它会自动改 crontab.json 里的时间字段。毕竟这种机械换算的活交给 AI 来做正合适。
💡 你也可以在 EC2 上改系统时区(
timedatectl set-timezone Asia/Shanghai),但不建议------云上统一用 UTC 是业界惯例,避免和 CloudWatch、CloudTrail 等服务的日志时间对不上。日志排查的时候时区不统一会让人抓狂。
坑 4:渠道重连------Token 能用但 Webhook 要换
Slack 和 Telegram 的 bot token 是跟着 bot 走的,不绑定特定 IP 或机器。所以 token 搬过去理论上直接能用------但 webhook URL 是绑 IP 的,换了机器就得更新。
Slack(Socket Mode)
如果你用的是 Socket Mode(推荐),连接方式是 outbound websocket,不需要 webhook URL,token 搬过去就能用:
jsonc
// openclaw.json --- Slack 配置,直接搬
{
"channels": {
"slack": {
"enabled": true,
"appToken": "xapp-1-A07XXXXXX-...",
"botToken": "xoxb-..."
}
}
}
启动后确认连接:
bash
$ openclaw gateway start
...
[Slack] Connected via Socket Mode ✓
[Slack] Listening on 2 channels
Telegram(Webhook Mode)
Telegram bot 默认用 webhook,URL 绑定了旧机器的地址。搬到新 IP 后需要更新:
bash
# 更新 webhook 到新 IP
curl -s "https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://<NEW-EC2-IP>:8443/telegram/webhook"
# 验证
curl -s "https://api.telegram.org/bot<TOKEN>/getWebhookInfo" | jq '.result.url'
"https://<NEW-EC2-IP>:8443/telegram/webhook"
如果嫌每次换 IP 都要改 webhook,可以改用 long polling 模式------在 openclaw.json 里把 webhook 去掉,龙虾会自动降级到 polling:
jsonc
{
"channels": {
"telegram": {
"enabled": true,
"botToken": "7000000000:AAxxxxxx"
// 不配 webhook,自动用 long polling
}
}
}
💡 第 2 篇里的 iMessage 渠道比较特殊------它依赖 macOS 系统,如果你从 Mac 迁到 Linux,iMessage 渠道需要单独保留在 Mac 实例上。可以参考第 2 篇的 Mac 云实例方案。
搬家前后对比
跑了一周之后回头看,差距一目了然:
| 维度 | 本地 Mac | EC2 云端 |
|---|---|---|
| 在线时长 | 取决于开机时间,平均每天不到 12 小时 | 7×24 不间断运行 |
| 断线次数(一周) | 3 次(合盖、断网、重启) | 0 次 |
| API 密钥管理 | 明文写在配置文件里 | IAM 角色自动管理,零密钥 |
| cron 定时任务 | 合盖就停,醒来不一定恢复 | 准时执行,从未漏过 |
| Slack 消息响应 | 人在电脑前才有反应 | 凌晨 3 点消息也能秒回 |
| RSS 抓取推送 | 出差那几天漏了 3 天内容 | 每天定点推送,一天不落 |
| 安全审计 | 无,全靠自觉 | CloudTrail 记录每次 API 调用 |
| 迁移耗时 | --- | 约 40 分钟(含踩坑排查时间) |
体感上变化很大的一点:以前用龙虾像用一个"桌面软件",打开才有,关了就没了。搬到云上之后它变成了一个"一直在线的同事"------你不需要主动想着去用它,它自己会在后台帮你抓新闻、处理消息、跑定时任务。
那三次合盖断线的日子一去不复返了。
写给还在犹豫的人
如果你现在还在本地跑龙虾,而且只是偶尔用用,本地完全够了------不需要为了"上云"而上云。
但如果你已经开始依赖它(配了 cron 任务、接了 Slack 渠道、让它帮你监控 RSS),那迁移到云上是早晚的事。与其等下次合盖断线的时候着急,不如现在花 40 分钟搬完。
从这个系列五篇文章走下来,一只龙虾从"试试看"变成了"离不开":第 1 篇解决了部署和安全问题,第 2 篇打通了苹果生态,第 3 篇实现了全自动扩展,第 4 篇探索了多模型协作,这第 5 篇解决了"搬家"的临门一脚。
五篇看完,你手上应该已经有一只跑在云端、24/7 在线、零密钥、能自己干活的龙虾了。剩下的事------就交给它吧。
完整迁移命令速查
怕你上面看散了,这里把所有命令串一遍:
bash
# ===== 本地 Mac =====
# 1. 打包
cd ~/.openclaw
tar czf ~/openclaw-backup.tar.gz \
openclaw.json workspace/ sessions/ crontab.json
# 2. 传到云端
rsync -avzP ~/openclaw-backup.tar.gz ubuntu@<EC2-IP>:~/
# ===== 云端 EC2 =====
# 3. 解压
mkdir -p ~/.openclaw && cd ~/.openclaw
tar xzf ~/openclaw-backup.tar.gz
# 4. 改配置:API Key → Bedrock
# 编辑 openclaw.json,provider 改 amazon-bedrock,删掉 apiKey
# 5. 修 session 路径
cd sessions/
sed -i 's|/Users/<你的用户名>/.openclaw|/home/ubuntu/.openclaw|g' *.json
# 6. 改 cron 时区(UTC+8 → UTC,减 8 小时)
# 编辑 crontab.json
# 7. 更新 Telegram webhook(如果用了的话)
curl -s "https://api.telegram.org/bot<TOKEN>/setWebhook?url=https://<EC2-IP>:8443/telegram/webhook"
# 8. 启动!
openclaw gateway start
一句话总结
搬家本身不难------4 条命令传文件,改 3 处配置------难的是那几个不看日志根本发现不了的坑。踩完之后回头看,早搬早省心。
📖 系列回顾:
- 第 1 篇:Bedrock + IAM 零密钥部署
- 第 2 篇:Mac 云实例接入苹果生态
- 第 3 篇:龙虾 AI 全自动部署实战
- 第 4 篇:电商多 Agent 协作实战(即将发布)
🔗 延伸阅读:《把 AI Agent 部署到云端,是值得做的事》 --- 亚马逊云科技官方博客
OpenClaw 是开源项目,欢迎参与社区贡献。本系列所有代码和配置均在 GitHub 上公开。