在 Railway 上部署 agentmemory:持久卷、HMAC 认证与 Viewer 访问完整指南
【免费下载链接】agentmemory#1 Persistent memory for AI coding agents based on real-world benchmarks项目地址: https://gitcode.com/GitHub_Trending/age/agentmemory
本文基于 agentmemory 官方部署模板 deploy/railway/README.md,系统讲解如何在 Railway 平台上以单个服务 + 持久卷的方式运行 agentmemory:包括 Dashboard 与 CLI 两条部署路径、首启 HMAC 密钥的生成与捕获、/agentmemory/livez健康检查、3113 端口 Viewer 的安全访问方案、密钥轮换与/data卷备份。读完本文,你将掌握一套完整、可复现、可迁移的 agentmemory 托管部署流程,并理解其背后的容器化实现原理。
部署方案概览:单服务 +/data持久卷
agentmemory 在 Railway 上的部署采用单服务模板:一个公开的 HTTPS 端点对外提供 REST API(端口 3111),一个 Railway Volume 挂载在/data上承载记忆数据。其核心设计可归纳为以下几点:
- 公开端点:REST API 通过 HTTPS 暴露在端口
3111,由 Railway 边缘代理终结 TLS。 - 持久化存储:Railway Volume 挂载到
/data,存放 memories(记忆)、BM25 索引(remember-bm25-index相关检索数据)以及 stream backlog(流式消息积压)。 - 健康检查:Railway 对
/agentmemory/livez进行探测,该端点由 agentmemory 服务端源码中的api::liveness函数注册(见 src/triggers/api.ts),返回{"status":"ok", ...}。 - 首启密钥:HMAC bearer 密钥在容器首次启动时生成,并持久化到
/data/.hmac(权限chmod 600);操作者只需在部署日志中读取一次,之后每次重启都从文件加载,不再重复打印。 - 强制挂载校验:部署配置中设置了
requiredMountPath: /data,若没有在/data挂载卷,Railway 会拒绝启动服务——因此首次部署前必须先通过面板创建卷。
这套模板与仓库中其他平台的模板(fly.io、Render、Coolify)共享同一套保证机制:卷统一挂载/data、HMAC 首启生成、仅公开 3111、TLS 由平台边缘代理终结,详见 deploy/README.md。
部署配置逐项解读:railway.json 与 Dockerfile
railway.json:Railway 的 Config-as-Code
deploy/railway/railway.json 是 Railway 的配置文件(使用https://railway.com/railway.schema.json作为 JSON Schema),内容如下:
{ "$schema": "https://railway.com/railway.schema.json", "build": { "builder": "DOCKERFILE", "dockerfilePath": "deploy/railway/Dockerfile" }, "deploy": { "numReplicas": 1, "healthcheckPath": "/agentmemory/livez", "healthcheckTimeout": 30, "restartPolicyType": "ON_FAILURE", "restartPolicyMaxRetries": 10, "requiredMountPath": "/data" } }关键字段含义:
| 字段 | 值 | 作用 |
|---|---|---|
builder | DOCKERFILE | 使用 Dockerfile 构建,而非 Nixpacks 等自动检测 |
dockerfilePath | deploy/railway/Dockerfile | 指定 Dockerfile 相对仓库根目录的路径 |
numReplicas | 1 | 单副本运行(记忆数据存于卷上,多副本需要额外处理写入一致性) |
healthcheckPath | /agentmemory/livez | 健康检查端点,对应源码中的 liveness 触发器 |
healthcheckTimeout | 30 | 健康检查超时 30 秒,为冷启动预留约 3 倍余量 |
restartPolicyType | ON_FAILURE | 仅在失败时重启 |
restartPolicyMaxRetries | 10 | 失败重启最大重试 10 次 |
requiredMountPath | /data | 强制要求/data挂载卷,未挂载则拒绝启动 |
Dockerfile:双阶段构建与版本锁定
deploy/railway/Dockerfile 采用多阶段构建,从官方iiidev/iii镜像拷贝 iii 引擎二进制,再从 npm 安装@agentmemory/agentmemory:
ARG III_VERSION=0.11.2 FROM iiidev/iii:${III_VERSION} AS iii-image FROM node:22-slim ARG AGENTMEMORY_VERSION=0.9.29 ARG III_VERSION=0.11.2 ARG III_SDK_VERSION=0.11.2 RUN apt-get update \ && apt-get install -y --no-install-recommends openssl ca-certificates tini gosu curl \ && rm -rf /var/lib/apt/lists/* COPY --from=iii-image /app/iii /usr/local/bin/iii # 在独立前缀安装 agentmemory,以便 package.json 的 overrides 字段 # 将 iii-sdk 锁定到与引擎匹配的版本 WORKDIR /opt/agentmemory RUN printf '{"name":"agentmemory-deploy","version":"1.0.0","private":true,"overrides":{"iii-sdk":"%s"}}\n' "${III_SDK_VERSION}" > package.json \ && npm install "@agentmemory/agentmemory@${AGENTMEMORY_VERSION}" --omit=optional --no-fund --no-audit \ && ln -s /opt/agentmemory/node_modules/.bin/agentmemory /usr/local/bin/agentmemory ENV AGENTMEMORY_III_VERSION=${III_VERSION} \ TINI_SUBREAPER=1 COPY --chmod=0755 entrypoint.sh /usr/local/bin/agentmemory-entrypoint.sh EXPOSE 3111 ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/agentmemory-entrypoint.sh"]其中值得注意的工程细节:
- iii-sdk 版本锁定:注释说明了为什么要用本地前缀安装——agentmemory 依赖声明为
^0.11.2(caret 范围),会解析到 0.11.6,而该版本要求新的 sandbox-everything worker 模型,agentmemory CLI 尚未适配;npm install -g会忽略overrides字段,因此通过本地package.json的overrides将iii-sdk钉死在 0.11.2。 - 系统依赖:
openssl(生成 HMAC 密钥)、tini(作为 PID 1 的 init 进程,负责子进程回收)、gosu(权限降级)、curl(容器内自检)。 - 版本 Build Args:
AGENTMEMORY_VERSION(默认 0.9.29)与III_VERSION(默认 0.11.2)均可通过 Railway 面板的Variables标签页覆盖,用于锁定特定发布版本。
部署路径一:Railway Dashboard(面板部署)
- 在 Railway 面板点击Deploy from GitHub,选择
rohitg00/agentmemory仓库。 - 在服务的Settings中,将Config-as-Code Path设置为
deploy/railway/railway.json。Railway 会从该配置读取 Dockerfile 路径(deploy/railway/Dockerfile)。 - 打开服务的Volumes标签页,添加一个挂载到
/data的卷。注意:Railway 的卷是在面板中配置(或通过railway volume add命令),不会写进railway.json。 - 点击Deploy开始部署。
由于requiredMountPath: /data的存在,首次部署前必须先在面板创建卷,否则服务无法启动。这正是该配置项的意义所在——它把"忘记挂载卷"这一最常见错误变成启动期硬失败,而不是运行期数据丢失。
部署路径二:Railway CLI(命令行部署)
# 安装 CLI 后登录 railway login railway init # 关联一个新项目 railway up --service agentmemory # 构建并部署 railway volume add --service agentmemory --mount /data # 附加持久卷 railway redeploy # 带卷重启流程逻辑与面板一致:railway up构建并部署,railway volume add --mount /data挂载持久卷,railway redeploy让服务以挂载卷的状态重启。
捕获 HMAC 密钥:一次性的安全凭证交接
agentmemory 使用 HMAC bearer token 保护 API(源码中通过timingSafeCompare进行恒定时间比较,见 src/auth.ts)。部署成功后,打开服务的Deploy Logs:
railway logs --service agentmemory | grep AGENTMEMORY_SECRET=你会看到恰好一行形如AGENTMEMORY_SECRET=<64 hex chars>的输出,将其复制到客户端环境变量中。该密钥只在首次启动时打印一次,后续启动均从/data/.hmac加载,不再重复输出。
这一行为由入口脚本 deploy/railway/entrypoint.sh 实现:首次启动时检测/data/.hmac不存在或为空,便用openssl rand -hex 32生成 64 个十六进制字符的密钥,以umask 077+chmod 600写入卷,再打印到 stdout:
if [ ! -s "$HMAC_FILE" ]; then SECRET="$(openssl rand -hex 32)" umask 077 printf '%s\n' "$SECRET" > "$HMAC_FILE" chmod 600 "$HMAC_FILE" echo "AGENTMEMORY_SECRET=$SECRET" fi验证部署:livez 健康检查与认证调用
健康检查端点是部署是否就绪的权威信号:
curl https://<your-service>.up.railway.app/agentmemory/livez # {"status":"ok"}从源码看,该端点由api::liveness函数注册(src/triggers/api.ts),响应体为{"status":"ok"},并附带viewerPort、streamsPort等实例元数据(instanceInfo),用于让 viewer 与流服务通过服务端解析端口而非端口算术,避免绑定回退端口时产生漂移。
带认证的真实调用则需要客户端在请求头中携带 bearer:
Authorization: Bearer <secret>服务端校验逻辑位于 src/triggers/api.ts:读取authorization头,与Bearer ${secret}做恒定时间比较,不匹配则返回401 {"error":"unauthorized"}。CLI 侧则通过AGENTMEMORY_SECRET环境变量注入请求头(见 src/cli.ts)。
Viewer 访问:3113 端口保持容器内部
Railway 只暴露服务PORT环境变量映射的单一公网端口(本模板映射到 3111),Viewer 默认绑定在容器 localhost 的3113端口。railway ssh是交互式 shell,不支持-L风格的端口转发,因此要访问 Viewer 有以下途径。
快速容器内检查:
railway ssh --service agentmemory # 容器内执行: curl http://localhost:3113浏览器访问方案 A(TCP Proxy,推荐):在 Railway 面板打开服务的Settings → Networking,为容器端口3113添加TCP Proxy。Railway 会返回一对公网 host/port,可直接在浏览器访问。务必搭配 HMAC bearer-auth 头使用,避免 Viewer 被匿名访问。
浏览器访问方案 B(容器内 sshd):在镜像中加入openssh-server进程,由entrypoint.sh在固定端口启动它,通过第二个 Railway TCP Proxy 暴露该端口,然后从笔记本使用原生 SSH 隧道:
ssh -L 3113:localhost:3113 <proxy-host> -p <proxy-port>方案 B 更重,大多数用户选择方案 A。从源码看,Viewer 默认只信任 loopback Host(isLoopbackHost校验见 src/viewer/server.ts),并内置 CSP 与随机 nonce(src/auth.ts),因此在暴露时保持 Host 头白名单与认证头是安全底线。
轮换 HMAC 密钥
railway ssh --service agentmemory rm /data/.hmac exit railway redeploy --service agentmemory railway logs --service agentmemory | grep AGENTMEMORY_SECRET=删除卷上的/data/.hmac后重启,入口脚本会再次走首启逻辑生成新密钥并打印。更新所有客户端后,旧 token 立即失效。这正是"密钥持久化在卷上而非环境变量"设计的好处:轮换只需删除文件并重启,无需改动平台配置。
备份与恢复/data
Railway 卷不会自动快照,因此主动备份是数据安全的关键。整体备份(打包整个/data):
railway ssh --service agentmemory -- "tar czf - /data" > agentmemory-$(date +%Y%m%d).tar.gz恢复到全新卷:
cat agentmemory-YYYYMMDD.tar.gz | railway ssh --service agentmemory -- "tar xzf - -C /" railway redeploy --service agentmemory这套tar备份/恢复流程与仓库中其他平台的迁移方式一致——所有模板共用同一套/data布局,平台间迁移本质就是对/data做一次 tar 再导入(见 deploy/README.md 的"Pick a platform"说明)。
成本地板与出口流量
- Hobby 计划:每月固定 $5,含 $5 用量。
- 典型用量:agentmemory 空闲 + 1 GB 卷,在最小实例上每月约消耗 $3–$6,大多数用户停留在 $5 地板附近。
- 出口流量:套餐内额度用尽后按 $0.10/GB 计费。
具体费率以 Railway 官方定价页为准(原文给出 https://railway.com/pricing 供查阅最新费率卡)。
已知注意事项与生产建议
- 卷无自动快照:务必自行备份(见上文)或使用 Railway 面板的手动快照功能。
- 每次部署都会在 Railway 构建器上重新构建:首次部署约 2 分钟,之后的重新构建因层缓存而较快。如需锁定特定发布版本,请在服务的Variables标签页钉住
AGENTMEMORY_VERSION/III_VERSION构建参数(对应 Dockerfile 中的 ARG)。 - 入口脚本的运行期行为(deploy/railway/entrypoint.sh)值得理解:它以 root 启动,依次完成三件事——用部署调优版配置覆盖 npm 打包的
iii-config.yaml(将 HTTP 绑定从127.0.0.1改为0.0.0.0、数据路径从相对./data改为绝对/data、配置 CORS 允许localhost:3111/3113、将 state/stream 存储落到/data下的state_store.db与stream_store)、把平台挂载的 root 属主卷 chown 给运行时用户node、在首启生成 HMAC 密钥;随后通过gosu降权为无特权node用户执行agentmemory。TINI_SUBREAPER=1保证进程树在容器内被正确回收。 - 可选能力解锁:模板开箱即可运行,无需任何 LLM/embedding 密钥——搜索回退为 BM25-only 模式,合成(零 LLM)压缩也能保持记忆可索引。若要解锁 LLM 压缩与混合(BM25 + vector)召回,可在 Railway 的Variables / Environment标签页添加
ANTHROPIC_API_KEY、GEMINI_API_KEY、OPENROUTER_API_KEY、OPENAI_API_KEY、VOYAGE_API_KEY之一,并按需开启AGENTMEMORY_AUTO_COMPRESS=true与AGENTMEMORY_INJECT_CONTEXT=true(默认均为关闭,属保守策略,确认配额可承受后再开启)。
小结
本文完整覆盖了 agentmemory 在 Railway 上的部署全流程:通过railway.json的 Config-as-Code 声明构建与健康检查、理解Dockerfile的版本锁定与双阶段构建、掌握 Dashboard 与 CLI 两条部署路径、捕获一次性 HMAC 密钥、验证 livez、通过 TCP Proxy 或 sshd 访问 Viewer、轮换密钥、备份恢复/data,以及成本与已知注意事项。这套部署方案与仓库中 fly.io、Render、Coolify 模板共享相同的数据布局与认证模型(deploy/README.md),后续如需跨平台迁移,只需对/data做 tar 打包并重新导入即可。
【免费下载链接】agentmemory#1 Persistent memory for AI coding agents based on real-world benchmarks项目地址: https://gitcode.com/GitHub_Trending/age/agentmemory
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考