自托管远程 VSCode 与 Cloudflare Tunnel 和 Authentik SSO
Source: Dev.to
请提供您希望翻译的完整文本内容,我将为您翻译成简体中文(保持代码块、URL 和 Markdown 格式不变)。
概述
在远程进行实验项目时,通常需要在每台设备上配置 VPN 或 SSH 密钥。code‑server 解决了这个问题——它在浏览器标签页中提供完整的 VS Code 体验,并通过 Google SSO 进行锁定,24/7 运行在 Mac Mini 上。
组件
| Component | Purpose |
|---|---|
| code‑server (by Coder) | 在浏览器中运行的 VS Code,由 LinuxServer.io 打包为 Docker 镜像 |
| Cloudflare Tunnel | 仅出站的隧道——路由器上无需打开端口 |
| Authentik (by Authentik Security) | 使用 Google OAuth2 的自托管 SSO |
| Nginx Proxy Manager (by jc21) | 对每个请求强制 forward‑auth 的反向代理 |
SSH 可以使用,但需要在每台设备上配置客户端和密钥,并且失去了完整的编辑器体验。
code‑server 提供扩展、集成终端以及在任何现代浏览器中的 Claude Code。只要它运行并通过代理,就能在 iPad 上和笔记本电脑一样流畅使用。
请求流程
Browser → Cloudflare Tunnel Edge → Nginx Proxy Manager → Authentik outpost check
↓ (if authenticated)
code‑server
- Nginx Proxy Manager 使用
auth_request对每个请求进行检查,针对 Authentik 的嵌入式 outpost。 - 如果您未通过身份验证,则会跳转到 Authentik 登录页面——在本例中是 Google OAuth2 提示。
Source: …
Docker Compose 用于 code‑server
services:
code-server:
image: lscr.io/linuxserver/code-server:latest
container_name: code-server
environment:
- PUID=501
- PGID=20
- TZ=America/Chicago
- PASSWORD=${CODE_SERVER_PASSWORD}
- SUDO_PASSWORD=${CODE_SERVER_PASSWORD}
- DEFAULT_WORKSPACE=/config/workspace
volumes:
- /your/config:/config
- /your/projects:/config/workspace/Projects
ports:
- 8484:8443
restart: unless-stopped
密钥
在 compose 文件旁边创建一个 .env 文件:
CODE_SERVER_PASSWORD=your-password-here
chmod 600 .env # 仅你的用户可以读取它
重要提示: 更改环境变量后,请始终(重新)运行
docker compose up -d。
docker restart会使用容器创建时的原始环境,而docker compose up -d会重新读取 compose 文件 以及.env。
Nginx 代理管理器配置
-
为
code.yourdomain.com创建代理主机- 转发主机名: 您服务器的 本地 IP(不是
localhost) - 转发端口:
8484
- 转发主机名: 您服务器的 本地 IP(不是
-
WebSockets 支持: 开启(code‑server 所必需)
-
强制 SSL: 关闭 – Cloudflare 在边缘终止 TLS 并向 NPM 发送普通 HTTP。启用强制 SSL 会导致无限重定向循环。
-
修补生成的 NPM 配置(在主
location /块 之前 添加 Authentik 区块):
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
location /outpost.goauthentik.io {
proxy_pass http://your-server-ip:9010/outpost.goauthentik.io;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location @goauthentik_proxy_signin {
internal;
return 302 /outpost.goauthentik.io/start?rd=https://$http_host$request_uri;
}
rd=https://… 参数在成功登录后会将您重定向回 code‑server。如果没有此参数,Authentik 会将您送到其自己的仪表板。
- 编辑配置后重新加载 Nginx:
docker exec nginx-proxy-manager nginx -s reload
常见陷阱与解决方案
| 症状 | 原因 | 解决方案 |
|---|---|---|
| 凭证在编辑 compose 后未更新 | 运行了 docker restart 而不是 docker compose up -d | 使用 docker compose up -d |
包含 & 的密码导致 compose 出错 | YAML 将 & 视为锚点 | 将机密移至 .env 文件并使用 ${VAR} 引用 |
| 强制 SSL 重定向循环 | NPM 强制使用 HTTPS,而 Cloudflare 已经发送 HTTP | 在 NPM 中禁用 Force‑SSL |
| 缺少扩展 | code‑server 使用 Open VSX Registry,而非 Microsoft Marketplace | 仅安装 Open VSX 上可用的扩展(见下表) |
安装扩展
大多数扩展可在 Open VSX Registry 上获取。以下对我有效:
for ext in \
anthropic.claude-code \
llvm-vs-code-extensions.lldb-dap \
mechatroner.rainbow-csv \
ms-azuretools.vscode-containers \
ms-python.debugpy \
ms-python.python \
swiftlang.swift-vscode \
tomoki1207.pdf; do
docker exec -u abc code-server \
/app/code-server/bin/code-server --install-extension "$ext"
done
注意:
github.copilot-chat和ms-python.vscode-pylance不在 Open VSX 上,无法安装。
添加 Claude Code(需要 Node.js)
LinuxServer.io 的 code-server 镜像 不 包含 Node.js,而 Claude Code 需要它来运行 CLI 代理。
启动脚本 (config/custom-cont-init.d/install-claude.sh)
#!/bin/bash
# Install Node.js if missing
if ! command -v node &> /dev/null; then
apt-get update -qq && apt-get install -y -qq nodejs npm > /dev/null 2>&1
fi
# Install Claude CLI if missing
if ! command -v claude &> /dev/null; then
npm install -g @anthropic-ai/claude-code > /dev/null 2>&1
fi
LinuxServer.io 镜像会在容器启动时自动执行 custom-cont-init.d/ 中的所有内容,因此 Node 和 Claude CLI 会在 docker compose up -d 循环中保持持久。
Claude Code 身份验证陷阱
Claude Code 支持两种认证方式:
- OAuth 登录 – 使用您的 Claude Pro/Max 订阅。
- API 密钥 – 按使用量计费,使用您的 Anthropic API 账户。
在无头容器中,OAuth 浏览器流程会失败,因为回调无法到达容器。
解决方案(macOS)
如果您已经在桌面机器上完成认证,OAuth 令牌会保存在系统钥匙串中:
security find-generic-password -s "Claude Code-credentials" -w
该命令会返回一个包含 accessToken 字段的 JSON 数据(例如 sk-an…)。将此令牌导出到容器中,或将其设置为 Claude Code 的环境变量即可。
摘要
- 通过 Docker Compose 部署
code-server。 - 通过 Cloudflare Tunnel → Nginx Proxy Manager → Authentik 暴露 它。
- 在 NPM 中配置 Authentik 的
auth_request块并关闭 Force‑SSL。 - 安装所需的扩展(仅限 Open VSX)。
- 添加启动脚本,用于安装 Node.js 和 Claude Code CLI。
- 通过钥匙串导出(macOS)或 API 密钥处理 Claude Code 认证。
现在,你拥有一个功能完整的 VS Code 环境,可通过任何现代浏览器(包括 iPad)访问,使用 Google SSO 进行安全保护,并在你的 Mac Mini 上持续运行。祝编码愉快!
设置您的 Anthropic OAuth 令牌
# .env file (in the container)
ANTHROPIC_API_KEY=sk-ant-oat01-your-token-here
- OAuth 令牌(
sk-ant‑oat…) 通过您的 订阅(而非按使用付费)进行计费。 - API 令牌(
sk-ant‑api…) 按每个令牌对您的 API 账户计费。 - 如果您在 console.anthropic.com 上生成密钥,您将获得 API 密钥,并按令牌计费。
- 存储在钥匙串中的 OAuth 令牌使用您现有的套餐。
在容器中运行 Claude Code
Out‑of‑the‑box Claude Code 可以:
- 读取和写入工作区中的文件。
它 默认情况下不能:
- 运行 Docker 命令。
- 推送到 GitHub。
- 使用您构建的任何自定义技能。
为什么不采用天真的修复方案?
- 挂载 Docker 套接字 → 在主机上获得 root(存在容器逃逸风险)。
- 添加 SSH 密钥 / 使用
sudo安装工具 → 引入真实的安全风险。
在不使用 sudo 的情况下安装 GitHub CLI
# Get the latest GH version
GH_VERSION=$(curl -s https://api.github.com/repos/cli/cli/releases/latest \
| grep '"tag_name"' | cut -d'"' -f4 | sed 's/v//')
# Download the tarball
curl -sL "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_arm64.tar.gz" \
-o /tmp/gh.tar.gz
# Extract and install to a writable directory
mkdir -p /config/bin
tar -xz -f /tmp/gh.tar.gz -C /tmp
cp /tmp/gh_${GH_VERSION}_linux_arm64/bin/gh /config/bin/gh
# Add to PATH for future sessions
echo 'export PATH="/config/bin:$PATH"' >> /config/.bashrc
/config是一个 持久卷,因此二进制文件在容器重新创建后仍然存在。- 使用仅对 Claude 所需仓库授权的 细粒度个人访问令牌(PAT)进行身份验证。这可以在容器被攻破时限制影响范围。
使用 Portainer 替代 Docker Socket
挂载 Docker socket 等同于给容器 在主机上的 root 权限。
更安全的替代方案是让 Claude 通过 Portainer 的 REST API 进行通信。
-
创建 Portainer 访问令牌
- Portainer → Account Settings → Access Tokens → Add access token
- 给它起个名字,例如
claude-code-server。
-
在容器的
.env文件中存储令牌PORTAINER_URL=https://portainer.yourdomain.com PORTAINER_TOKEN=your-token-here -
在容器内部测试连接
curl -s -H "X-API-Key: $PORTAINER_TOKEN" \ $PORTAINER_URL/api/endpoints
Claude 现在可以创建容器、检查服务、拉取镜像等,无需任何提升的主机访问权限。令牌是有作用域的、可审计的且可撤销的。
添加自定义 Claude 代码技能(斜杠命令)
自定义技能位于主机的 ~/.claude/commands/ 目录下。在容器内部,这映射为 /config/.claude/commands/,默认情况下该目录不存在。
修复方案 – 在 docker‑compose.yml 中挂载卷
volumes:
- /your/config:/config
- /your/projects:/config/workspace/Projects
- ~/.claude/commands:/config/.claude/commands:ro # 只读挂载
:ro标志将挂载设为 只读 —— Claude 可以使用这些技能,但无法在容器内部对其进行修改。- 重启容器;技能将在下一个会话中出现。
代理定义与金库访问
存储在金库笔记中的代理定义已经可以访问,因为金库已挂载为工作区文件夹。无需额外设置。
持久化开发环境
已认证的 VS Code
- URL:
https://code.yourdomain.com - 在 iPad、iPhone、任何笔记本电脑上均可使用。
- 会话、扩展、设置和工作区在镜像更新后仍然保留,因为它们存放在
/config卷中。
Obsidian 金库
- 挂载为工作区文件夹。
- 在浏览器中编辑的笔记会即时同步到 iCloud。
TL;DR 检查清单
- 设置
ANTHROPIC_API_KEY为 OAuth 令牌 (sk-ant‑oat…). - 安装
gh到/config/bin(不使用sudo). - 优先使用 Portainer API 而非 Docker socket;将
PORTAINER_URL与PORTAINER_TOKEN存储在.env. - 通过
~/.claude/commands:/config/.claude/commands:ro只读挂载自定义技能. - 利用持久卷 (
/config, vault, projects) 为 VS Code 和 Obsidian 提供存储.
遵循这些步骤,Claude Code 将能够 安全 地与外部服务交互,同时保持容器环境的整洁和可复现性。