从本地到云:一个 OpenClaw 玩家的迁移踩坑实录

从本地到云:一个 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.mdmemory/ 目录重建上下文。丢的是逐条对话记录,不是"人格"。人格在 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 处配置------难的是那几个不看日志根本发现不了的坑。踩完之后回头看,早搬早省心。

📖 系列回顾:


OpenClaw 是开源项目,欢迎参与社区贡献。本系列所有代码和配置均在 GitHub 上公开。