首页
/ Headroom 持久化安装实战:用 headroom install 把 8787 端口常驻代理变成可管理的本地运行时

Headroom 持久化安装实战:用 headroom install 把 8787 端口常驻代理变成可管理的本地运行时

2026-09-04 11:40:17作者:傅爽业Veleda

本篇指南基于 Headroom 仓库的 persistent-installs 文档展开,讲清楚 headroom install 子系统的三大持久化预设(persistent-service / persistent-task / persistent-docker)、--scope--providers 的完整参数语义、部署清单(manifest)的存储位置与结构,以及 headroom wrap 如何自动复用或恢复常驻部署。读完并对照仓库源码后,你将掌握三种常驻运行时的选型依据、每个 CLI 命令的底层行为,以及 manifest 原子写入与损坏恢复等工程细节。

从临时代理到常驻运行时:persistent install 要解决什么问题

此前运行 Headroom 只有两种方式:临时起一个 headroom proxy(进程退出即消失),或 headroom wrap ... 包一层工具会话(代理生命周期与会话绑定)。这两种方式都要求代理在需要时"恰好活着"。

Persistent Installs 让 Headroom 以持久本地运行时的形式安装到机器上:受支持的编码工具(Claude Code、Codex、Copilot 等)持续访问 http://127.0.0.1:8787 上一直开着的代理,而 headroom wrap ...复用或恢复这个部署,而不是再启一个第二套临时代理。文档明确建议:当你希望工具长期对接一个 always-on 代理时,使用 Python 原生的 headroom install CLI。

整个子系统位于 headroom/install/ 包内,从源码结构看,各模块职责划分如下:

模块 职责
models.py 预设、运行时、supervisor、作用域等枚举与 DeploymentManifest 数据类
planner.py 目标探测、参数解析、生成规范化 manifest
state.py manifest 的原子写入、加载与删除
paths.py 部署状态目录、runner 脚本路径、各工具的配置文件路径
supervisors.py systemd / launchd / 计划任务等 supervisor 的渲染与启停
providers.py 对工具配置的可逆修改(mutation)与应用/回滚
runtime.py 前台/后台运行、端口探测、健康等待、Docker 启动
health.py readyz / health 端点探测

对应的回归测试位于 tests/test_install/,覆盖 planner、state、supervisors、runtime、health、providers、native installers 等每个模块(如 test_planner.pytest_supervisors.py)。

运行时矩阵:先选对模式,再执行命令

原文档给出的运行时矩阵是选型的核心依据,完整继承如下:

Mode What stays running Primary entrypoint
Persistent Service Native background service headroom install apply --preset persistent-service
Persistent Task Scheduled watchdog + on-demand runner headroom install apply --preset persistent-task
Persistent Docker Restartable Docker container headroom install apply --preset persistent-docker
On-Demand CLI (Python) Nothing after command exits headroom proxy
On-Demand CLI (Docker) Nothing after container exits Docker-native wrapper / compose CLI
Wrapped (Python) Proxy lasts for wrapped session headroom wrap ...
Wrapped (Docker) Containerized proxy + host tool session Docker-native wrapper

三种持久化预设的区别本质在于"谁来保证代理活着":

  • persistent-service 交给操作系统原生服务管理器(Linux 上是 systemd unit,macOS 上是 launchd LaunchAgent);
  • persistent-task 用定时任务(cron / 计划任务)跑一个 watchdog,周期性探测并按需拉起,适合不允许注册系统服务的场景;
  • persistent-docker 则把存活责任完全交给 Docker 的 restart policy,不引入额外 OS 层监督。

快速上手:三种预设的最短命令

本机持久服务

headroom install apply --preset persistent-service --providers auto
headroom install status

这条命令在当前机器上安装一个后台服务,应用"持久化工具接线"(即把代理端点写进各工具配置),并保证 8787 端口上的代理持续健康。

