我的 OpenClaw 设置:一个能制作网站的“全能盒子”

发布日期
2026年7月31日
更新日期
2026年9月16日
作者
Jacob Lloyd —— 项目完成后,在 AI 协助下撰写
阅读时长
约 13 分钟阅读

简单来说: 这篇文章介绍了我家中的一台小型 Linux 计算机上的 AI 助手是如何维护这个网站的。它们负责撰写草稿、重新构建网站并准备各项更改。不过,任何即将发布的更新都会先经过一个安全脚本的审核:该脚本会预览更新内容、备份服务器数据,且绝不会删除任何文件。这些工作都由 AI 助手来完成;而我则决定何时正式发布更新。

在我家中的一台小型 Linux 主机上运行的 AI 智能体负责维护您正在阅读的这个网站。它们可以真正对网站进行操作,而整个系统设置也确保了它们不会破坏网站:所有更改都通过一个脚本传递到服务器——该脚本会先进行预览、备份服务器,且绝不会删除任何文件;只有在我发出指令后才会发布更新。这个脚本正是最值得借鉴的部分,本文的大部分内容也是围绕它展开的。

简而言之

  • 系统构成:一台运行着 OpenClaw(一款自托管式 AI 智能体网关)的 Linux 迷你电脑,它连接至静态网站生成器以及一个受控部署脚本。
  • 思考与决策过程:主导智能体运行在云端模型(MiniMax M3)上;本地模型则由我局域网中的一台 GPU 机器提供。这台迷你电脑仅负责托管网关、网站及各类脚本,本身并不运行任何模型。
  • 成本情况:每月费用波动较大;实际开支详情可参阅 我的 AI 智能体实际耗费情况。
  • 最终效果:智能体负责撰写文章、重建网站并模拟整个部署流程;过程中还会执行安全性扫描与链接校验,而发布操作则完全由我亲自决定。

2026年9月现状: 第3步中提到的每周自动刷新功能目前已失效。该功能在7月底的一次备份恢复过程中丢失,至今尚未重新设置。其他功能均可在需要时正常运行。

整体架构概览

该网关将各类模型转化为具备工具使用能力的智能体。这些智能体负责编辑纯文本格式的内容;一个确定性的静态网站生成器则负责构建网站。而唯一通往网络服务器的路径就是那个受控部署脚本。至于模型本身,它们则运行在其他地方:一部分位于云端 API 中,另一部分则存在于我局域网内的 GPU 机器上。

最终实现效果

  • “帮我撰写一篇关于 X 的文章吧”:智能体随即按照指定的格式规范及风格要求,将 Markdown 格式文章写入网站内容目录,并即时生成本地预览版本。
  • “发布该文章吧”:智能体调用部署脚本;默认情况下该脚本仅执行模拟运行。它会详细列出哪些文件会在服务器端发生变更,但绝不会执行任何实际修改操作。真正发布则需要我明确下达 --go 指令才行。
  • “检查一下整个网站状况吧”:另一智能体会扫描是否存在过期日期标记、内容质量欠佳的文章以及失效链接;所有此类检查均具备安全防护措施,确保不会随意发布任何未经审核的内容。

正是这些智能体负责完成各项编辑操作,各类脚本则负责落实规则约束;而我仅需在关键时刻做出决定:是否让某次更改正式上线。

硬件要求:任意 Linux 主机均可使用

我所用的是 CHUWI AuBox Ai365 迷你电脑(具体硬件参数可参阅该文)。由于模型运行在其他位置,网站端所需资源极少:

  • 任何搭载 systemd 的 64 位 Linux 机器,用于服务监控及定时任务调度。
  • Python 3 环境,供静态网站生成器使用;另需 rsync 与 SSH 工具来完成部署操作。
  • 模型资源:既可以是云端 API 密钥,也可以是局域网内运行的模型服务器。若希望所有组件均集中在一台机器上运行,LM Studio、Ollama 或 llama.cpp 所提供的服务器均可兼容 OpenClaw 网关所需的 OpenAI 格式接口。

第1步:配置带有限定权限的智能体网关

