自托管远程 VSCode 与 Cloudflare Tunnel 和 Authentik SSO

发布: (2026年3月3日 GMT+8 05:47)
12 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的完整文本内容,我将为您翻译成简体中文(保持代码块、URL 和 Markdown 格式不变)。

概述

在远程进行实验项目时,通常需要在每台设备上配置 VPN 或 SSH 密钥。code‑server 解决了这个问题——它在浏览器标签页中提供完整的 VS Code 体验,并通过 Google SSO 进行锁定,24/7 运行在 Mac Mini 上。

组件

ComponentPurpose
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 代理管理器配置

  1. code.yourdomain.com 创建代理主机

    • 转发主机名: 您服务器的 本地 IP(不是 localhost
    • 转发端口: 8484
  2. WebSockets 支持: 开启(code‑server 所必需)

  3. 强制 SSL: 关闭 – Cloudflare 在边缘终止 TLS 并向 NPM 发送普通 HTTP。启用强制 SSL 会导致无限重定向循环。

  4. 修补生成的 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 会将您送到其自己的仪表板。

  1. 编辑配置后重新加载 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-chatms-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 支持两种认证方式:

  1. OAuth 登录 – 使用您的 Claude Pro/Max 订阅。
  2. API 密钥 – 按使用量计费,使用您的 Anthropic API 账户。

在无头容器中,OAuth 浏览器流程会失败,因为回调无法到达容器。

解决方案(macOS)

如果您已经在桌面机器上完成认证,OAuth 令牌会保存在系统钥匙串中:

security find-generic-password -s "Claude Code-credentials" -w

该命令会返回一个包含 accessToken 字段的 JSON 数据(例如 sk-an…)。将此令牌导出到容器中,或将其设置为 Claude Code 的环境变量即可。

摘要

  1. 通过 Docker Compose 部署 code-server
  2. 通过 Cloudflare Tunnel → Nginx Proxy Manager → Authentik 暴露 它。
  3. 在 NPM 中配置 Authentik 的 auth_request 块并关闭 Force‑SSL。
  4. 安装所需的扩展(仅限 Open VSX)。
  5. 添加启动脚本,用于安装 Node.js 和 Claude Code CLI。
  6. 通过钥匙串导出(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 进行通信。

  1. 创建 Portainer 访问令牌

    • Portainer → Account Settings → Access Tokens → Add access token
    • 给它起个名字,例如 claude-code-server
  2. 在容器的 .env 文件中存储令牌

    PORTAINER_URL=https://portainer.yourdomain.com
    PORTAINER_TOKEN=your-token-here
  3. 在容器内部测试连接

    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_URLPORTAINER_TOKEN 存储在 .env.
  • 通过 ~/.claude/commands:/config/.claude/commands:ro 只读挂载自定义技能.
  • 利用持久卷 (/config, vault, projects) 为 VS Code 和 Obsidian 提供存储.

遵循这些步骤,Claude Code 将能够 安全 地与外部服务交互,同时保持容器环境的整洁和可复现性。

0 浏览
Back to Blog

相关文章

阅读更多 »

当工作成为心理健康风险时

markdown !Ravi Mishrahttps://media2.dev.to/dynamic/image/width=50,height=50,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fu...