从源码看,apply 的完整链路是:cli/install.py 中的 install 命令组接收参数 → planner.pybuild_manifest() 生成 DeploymentManifeststate.pysave_manifest() 落盘 → supervisors.pyinstall_supervisor() 注册 supervisor → runtime.pywait_ready() 等待 readyz 通过。

一个值得注意的平台细节:在 Windows 上,build_manifest() 会把 persistent-service 静默降级为 persistent-task(见 planner.py 的注释)——因为 Python runner 是普通控制台进程,无法实现 Windows SCM 协议协议,sc.exe create 注册的服务永远无法启动(SCM error 1053),而任务计划程序既能开机自启又能周期健康恢复,因此成为 Windows 上的有效预设(对应 issue #2552)。

持久看门狗任务

headroom install apply --preset persistent-task --providers manual --target claude --target codex

这条命令安装的是"定时恢复路径"而非传统常驻服务。从 supervisors.py 看,apply 会为每个 profile 渲染两个脚本:

  • run-headroom.sh:前台 runner,执行 headroom install agent run --profile <profile>
  • ensure-headroom.sh:watchdog 脚本,执行 headroom install agent ensure --profile <profile>,由 cron/计划任务周期性调用,发现代理挂了就拉起。

Windows 上对应的是 run-headroom.ps1 / run-headroom.cmdensure-headroom.ps1 / ensure-headroom.cmd(见 paths.py)。

持久 Docker

headroom install apply --preset persistent-docker --scope user --providers auto

这条命令让 Docker 的 restart policy 取代 OS supervisor。源码中有个针对该预设的实现细节:开启 --memory 时,Python 运行时会显式传 --memory-db-path <宿主路径>,但 Docker 运行时会被刻意省略该参数(见 planner.py 注释)——因为容器内 HOME 是 /tmp/headroom-home,宿主的 ~/.headroom 只是挂载进来,直接传宿主绝对路径会导致 SQLite 打不开、/readyz 恒 503、部署超时回滚(issue #2803);省略后代理在容器工作目录下解析 DB,恰好落在同一个绑定挂载文件上。

另外,如果你使用的是 Docker 原生宿主 wrapper(而非 Python 安装),也可以直接从已安装的 wrapper 上对 persistent-docker 预设执行 headroom install apply|status|start|stop|restart|remove。但注意边界:service/task 安装以及 provider/user/system 的变更流程仍属于 Python 原生 CLI 的职责

命令面:六个生命周期子命令

headroom install apply
headroom install status
headroom install start
headroom install stop
headroom install restart
headroom install remove

文档说明:apply创建或更新一个具名部署档案(profile),把清单存到 ~/.headroom/deploy/<profile>/manifest.json,应用可逆的配置变更,然后启动所选运行时。

源码对这条命令的补充细节:

  • profile 命名有校验paths.pyvalidate_profile_name() 要求 profile 只含 [A-Za-z0-9._-],且不允许 . / ..,防止路径穿越;
  • 目录布局:每个 profile 一个目录,除 manifest.json 外还放 runner.log(运行日志)、runner.pid(前台进程 pid)、各平台 runner/watchdog 脚本(见 paths.py);
  • 显式 --profile 不容错cli/install.py 中,如果命令行显式传了 --profile 但该 profile 不存在,命令会原样报错而不是悄悄转向其他已安装 profile——stop/restart/remove 这类破坏性命令绝不允许误伤别的部署。只有 --profile 缺省时才走恢复回退(读 HEADROOM_DEPLOYMENT_PROFILE 环境变量或唯一的已安装 profile);
  • remove 的行为:先 revert_mutations() 回滚对工具配置的修改,再 remove_supervisor() 注销 supervisor,最后 delete_manifest() 删除整个 profile 目录(见 state.pyshutil.rmtree)。

Presets 与 Runtime kinds

Presets

  • persistent-service -> 原生服务监督器
  • persistent-task -> 定时看门狗 / 恢复监督器
  • persistent-docker -> Docker restart policy,无额外 OS 监督器

这与 models.py 中的枚举一一对应:InstallPresetSupervisorKindservice / task / none)。预设到 supervisor 的映射逻辑在 build_manifest() 里:service 预设产生 SupervisorKind.SERVICE,task 预设产生 TASK,Docker 预设产生 NONE(由容器引擎负责重启)。

supervisor 的实际产物(从 supervisors.py 可见):

  • Linuxpersistent-service 渲染 systemd unit,scope=user 时放在 ~/.config/systemd/user/headroom-<profile>.servicescope=system 时放在 /etc/systemd/system/;unit 内容为 Restart=on-failureRestartSec=5ExecStart 指向渲染出的 run-headroom.sh
  • macOS:渲染 launchd plist 并通过 launchctl bootstrap 加载。源码还处理了一个真实的竞态:launchctl bootout 之后立刻 bootstrap 同一 label 可能在数秒内返回 EIO,因此 _bootstrap_with_retry() 会重试最多 30 次(每次 0.5 秒,约 15 秒)以扛过 launchd 的释放窗口(见 supervisors.py)。

Runtime kinds

  • --runtime python:直接运行 headroom proxy
  • --runtime docker:在 Docker 内运行 Headroom,但部署本身仍由本机管理

persistent-docker 预设,runtime 永远是 Docker。DeploymentManifest 中 Docker 相关默认值可在 models.py 看到:镜像 ghcr.io/headroomlabs-ai/headroom:latest、容器名 headroom-<profile>、健康检查 URL http://127.0.0.1:8787/readyz

配置作用域(Scope):改到哪里、改多少

Scope What changes
provider Tool-specific config surfaces where Headroom can make a precise reversible edit
user User-level shell or environment surfaces
system Machine-wide shell or environment surfaces

paths.py 可以看到各 scope 实际落笔的文件:

  • user~/.bashrc~/.zshrc~/.profile(可写入持久环境块的文件列表);
  • system:Linux 上是 /etc/profile.d/headroom.sh;macOS 上是 /etc/profile/etc/zprofile/etc/bashrc
  • provider:直接编辑各工具自己的配置文件。

当前 Provider scope 支持的直接适配器

文档强调 provider scope 是有意保守的,当前的直接适配器为:

  • Claude Code -> ~/.claude/settings.jsonenv
  • Codex -> ~/.codex/config.toml 中的托管块(managed block)
  • OpenClaw -> 复用既有的 wrap openclaw / unwrap openclaw 流程

对于 Copilot、Aider、Cursor 以及更宽泛的 env 驱动配置,建议用 --scope user--scope system

与文档的一个差异值得注意:源码里 PROVIDER_SCOPE_TARGETS 实际包含 claude、codex、openclaw、opencode 四个目标(见 planner.py),且 paths.py 为 OpenCode 提供了配置路径解析(优先 OPENCODE_CONFIG 环境变量,其次 ~/.config/opencode/opencode.jsoncopencode.json)。也就是说 OpenCode 已具备 provider 级直接适配能力,只是 Wiki 文档尚未同步更新这一条。apply 对 provider scope 下不支持的 target 会明确报错列出,例如 Provider scope supports only claude, codex, openclaw, and opencode(见 planner.py)。

Provider 选择:auto / all / manual

Option Meaning
--providers auto Detect supported tools on the host and configure the best available defaults
--providers all Configure all known targets
--providers manual --target ... Configure only the named tools
headroom install apply --providers auto
headroom install apply --providers all --scope user
headroom install apply --providers manual --target claude --target copilot

models.pyToolTarget 枚举看,当前支持的全部 target 为:claude、copilot、codex、aider、cursor、grok_build、grok、openclaw、opencode

auto 模式的探测机制在 planner.pydetect_targets():对每个 target 用 shutil.which() 查可执行文件是否在 PATH 上;若一个都没探测到,resolve_targets() 会回退到默认集合 claude + codex(provider scope 下再额外去掉 copilot,见 planner.py)。

生成 manifest 时,每个 target 会得到一份专属环境变量(build_install_target_envs()),代理自身的基础环境则固定写入 HEADROOM_PORTHEADROOM_HOST=127.0.0.1HEADROOM_MODEHEADROOM_BACKEND、显式的 HEADROOM_TELEMETRY=on|off(见 planner.py)。另有两条自动派生规则:

  1. 若目标只含 Grok / Grok Build 且没有共享该代理的 OpenAI 系工具,自动设置 OPENAI_TARGET_API_URL 指向 xAI 端点(从 providers/grok/runtime.py 引入 DEFAULT_API_URL);
  2. --env 显式传入的变量最后应用,可覆盖上述所有自动派生默认值。

健康端点与 wrap 的复用/恢复行为

持久化部署发布与临时代理运行完全相同readyzhealth 端点。当代理经由 install 子系统启动时,/health 额外暴露部署元数据:

{
  "deployment": {
    "profile": "default",
    "preset": "persistent-service",
    "runtime": "python",
    "supervisor": "service",
    "scope": "user"
  }
}

这些字段恰好对应 DeploymentManifest 的同名属性(profile / preset / runtime_kind / supervisor_kind / scope),说明 /health 是把 manifest 中相应字段原样透出,方便运维端判断"这个 8787 端口是谁在管"。

Python 原生的 headroom wrap ... 流程会先检查请求端口上是否存在匹配的持久化部署,再决定是否新起临时代理;如果已安装的部署存在但处于停止或不健康状态,它会先尝试恢复它。探测逻辑基于 health.pyprobe_ready() / probe_json(),等待逻辑在 runtime.pywait_ready(),对 /readyz 轮询直到 200。

需要明确的边界:Docker 原生宿主 wrapper 尚不会自动复用或恢复持久化 profile——除非显式 --no-proxy,否则它总是启动一个全新的代理容器。

Docker 原生路径的关系与 compose 管理

Docker 原生宿主 wrapper 与 Python install CLI 解决的是运行时故事的不同层

  • Docker-Native Install -> 容器化的按需 CLI、宿主工具的 wrap 流程,以及 Docker 原生的 persistent-docker 生命周期命令;
  • headroom install ... -> 完整的持久 service / task / Docker 生命周期管理,包含 provider/user/system 变更。

对于不依赖 Python 的持久 Docker 工作流,使用 docker/docker-compose.native.yml 中 compose 管理的代理路径:

export HEADROOM_HOST_HOME="$HOME"
export HEADROOM_WORKSPACE="$PWD"
docker compose -f docker/docker-compose.native.yml up -d proxy

这样可以保持 localhost:8787 稳定,并在容器退出时自动重启代理。

注意HEADROOM_WORKSPACE(compose 文件使用的宿主侧 bind-mount 源目录)与 HEADROOM_WORKSPACE_DIR(容器内 Headroom 状态根的规范变量)不是同一个变量。两者都保留;compose 文件会自动设置后者。完整的 bucket 模型见 Filesystem Contract

清单持久化的可靠性细节

manifest.json 是整套安装系统的"事实来源",state.py 对它做了三层保护:

  1. 原子写入save_manifest() 经由 _atomic_write_text() 先把 payload 写入同目录临时文件(mkstemp),flush + fsync 后再 os.replace() 原子改名。即使写入中途被 SIGKILL、OOM 或断电打断,磁盘上也只会留下旧文件或完整新文件,绝不出现被截断的 manifest;只读文件系统则降级为告警而非崩溃。
  2. 损坏清单的优雅失败load_manifest() 对解析失败(部分写入、手改、schema 漂移)抛出类型化的 ManifestError,而不是裸 traceback——因为所有 install 生命周期命令以及自动执行的 init hook ensure 路由都要经过这里;CLI 层会把它转成可读的报错(见 cli/install.py)。
  3. 旧镜像仓库自动迁移:旧 manifest 若仍钉在已停止更新的 ghcr.io/chopratejas/headroom 镜像上,加载时会被自动重写到组织仓库 ghcr.io/headroomlabs-ai/headroom 并保留 tag(issue #2426,见 state.py)。

与文档配套的其他资源

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
982
502
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384