该网关能将各类模型转化为具备工具使用能力、可访问文件并执行定时任务的智能体。我选用的是 OpenClaw:它能托管多个命名智能体,将每个智能体指派至相应模型并具备备用模型切换功能;同时它还提供聊天式交互界面。首先需创建一个名为“Webmaster”的智能体,为其配置文件与命令行工具使用权限;随后还需执行两条适用于所有网关的规则:

  • 限制网关仅能在本机内部循环使用,且所有聊天界面均需设置身份验证机制。拥有命令行访问权的智能体若直接暴露于局域网内将存在极大风险。
  • 限定该智能体的工作目录范围仅为网站源码库。它只需编辑网站内容,绝不应触及用户主目录等敏感区域。

我的网关还托管着其他若干智能体(具体信息可参阅 本地 AI 智能体架构详解)。针对本网站而言,最关键的区别在于:那些适用于家庭环境的安全型智能体根本不具备文件或命令行操作权限;如此即便手机落入他人之手,也无法对网站进行任何改动。

当系统本身发生故障(如配置文件出错、网关崩溃、构建程序无法运行等),我会启用云端高性能编程模型来处理问题,该模型将整台主机视为需修复的“患者”。整个处理过程详见 OpenClaw 崩溃后我如何借助 Claude Code 修复系统一文。

第2步:静态网站与受控部署脚本

智能体与 WordPress 这类动态系统极不匹配:数据库、登录认证机制、各类插件及 PHP 组件均属潜在的攻击入口及故障源。相比之下,静态网站更适合智能体操作。整个网站仅由文件夹内的纯文本文件构成;构建过程仅需一条指令即可完成;发布工作也不过是简单的文件复制操作而已。我所使用的生成器代码量不足千行,基于 Jinja2、Markdown 与 YAML 技术实现;Hugo、Eleventy 或 Zola 同样可达成相同效果。真正关键的在于以下规则约定:

  • 内容文件为带元数据信息的 Markdown 格式文档。大语言模型可直接编辑此类文件,生成的差异对比信息亦可直观反映其修改细节。
  • 构建过程具备确定性:输入相同内容必然生成完全相同的网站输出;因此任何输出变化均可追溯到对应的内容改动。在我的机器上,完整构建仅需约两秒时间。
  • 部署路径仅有一条,且该路径由一个内置多重安全机制的脚本掌控,而非依赖智能体自行遵循的一系列指令。

最后一点正是整个系统的核心所在。其操作界面如下:

./deploy.sh preflight   # 检查工具配置、SSH连接状态、网站根目录、清单文件及容量限制
./deploy.sh             # 执行构建并模拟 rsync 操作:仅列出预期变更的文件列表
./deploy.sh --go        # 执行完整构建、服务器端备份、正式发布及验证程序

该脚本确保以下安全特性:

  1. 默认执行模拟运行:不添加任何参数的情况下运行该脚本绝不会改动服务器内容,因此智能体可自由调用它来向我展示即将发布的更新内容。
  2. 绝不会删除任何文件:rsync 运行时未启用 --delete 参数。即便某个智能体误操作导致某页面被新版本覆盖,也绝不可能出现整个网站被抹除的情况。
  3. 先备份后操作:执行 --go 指令时,脚本会在所有写入动作发生前将服务器端的网站根目录打包备份,并保留最近五次备份记录;一旦备份失败,发布流程即刻中止。
  4. 严格的安全拦截机制:所有禁止操作规则均源于清单文件。若清单解析失败、未生成任何排除规则或目标路径仍保留初始占位符值,则脚本会在 rsync 执行前直接终止流程。此外还有硬编码的排除规则保护源代码文件(包括脚本、模板、Markdown文档、YAML配置文件及密钥等)不被误传至服务器;标记为“草稿”的文章同样被自动排除在外;脚本还会校验传输列表以确保没有任何违规内容混入。
  5. 发布后验证程序:脚本会获取网站首页内容并检查其中是否包含构建程序预设的特定标记字符串。仅凭 HTTP 200 响应码尚无法确认安全性,因为旧版托管服务也可能返回相同代码。

以下为该脚本的核心代码节选并作了通用化处理。完整脚本约430行,其余多为各类校验语句及错误提示信息。

