背景 OpenClaw 是一个强大的 AI 助手框架,但自建服务器成本不低。HuggingFace Space 提供免费 Docker 容器环境(2vCPU + 16GB RAM),足够跑起 OpenClaw 配合 MiniMax 模型,实现零成本 7×24 在线部署。
本文记录完整部署流程,包含数据持久化(备份/恢复)和关键的 HF Spaces 适配修改。
整体架构
层级
方案
成本
模型层
MiniMax API(api.xins.live)
参考 MiniMax 额度
部署层
HuggingFace Space(Docker)
$0
持久化层
HuggingFace Dataset 备份
$0
保活层
UptimeRobot 定时请求
$0
第一步:创建 HuggingFace Space 访问 hf.co/spaces → New Space
SDK :选择 Docker
Template :选择 Blank
Privacy :选择 Private(保护个人数据)
第二步:创建 HuggingFace Dataset 在头像菜单 → New Dataset ,创建私有数据集。 记下数据集名称,格式为 username/dataset-name。
第三步:生成 Access Token 头像菜单 → Access Tokens → New token
Token Type :选择 Write(需要写入 Dataset)
复制保存好 Token。
第四步:配置环境变量 回到 Space 页面 → Settings → 找到 Variables and Secrets ,添加以下变量:
变量名
取值
说明
OPENCLAW_GATEWAY_TOKEN
自定义 Token
用于登录 Web UI
HF_DATASET
username/dataset-name
私有 Dataset 名称
HF_TOKEN
你的 HF Access Token
Secret
第五步:上传部署文件 在 Space 的 Files 页面创建以下三个文件。
sync.py(数据持久化脚本) 负责每次 Space 重启时从 HuggingFace Dataset 恢复数据,以及定期备份。支持 SHA256 校验、Gateway 重启跳过无变化备份、20 分钟超时。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 import osimport sysimport tarfileimport shutilimport hashlibimport subprocessfrom huggingface_hub import HfApi, hf_hub_downloadapi = HfApi() repo_id = os.getenv("HF_DATASET" ) token = os.getenv("HF_TOKEN" ) FILENAME = "latest_backup.tar.gz" CHECKSUM_FILE = "latest_backup.sha256" BACKUP_TIMEOUT = 1200 def calc_sha256 (filepath ): h = hashlib.sha256() with open (filepath, "rb" ) as f: for chunk in iter (lambda : f.read(65536 ), b"" ): h.update(chunk) return h.hexdigest() def restore (): print (f"[sync] restore() 开始" ) print (f" HF_DATASET: {repo_id} " ) print (f" HF_TOKEN: {'已设置' if token else '未设置' } " ) if not repo_id or not token: print ("[sync] Skip Restore: HF_DATASET or HF_TOKEN not set" ) return print (f"[sync] 阶段 1/3:下载 & 校验" ) try : print (f" 下载 {FILENAME} ..." ) path = hf_hub_download( repo_id=repo_id, filename=FILENAME, repo_type="dataset" , token=token, ) print (f" 下载完成: {os.path.getsize(path) / 1024 / 1024 :.1 f} MB" ) except Exception as e: print (f" 远程无备份或下载失败 ({type (e).__name__} ),跳过恢复" ) return print (f" 校验 tar 包完整性 ..." ) try : with tarfile.open (path, "r:gz" ) as tar: members = tar.getmembers() print (f" ✓ tar 包完整,{len (members)} 个条目" ) except tarfile.TarError as e: print (f" ✗ tar 包损坏: {e} " ) return print (f" 校验 SHA256 ..." ) try : cs_path = hf_hub_download(repo_id=repo_id, filename=CHECKSUM_FILE, repo_type="dataset" , token=token) expected = open (cs_path).read().strip() actual = calc_sha256(path) if expected != actual: print (f" ✗ SHA256 不匹配!expected={expected[:16 ]} ..., actual={actual[:16 ]} ..." ) return print (f" ✓ SHA256 匹配" ) except Exception as e: print (f" ! SHA256 校验跳过: {e} " ) print (f"[sync] 阶段 2/3:清空 & 解压" ) target = "/root/.openclaw" if os.path.exists(target): before = set (os.listdir(target)) shutil.rmtree(target) print (f" 已清空 {target} ({len (before)} 项)" ) os.makedirs(target) print (f" 解压到 /root/ ..." ) with tarfile.open (path, "r:gz" ) as tar: tar.extractall(path="/root" ) print (f" 解压完成" ) restored = sorted (os.listdir("/root/.openclaw" )) print (f"[sync] ✓ 恢复成功,共 {len (restored)} 项:" ) for item in restored: m = os.stat(os.path.join("/root/.openclaw" , item)).st_mode & 0o777 print (f" {oct (m)[-3 :]} {item} " ) def backup (): print (f"[sync] backup() 开始" ) print (f" HF_DATASET: {repo_id} " ) print (f" HF_TOKEN: {'已设置' if token else '未设置' } " ) if not repo_id or not token: print ("[sync] Skip Backup: HF_DATASET or HF_TOKEN not set" ) return src = "/root/.openclaw" tmp_tar = "/tmp/latest_backup.tar.gz" tmp_sha = "/tmp/latest_backup.sha256" print (f"[sync] 打包 {src} ..." ) tar_cmd = ( f"cd /root && tar --numeric-owner -czf {tmp_tar} " f".openclaw > /dev/null 2>&1 && echo OK" ) print (f" tar 命令执行中 (timeout={BACKUP_TIMEOUT} s) ..." ) proc = subprocess.run( tar_cmd, shell=True , capture_output=True , text=True , timeout=BACKUP_TIMEOUT ) if proc.returncode != 0 : print (f"[sync] ✗ tar 失败: {proc.stderr[:200 ]} " ) return size_mb = os.path.getsize(tmp_tar) / 1024 / 1024 print (f" 打包完成: {size_mb:.1 f} MB" ) checksum = calc_sha256(tmp_tar) with open (tmp_sha, "w" ) as f: f.write(checksum) print (f" SHA256: {checksum[:16 ]} ..." ) print (f"[sync] 上传 {FILENAME} ({size_mb:.1 f} MB) ..." ) try : api.upload_file( path_or_fileobj=tmp_tar, path_in_repo=FILENAME, repo_id=repo_id, repo_type="dataset" , token=token, ) print (f" ✓ {FILENAME} 上传成功" ) except Exception as e: print (f"[sync] ✗ {FILENAME} 上传失败: {e} " ) for f in [tmp_tar, tmp_sha]: if os.path.exists(f): os.remove(f) print ("[sync] Backup aborted" ) return try : api.upload_file( path_or_fileobj=tmp_sha, path_in_repo=CHECKSUM_FILE, repo_id=repo_id, repo_type="dataset" , token=token, ) print (f" ✓ {CHECKSUM_FILE} 上传成功" ) except Exception as e: print (f"[sync] ✗ {CHECKSUM_FILE} 上传失败: {e} " ) for f in [tmp_tar, tmp_sha]: if os.path.exists(f): os.remove(f) print (f"[sync] ✓ 备份完成: {FILENAME} ({size_mb:.1 f} MB)" ) if __name__ == "__main__" : if len (sys.argv) > 1 and sys.argv[1 ] == "backup" : backup() else : restore()
关键特性:
SHA256 校验 :备份上传 latest_backup.sha256,恢复时校验完整性
tar 输出屏蔽 :> /dev/null 2>&1 避免干扰日志,进程退出码判断成功与否
20 分钟超时 :tar 打包设置 1200s 超时,适合大备份包
恢复跳过机制 :远程无备份时直接跳过(except 捕获),不报错
恢复前清空 :shutil.rmtree + os.makedirs 确保旧文件不残留
start-openclaw.sh(启动脚本) 1 2 3 4 5 6 7 #!/bin/bash set -epython3 /app/sync.py restore exec openclaw gateway
关键适配点(相对于通用部署):
dangerouslyDisableDeviceAuth: true HF Spaces 是完全托管的环境,用户无法 SSH 进入容器运行 openclaw pairing approve 命令。开启此选项后,Web UI 配对验证被禁用,直接用 Token 登录。
allowedOrigins 限制来源 只允许指定的 HF Space 域名访问控制台,防止 Token 泄露被滥用。需在 openclaw.json 中手动添加:
1 2 3 4 5 6 7 "gateway" : { "controlUi" : { "allowedOrigins" : [ "https://[username]-[spacename].hf.space" ] } }
OPENCLAW_GATEWAY_TOKEN 替代密码 不使用传统的 OPENCLAW_GATEWAY_PASSWORD,改用 Token 模式,值通过环境变量注入。
MiniMax 模型配置 在 openclaw.json 的 models.providers 中配置 baseUrl: https://api.xins.live,完整示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 "models" : { "mode" : "replace" , "providers" : { "cloud" : { "api" : "anthropic-messages" , "apiKey" : "你的 MiniMax API Key" , "baseUrl" : "https://api.xins.live" , "models" : [ { "id" : "MiniMax" , "name" : "MiniMax" , "reasoning" : true , "contextWindow" : 200000 , "maxTokens" : 131072 , "cost" : { "input" : 4.2 , "output" : 16.8 , "cacheRead" : 0.42 , "cacheWrite" : 2.625 } } ] } } }
bind: "lan" HF Space 容器内必须绑定 LAN 接口才能被外部访问。
控制台模型白名单 在 openclaw.json 的 agents.defaults 中通过 models 字段指定 Control UI 可选的模型列表:
1 2 3 4 5 6 7 8 9 "agents" : { "defaults" : { "models" : { "cloud/MiniMax" : { } , "minimax/MiniMax-M2.7-highspeed" : { } , "loss/MiniMax" : { } } } }
Dockerfile(容器镜像配置) 完整的容器镜像配置,包含 .NET SDK(minimax-docx skill 用 OpenXML SDK)、Python 和 Node.js 依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 FROM node:22 -slimRUN apt-get update && apt-get install -y --no-install-recommends \ git openssh-client build-essential python3 python3-pip \ g++ make ca-certificates curl wget gnupg \ && rm -rf /var/lib/apt/lists/* RUN ln -snf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' > /etc/timezone RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc \ | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \ && curl -fsSL https://packages.microsoft.com/config/debian/12/prod.list \ | tee /etc/apt/sources.list.d/microsoft-prod.list \ | grep -v '^#' | grep -v '^$' > /dev/null \ && apt-get update \ && apt-get install -y --no-install-recommends dotnet-sdk-8.0 \ && rm -rf /var/lib/apt/lists/* RUN pip3 install --no-cache-dir --break-system-packages \ "huggingface_hub>=0.23" \ openpyxl reportlab pypdf beautifulsoup4 lxml requests uv RUN npm install -g openclaw@latest --unsafe-perm \ && npm install -g pptxgenjs --unsafe-perm \ && npm install -g mmx-cli --unsafe-perm \ && ln -sf /usr/local/lib/node_modules/openclaw/openclaw.mjs /usr/local/bin/openclaw RUN npm install -g hexo --unsafe-perm \ && npm install -g hexo-deployer-aliyun-oss --unsafe-perm \ && npm install -g hexo-generator-archive --unsafe-perm \ && npm install -g hexo-generator-category --unsafe-perm \ && npm install -g hexo-generator-index --unsafe-perm \ && npm install -g hexo-generator-tag --unsafe-perm \ && npm install -g hexo-renderer-marked --unsafe-perm \ && npm install -g hexo-renderer-pug --unsafe-perm \ && npm install -g hexo-renderer-ejs --unsafe-perm \ && npm install -g hexo-renderer-stylus --unsafe-perm \ && npm install -g probe-image-size --unsafe-perm WORKDIR /app COPY sync.py . COPY start-openclaw.sh . RUN chmod +x start-openclaw.sh ENV PORT=7860 HOME=/rootEXPOSE 7860 CMD ["./start-openclaw.sh" ]
⚠️ Microsoft APT 源添加时不要用 sed 删除 arch=amd64 ,否则 prod.list 会变成 deb [] https://... 导致 apt 解析失败。直接 tee 原始文件即可,node:22-slim 默认支持多架构。
⚠️ HF Spaces 容器内 npm 全局包的 .bin 目录不会自动创建,导致 openclaw 命令找不到。必须显式 ln -sf 创建符号链接到 /usr/local/bin/,这一步不能省略。
⚠️ Hexo 阿里云 OSS 凭证不要写在 Dockerfile 里 ,改为在 HF Spaces Settings → Variables and Secrets 中配置以下环境变量(对应 _config.yml 的 deploy: 节点):
OSS_REGION → oss-cn-wuhan-lr
OSS_ACCESS_KEY_ID → 你的 Access Key ID
OSS_ACCESS_KEY_SECRET → 你的 Access Key Secret 部署完成后手动运行 hexo g && hexo deploy 即可。
第六步:提交并验证
在 Space 的 Files 页面添加上述三个文件后 Commit ,HF 自动触发构建
点击 Logs 查看构建和运行状态
日志出现以下信息说明部署成功:
1 2 3 4 5 ◇ Gateway connection ───────────────────────────── │ Gateway target: ws://10.108.65.42:7860 │ Source: local lan 10.108.65.42 │ Config: /root/.openclaw/openclaw.json │ Bind: lan
第七步:配置 UptimeRobot 保活 HF Space 在 48 小时无访问 时会自动休眠。用 UptimeRobot 定时 ping 你的 Space URL 即可保持在线:
Monitor Type:HTTP(s)
URL:https://[username]-[spacename].hf.space/
Monitoring Interval:5 分钟(免费版最小间隔)
登录与使用 在浏览器打开你的 Space URL,首次访问时 UI 显示”未连接”状态。 在登录界面输入 OPENCLAW_GATEWAY_TOKEN 设置的值,确认后状态变为 “Connected” 。
之后就可以正常与 AI 对话了。
常见问题 Q: 部署后 Token 登录一直失败? 检查环境变量 OPENCLAW_GATEWAY_TOKEN 是否正确配置。另外确认 Space 日志里 config 是否写入了正确的 token。
Q: HF Space 重启后数据丢失? 确认 HF_DATASET 和 HF_TOKEN 环境变量配置正确。Space 首次部署时 sync.py restore 找不到备份文件是正常的(显示 Restore Note 即可),重新部署后下次重启就会自动恢复。
Q: openclaw: command not found? 这是 HF Spaces 容器内 npm 全局包路径问题,表现为 Dockerfile 构建成功但启动脚本运行 openclaw gateway 时报错。原因是 npm 全局包的 .bin 目录在容器内没有自动创建,CLI 符号链接丢失。
修复方法 :在 Dockerfile 第 4 步末尾加上:
1 && ln -sf /usr/local/lib/node_modules/openclaw/openclaw.mjs /usr/local/bin/openclaw
然后重新 Rebuild Space 即可。
Q: 国内访问 HF Space 速度慢? 可以用 Cloudflare Tunnel 或类似方案做反向代理改善访问速度。
记录于 2026-04-14 00:14