code-server 部署到 Coder 工作区:install.sh 启动脚本、healthz 健康检查与官方模块方案
本文以 docs/coder.md 为主体,讲解如何在 Coder 工作区的 Terraform 模板中部署 code-server。读完后你可以掌握两套落地方案:一是在 coder_agent 的 startup_script 中用官方安装脚本拉起服务,并配置 coder_app 的 /healthz 健康检查;二是直接引用官方发布的 Coder 模块。同时会深入源码说明 --auth none、--port 参数的含义、/healthz 端点的真实实现以及心跳(heartbeat)机制如何避免健康检查“误伤”活跃状态判定。
为什么把 code-server 跑在 Coder 工作区里
Coder 的每个 workspace 由一个或多个 coder_agent 进程负责执行初始化脚本并代理端口。code-server 作为“浏览器中的 VS Code”,只需要在 agent 容器内启动一个监听本地端口的 HTTP 服务,再通过 coder_app 资源把 localhost:13337 暴露为工作区应用即可。docs/coder.md 给出的正是这条最典型的路径:agent 装服务、app 做路由与探活、Terraform 声明式管理三者。
方案一:startup_script 中用 install.sh 安装并启动
官方推荐在模板中使用仓库根目录提供的 install.sh 脚本。docs/coder.md 中的完整模板如下:
resource "coder_agent" "dev" {
arch = "amd64"
os = "linux"
startup_script = <<EOF
#!/bin/sh
set -x
# install and start code-server
curl -fsSL https://code-server.dev/install.sh | sh -s -- --version 4.8.3
code-server --auth none --port 13337 &
EOF
}
resource "coder_app" "code-server" {
agent_id = coder_agent.dev.id
slug = "code-server"
display_name = "code-server"
url = "http://localhost:13337/"
icon = "/icon/code.svg"
subdomain = false
share = "owner"
healthcheck {
url = "http://localhost:13337/healthz"
interval = 3
threshold = 10
}
}
install.sh 的工作方式与 --version 参数
安装脚本支持 --version X.X.X 指定固定版本(模板中固定为 4.8.3,保证工作区可复现),也支持 --edge 安装最新 edge 版。从 install.sh 源码看,其核心行为包括:
- 安装方式选择:
--method detect(默认)会按发行版选择包管理器——Debian/Ubuntu 走 deb 包,Fedora/CentOS/RHEL/openSUSE 走 rpm 包,Arch 走 AUR,FreeBSD/Alpine 走 npm,macOS 优先 Homebrew,其余系统直接从 GitHub Release 拉取;--method standalone则强制把发行包解压到--prefix(默认~/.local)。 - 架构约束:Release 只为 Linux 的 amd64/arm64 和 macOS 的 amd64 构建,detect 模式在无匹配 Release 时会回退到 npm 安装,standalone 模式则会报错。这解释了模板里
coder_agent的arch = "amd64"写法——与工作区架构保持一致才能命中预构建产物。 - 下载缓存:脚本会把所有下载的资产缓存在
~/.cache/code-server,工作区重启时的二次安装会更快。
--auth none 与 --port 13337:启动参数的源码依据
在 Coder 场景下关闭 code-server 自身的认证是有意为之——访问控制交给 Coder 的 workspace 代理层(share = "owner" 表示只有 workspace 属主可访问应用),code-server 不再重复要求密码。参数含义可从源码确认:
--auth:src/node/cli.ts 中定义了AuthType枚举,仅有password与none两个取值;src/node/cli.ts 的setDefaults显示,若不显式指定,默认值是password。因此在 Coder 模板中必须显式写--auth none,否则工作区会多出一层需要密码的登录页。--port:属于已被--bind-addr取代但仍可用的参数(见 src/node/cli.ts 注释 “These two have been deprecated by bindAddr”),--port 13337即监听 13337 端口。也可以用--bind-addr 127.0.0.1:13337或环境变量$PORT覆盖,模板中选用--port是因为它更直观且与coder_app的url一一对应。- 启动命令末尾的
&让 code-server 在后台运行,避免阻塞startup_script中后续可能的步骤。
coder_app 各字段的作用
url = "http://localhost:13337/":Coder 在该 agent 容器内代理此地址,浏览器访问的工作区应用实际由 Coder 路由进来,这也是为什么--auth none是安全可行的。subdomain = false:以路径方式挂载(如/code-server/),而不是独立子域名;对需要 base-path 适配的场景,code-server 本身带有对代理路径的处理补丁(见 patches/base-path.diff)。share = "owner":只有 workspace 属主能打开该应用,弥补了--auth none取消认证后的访问控制缺口。healthcheck:Coder 每隔interval(3 秒)探测一次url,连续threshold(10 次)失败才判定应用不可用。选择/healthz而非根路径不是随意的,原因在于下面的实现细节。
/healthz 端点:源码级的健康检查机制
code-server 的 /healthz 路由在 src/node/routes/index.ts 中挂载,处理逻辑位于 src/node/routes/health.ts:它返回一个 JSON,包含 status(alive 或 expired)和 lastHeartbeat 时间戳:
router.get("/", (req, res) => {
res.json({
status: req.heart.alive() ? "alive" : "expired",
lastHeartbeat: req.heart.lastHeartbeat,
})
})
而 alive() 的判定来自心跳模块 src/node/heart.ts:code-server 通过一个本地心跳文件记录活动,heartbeatInterval 为 60000 毫秒,alive() 的语义是“距上次心跳不足 60 秒”。任何真实用户请求都会触发 heart.beat() 刷新心跳。
关键的排除逻辑在 src/node/routes/index.ts:
// /healthz|/healthz/ needs to be excluded otherwise health checks will make
// it look like code-server is always in use.
if (!/^\/healthz\/?$/.test(req.url)) {
heart.beat()
}
即健康检查请求本身不刷新心跳。这样设计的原因可以推断为:Coder 每 3 秒一次的探测如果计入“使用量”,会让 status 永远是 alive,健康检查就失去了反映“用户是否真的在用编辑器”的意义。对部署者而言的实用结论是:当 Coder 报告应用不健康、或你直接 curl 该端点看到 expired 时,说明 60 秒内没有任何真实用户活动,这可用于判断空闲工作区;而 HTTP 层探活(进程是否存活、端口是否监听)由 Coder 的 interval/threshold 机制独立保障。对应行为在单元测试 test/unit/node/routes/health.test.ts 中有覆盖。
方案二:使用官方 Coder 模块
对于不想在模板里手写安装命令的场景,Coder 官方在模块 registry 中发布了 code-server 模块,模板中只需引用:
module "code-server" {
source = "registry.coder.com/modules/code-server/coder"
version = "1.0.5"
agent_id = coder_agent.example.id
extensions = ["dracula-theme.theme-dracula", "ms-azuretools.vscode-docker"]
}
其中 extensions 参数支持按 VS Code 扩展 ID 批量预装扩展。这一能力对应 code-server CLI 的 --install-extension 选项:src/node/cli.ts 说明其接受 ${publisher}.${name} 形式的扩展标识符或 vsix 文件,并可追加 @${version} 指定版本(例如 vscode.csharp@1.2.3)。模块本质上就是把“install.sh 安装 + 启动 + coder_app 声明 + 扩展预装”打包成了可版本化管理的 Terraform 组件。
常见问题与求助渠道
- 版本固定:模板示例中
--version 4.8.3是显式钉死的,避免 Coder 重建工作区时因上游发版导致行为漂移;需要升级时应显式改模板,而不是依赖“latest”。 - 端口冲突:
13337只是约定端口,若 agent 容器内已有服务占用,可更换--port并同步修改coder_app.url与healthcheck.url。 - 认证层混淆:若在 Coder 代理的应用地址上仍看到 code-server 自带登录页,说明
--auth none未生效或启动命令被改写;反过来,若绕过 Coder 直接暴露 code-server 端口,则务必恢复密码认证(auth: password,密码仅可通过$PASSWORD/$HASHED_PASSWORD或配置文件传入,见 src/node/cli.ts)。 - 求助渠道:官方文档建议遇到问题时到 Coder 的
coder/coder项目 Discussions 区提问,code-server 与 Coder 同属 Coder 团队维护,该渠道能同时覆盖两侧的问题定位。
小结
在 Coder 工作区部署 code-server 的完整链路是:coder_agent.startup_script 通过 install.sh 安装固定版本(detect 模式按发行版选包管理器、无预构建产物时回退 npm),以 --auth none --port 13337 后台启动;coder_app 声明代理地址、属主级共享,并基于 /healthz 做 3 秒间隔、10 次阈值的健康检查——该端点由 health.ts 提供,且健康检查流量被有意排除在 src/node/routes/index.ts 的心跳刷新之外,从而区分“进程存活”与“真实使用”。更省事的替代方案是引用官方 registry.coder.com/modules/code-server/coder 模块,通过 extensions 参数(底层即 --install-extension)预装扩展。两条路径均以上述 Terraform 配置为最小可复制起点。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00