DRY=(-n); [ "$GO" -eq 1 ] && DRY=()          # 未指定 --go 时执行模拟运行

# 故障安全机制:若无可解析的清单文件或排除规则,则不进行 rsync 操作  
```bash
m_raw="$(read_manifest)" || die "清单文件解析失败"
mapfile -t M <<< "$m_raw"
[ "${#M[@]}" -gt 3 ] || die "清单文件中未找到任何排除规则"
MARKER="${M[2]}"; EXC=("${M[@]:3}")

HARD=(--exclude='.git/' --exclude='content/' --exclude='templates/'
      --exclude='**/*.py' --exclude='**/*.sh' --exclude='**/*.md'
      --exclude='**/*.yaml' --exclude='**/.env*' --exclude='**/*.key'
      --exclude='**/*.bak*' --exclude='**/*~')

ssh "$DEST" "test -d $WEBROOT" || die "无法访问 Web 根目录"

if [ "$GO" -eq 1 ]; then                      # 覆盖前先备份
  ssh "$DEST" "mkdir -p $WEBROOT-backups \
    && tar czf $WEBROOT-backups/site-$ts.tgz $WEBROOT \
    && test -s $WEBROOT-backups/site-$ts.tgz \
    && echo BACKUP_OK" | grep -q BACKUP_OK || die "备份失败,中止操作"
fi

rsync -az --itemize-changes "${DRY[@]}" \
  "${DRAFT_EXC[@]}" "${HARD[@]}" "${EXC[@]}" \
  ./ "$DEST:$WEBROOT/"                        # 注意:始终不使用 --delete 参数

[ "$GO" -eq 1 ] || { echo "仅执行模拟运行。请使用 --go 参数重新运行以发布。"; exit 0; }

curl -s -L "$SITE_URL" | grep -qF "$MARKER" \
  && echo "标记已出现:新网站已正式上线" \
  || echo "HTTP 响应正常但未找到标记:旧网站仍在提供服务?"

在此基础之上还有一个名为 publish 的封装脚本,它按顺序执行各项步骤并在遇到任何失败时立即中止:先进行包含无效链接与缺失图片检测的构建操作,随后对源代码树执行本地备份,接着对生成的 HTML 内容进行发布前扫描,最后调用带有 --go 参数的部署脚本。

代理程序可随时执行预检与模拟运行。而 --go 参数仅由我本人使用。正是这种不对称机制使得 AI 能够安全地参与到生产环境维护之中。

第三步:设置定时刷新任务(以及为何我目前未启用该功能)

最后一项机制可实现网站的自我维护,目前此步骤仍由我手动执行。systemd 定时器会按预定时间触发,并指示代理程序执行如下任务:审查网站内容、更新陈旧信息、优化质量欠佳的文章、检查内部链接有效性,随后生成待发布版本但暂不正式发布。

# ~/.config/systemd/user/site-refresh.timer
[Unit]
Description=每周网站内容刷新任务
[Timer]
OnCalendar=Sun 06:00
Persistent=true
[Install]
WantedBy=timers.target

该定时器所调用的服务会向网关发送相应指令,随后对代理程序生成的版本执行多项安全检测:

  • 机密信息扫描:检测是否存在 API 密钥、令牌、密码、私有主机名或私有 IP 地址。gitleaks 工具可完成此任务;一旦发现任何可疑内容,整个流程即刻终止。
  • 内容审查:我所使用的方案是通过关键词列表筛查低俗或不合规范的表述;此外另有一个模型依据不同提示词对草稿进行二次审核,从而发现单纯依靠关键词无法识别的问题,例如缺乏事实依据的断言。
  • 构建必须成功:包括链接与资源文件有效性检查;若存在无效图片或内部链接失效的情况,整个流程同样会失败,进而阻止后续部署操作。

仅当上述三项检测全部通过时,系统才会执行模拟发布操作;而真正的发布仍需我手动下达 --go 指令方可生效。若允许定时任务自行发布内容,这些安全机制与“先备份、绝不删除”的脚本设计便可最大限度降低风险,确保即便出现问题也仅表现为“一篇劣质文章短暂上线,随后通过备份恢复”。

此前我的网站一直依此方式运行;直至七月底一次备份恢复操作意外导致该定时任务也随之失效。数周之后我才从某页面上的日期不再更新这一现象察觉异常。这正是所有定时任务的共同隐患:停止运行的定时器与毫无任务可做的正常定时器外观完全一致。 若你也打算构建类似机制,务必确保每次运行均会输出反馈信息,哪怕只是“未发生任何变更”,如此方可避免因无输出而误判为故障。

安全检测机制的实际成效

本网站曾出现两起真实案例,均值得借鉴:

  • 扫描器遗漏特定文件类型:我的机密信息扫描工具未能识别 .zip 格式文件,内容审查模块也未检查下载目录。结果有三份公开发布的压缩包内含有敏感私人信息。最终解决方案是让两类扫描器均能解压并审查压缩包内的全部内容,同时设置大小限制以防止恶意构造的超大压缩包拖慢检测速度。因此评估任何扫描工具时都应关注其无法处理的文件类型。
  • 代理程序生成了虚假信息:某篇关于特定模型供应商的草稿中,自信地声称其产品被另一竞争对手以不同品牌名销售。事实上并无此事;该表述甚至通过了四轮人工审核才被发现。如今所有数值与厂商名称均须附有独立事实依据文档,缺乏依据的表述一律予以剔除。

如何复现此系统

文中所述内容均无专利限制。具体实施步骤如下:

  1. 选择一台 Linux 服务器,并决定模型来源:云端 API、本地模型服务器抑或网络内的 GPU 设备均可。
  2. 安装代理网关(如 OpenClaw 等),将其绑定至本地回环接口;同时配置一名仅拥有网站目录访问权限的管理员代理程序,限制其可使用的文件操作与 Shell 命令范围。
  3. 将现有网站迁移至静态生成器,若尚未使用此类工具则须先行部署。
  4. 编写受控发布脚本:必须实现前述五项安全保障措施。此环节最为关键,建议将具体要求清单及示例代码一并提供给大语言模型以作为设计依据。
  5. 配置各类安全检测机制(机密信息扫描、内容审查、链接有效性检查),均须遵循故障安全原则;若需定时运行,务必保证每次执行均有反馈输出。
  6. 暂时仅允许人工下达 --go 指令,直至整套流程的稳定性得到充分验证。

注意事项

  • 发布脚本必须是唯一发布途径:任何临时手动执行的 rsync 命令正是该脚本旨在防范的风险源头。我的脚本严格排除了源文件与占位符配置文件,因此类一次性操作本不该被允许。
  • 仅收到 HTTP 200 状态码并不等于发布成功:在 WordPress 迁移期间,旧服务器仍持续响应请求,导致所有检测均显示正常,而新网站内容却始终未被启用。因此务必在构建过程中嵌入特定标记并在上线后验证其存在性;反之亦需留意:新版本发布初期服务器可能仍提供缓存的旧版页面,故应稍作延迟后再确认标记是否出现。
  • 代理程序会原样复制给定模板,包括其中的占位符文本。若文章模板中包含示例文字,模型极有可能直接将其作为正式内容发布。为此需将模板中的占位符字符串纳入内容审查范畴。
  • 严禁让生成内容的代理程序自行审核:同一模型配合相同提示词必然产生相似的认知盲区。审核者至少须采用不同的提示词,理想情况下还应选用不同模型参与判定。
  • 定时运行的大语言模型任务须设置超时机制,并默认以“仅暂存、未发布”状态执行。缺乏约束的自动化任务极有可能在周日清晨意外发布不当内容;而预先设置暂存流程仅需额外增加一次人工审核成本即可规避此类风险。
  • 机密信息扫描必须作为流水线环节,而非单纯作为代理程序的指令要求。“绝不可包含敏感信息”这类描述仅属于主观期望,真正有效的控制手段是在最终输出阶段执行故障安全型扫描。

相关链接:我的 AI 代理系统架构、各类 AI 代理的实际运行成本分析、OpenClaw 故障及其修复过程、承载该系统的迷你 PC 配置详情、利用相同代理程序构建的第二网站实例以及 使用 AI 改造 WordPress 的早期实践。


← 更多AI 与本地 LLM