mcpField
U
ucloud-sandbox-site

ucloud-sandbox-site

github.com/ucloudクラウド・DevOps351 回インストール1 日前に更新
リポジトリ

ucloud-sandbox-site について

ucloud-sandbox-siteは、`ucloud-sandbox-cli`で既存のUCloudサイトスペースに接続し、管理するスキルです。リモートコマンド、ファイル操作、サービス確認を通じた開発とデプロイを案内し、認証情報と操作範囲を定めています。サイトやサンドボックスの作成は行いません。

主な機能

  1. 01既存サイトのサンドボックスへの接続と確認
  2. 02CLIによるリモートコマンド実行
  3. 03ファイルの閲覧、転送、管理
  4. 04サイトプロジェクトのビルドとデプロイ
  5. 05siteテンプレート向けPostgreSQLとpgvectorの案内
  6. 06認証情報と操作範囲の制限

活用シーン

  1. 01既存のサイトサンドボックスでの開発と実行
  2. 02プロジェクトファイルのアップロードとサイト公開
  3. 03サービスと外部アクセス応答の確認
  4. 04siteテンプレートでのアプリ用DB接続設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ucloud/ucloud-sandbox-cli --skill ucloud-sandbox-site

インストール後、Claude Code で/ucloud-sandbox-siteを入力して読み込まれたか確認します。

同梱ファイルreferences/windows.md

詳細

UCloud 站点空间

使用 ucloud-sandbox-cli 操作用户已经创建的站点空间。站点空间底层是一个沙箱;本技能只负责连接和维护该站点,不创建站点或沙箱。

前置检查和平台

执行 CLI 安装或调用站点 API 前,先确认当前环境允许访问公网。需要网络权限审批时先申请授权;未获授权时停止并说明原因。

在 Windows 或 PowerShell 环境中,执行安装、连接、文件传输或部署前,先完整阅读并遵循 Windows PowerShell 指南。本页的 Bash 安装、凭证注入和本地打包命令仅适用于 Linux 和 macOS;传给 sandbox exec 的命令仍在远端 Linux Shell 中执行。

核心概念

  • 站点连接 Key 格式为 site_<sandbox-id>_<code>,<code> 是站点空间随机生成的连接码,用于防止他人仅凭沙箱 ID 就连接到站点。例如 site_iy1qen6gs2835o0udufdz_7f3a9c2e 对应沙箱 ID iy1qen6gs2835o0udufdz。
  • 沙箱 ID 是 site_ 前缀之后、第一个 _ 之前的部分。连接码只是 Key 的组成部分,不要单独传给 CLI,也不要拼进沙箱 ID。
  • 站点连接 Key 同时是一个受限 API Key。把完整 Key 写入 UCLOUD_SANDBOX_API_KEY,但向 CLI 传资源 ID 时只使用派生出的沙箱 ID。
  • 旧格式 site_<sandbox-id>(不带 _<code>)已不再可用。用户提供旧格式时,不要尝试补全、猜测或省略连接码,也不要改用普通 API Key,直接请用户到星图控制台的站点空间页面重新复制新的站点连接语句。
  • 站点凭证只能操作它绑定的一个沙箱,不能列出或删除沙箱,也不能操作模板等其他资源。
  • /home/user/.site.env 保存用户为网站配置的环境变量。它由站点空间管理,不要删除、覆盖或纳入部署包。
  • 沙箱默认包含 Python 和 Node.js;确有需要时,可以通过 sandbox exec 调用 apt 安装其他依赖。
  • 沙箱命令默认以 user 用户运行。user 已配置免密 sudo;绑定 80 端口以及其他需要 root 权限的操作要直接使用非交互的 sudo -n,不要先以普通用户试运行。

把站点连接 Key 视为凭证:不要在回复、日志、生成的代码或仓库文件中重复暴露它(包括其中的连接码),也不要写入 ~/.ucloud-sandbox-cli/config.json。仅在执行 CLI 的 shell 环境中临时设置。派生出的沙箱 ID 不含连接码,可以正常出现在命令中。

权限和安全边界

站点操作只使用以下能力:

  • sandbox exec:执行命令、检查环境、构建项目和管理服务。
  • sandbox host:获取 80 端口的站点访问地址。
  • sandbox fs ls、sandbox fs cat、sandbox fs mkdir、sandbox fs cp、sandbox fs mv、sandbox fs rm:管理该站点沙箱内的文件和目录。本节以下把这一组简称为 fs ...。

不要尝试 sandbox list、create、fork、kill、pause,也不要执行快照、Secret、Volume、模板或其他管理命令。站点凭证返回无权限并不表示站点连接失败。

执行文件删除、覆盖或大范围移动前,先确认路径属于当前网站且操作符合用户意图。不要为了“清理部署目录”删除 /home/user、/home/user/.site.env 或来源不明的已有文件。

准备并验证 CLI

最低支持版本是 v1.3.2。v1.3.1 开始让控制面、RPC、文件和流式请求统一继承 HTTP_PROXY、HTTPS_PROXY 与 NO_PROXY;v1.3.2 进一步要求官方安装器校验 Release SHA256。更早版本在受限网络中可能误报 DNS 失败,或缺少安装完整性校验。

先执行一次 ucloud-sandbox-cli version。AstraFlow 的本地 Agent PATH 包含真实用户的通用 CLI 目录(Linux/macOS 为 ~/.local/bin),不是每个会话的私有 $HOME,也不是 AstraFlow 的 Application Support 目录。已满足最低版本时直接继续,不要更新。

如果命令不存在或低于 v1.3.2,只把官方安装命令安装到真实用户的 ~/.local/bin。这一步必须作为一个完整命令申请一次主机执行权限;获批后不要再为安装器内部的下载、临时目录或写文件分别申请权限:

TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/ucloud-sandbox-cli.XXXXXXXX")" && \
trap 'rm -rf "$TMP_DIR"' EXIT && \
curl -fsSLo "$TMP_DIR/install.sh" \
  https://raw.githubusercontent.com/ucloud/ucloud-sandbox-cli/main/install.sh && \
sh "$TMP_DIR/install.sh" -y -p "$HOME/.local/bin" && \
"$HOME/.local/bin/ucloud-sandbox-cli" version

不要先尝试 /usr/local/bin,不要使用 sudo,不要安装到 Agent 会话的私有 $HOME,不要写入或硬编码 AstraFlow 的 sandbox-workspaces / Application Support 路径,也不要用 find $HOME 搜索 CLI。安装完成后回到 Default 沙箱,按命令名 ucloud-sandbox-cli 使用;真实用户目录跨会话和重启复用。

Windows 按 Windows PowerShell 指南 使用用户级安装目录;同样把安装与版本验证合并成一次获批的主机命令。

仅当用户明确要求更新 CLI 时,如果已安装的版本是 v1.3.4 或更高,直接用自带的 update 命令,不必重新下载安装脚本。这里没有交互式终端,必须带 -y 跳过确认:

ucloud-sandbox-cli update -y && ucloud-sandbox-cli version

update 会校验 Release SHA256 后替换当前程序,保持原安装目录不变。低于 v1.3.4 的版本没有该命令,按上面的安装流程重装。查询版本报 GitHub API 限流时,说明原因并让用户稍后重试或设置 GITHUB_TOKEN。

本节只准备 ucloud-sandbox-cli,不要安装或更新本 Skill 本身。

判断 Skill 是否最新

当需要确认 Skill 是否为最新版本时,比较已安装 CLI 版本与 GitHub 最新 release;两者一致(或 Skill 相关文件无落后提交)即视为 Skill 已是最新:

ucloud-sandbox-cli version
curl -fsSL https://api.github.com/repos/ucloud/ucloud-sandbox-cli/releases/latest | grep tag_name

如果不是最新的通过npx skills add ucloud/ucloud-sandbox-cli -s astraflow-api -s ucloud-sandbox-site提示用户进行更新skill

连接站点

1. 获取并校验站点连接 Key

如果用户还没有提供站点连接 Key,只向用户索取 site_<sandbox-id>_<code> 格式的连接 Key(即站点空间页面上的站点连接语句);不要索取普通 UCloud API Key,也不要只要沙箱 ID。先按照上一节完成 CLI 安装和验证。

Linux 和 macOS 在同一个 shell 调用中校验 Key、设置凭证并派生沙箱 ID:

SITE_KEY='site_<sandbox-id>_<code>'

case "$SITE_KEY" in
  site_*_*) ;;
  site_?*)
    echo "检测到旧版站点 ID 格式 site_<sandbox-id>,已不再支持。请到星图控制台的站点空间页面重新获取站点连接语句(site_<sandbox-id>_<code>)。" >&2
    exit 1 ;;
  *)
    echo "站点连接 Key 格式无效,应为 site_<sandbox-id>_<code>" >&2
    exit 1 ;;
esac

SITE_BODY="${SITE_KEY#site_}"
SANDBOX_ID="${SITE_BODY%%_*}"
SITE_CODE="${SITE_BODY#*_}"

if [ -z "$SANDBOX_ID" ] || [ -z "$SITE_CODE" ]; then
  echo "站点连接 Key 缺少沙箱 ID 或连接码,请到星图控制台的站点空间页面重新获取站点连接语句。" >&2
  exit 1
fi

export UCLOUD_SANDBOX_API_KEY="$SITE_KEY"

SANDBOX_ID 只取第一个 _ 之前的部分,连接码留在 UCLOUD_SANDBOX_API_KEY 中;不要把 SITE_CODE 或完整 Key 传给任何 CLI 子命令的资源 ID 参数。

校验失败时立即停止,不要继续尝试 sandbox exec。用户提供旧格式时,只回复需要到站点空间页面重新获取连接语句,不要输出用户给出的旧 ID 之外的推测值。

环境变量只对当前 shell 进程及其子进程有效。Agent 每次开启新的 shell 调用时,都要重新注入 UCLOUD_SANDBOX_API_KEY 并派生 SANDBOX_ID,不要假设上一次 export 仍然有效。

站点所在地域或 API 域名仍由已有 CLI 配置以及 UCLOUD_SANDBOX_REGION、UCLOUD_SANDBOX_DOMAIN 决定。没有证据时不要擅自切换;连接失败且怀疑地域不符时,向用户确认站点地域。

2. 在一次调用中验证连接并检查初始目录
ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  "printf 'SITE_CONNECTED\\n'; pwd; printf 'SITE_HOME\\n'; ls -la /home/user"

只要这个 exec 成功,就认为 AI 已连接站点并已完成首次目录检查,可以继续生成代码和部署。不要把连接验证、pwd 和初始 ls 拆成多个调用,也不要用 sandbox list 验证连接。

3. サイトのアクセスコード保護を識別する

CLI 接続の検証と公開 URL へのアクセスは別のものです。AI は CLI でサンドボックスに接続できますが、アクセスコードが設定された公開サイトを AI が直接検証することはできません。

sandbox host またはユーザーのカスタムドメインにアクセスするときは、アクセスコードを一切含めないリクエストを使用して、HTTP ステータスとレスポンス本文を確認してください。401 が返され、レスポンス本文に Site protected が含まれる場合は、サービス障害ではなく、サイトでアクセスコード保護が有効になっていると判断します。アクセスコードを推測、回避、再試行したり、顧客にアクセスコードを AI へ送信するよう求めたりしないでください。アクセスコードは機密情報であり、コマンド、ログ、コード、返信に記載してはいけません。

この場合、サイト内の http://127.0.0.1:80 の検証結果は保持できますが、公開ページの検証は顧客に委ねてください。sandbox host が返したアドレスを顧客に渡し、ブラウザーでアクセスコードを入力してもらいます。アクセスコードが有効な間は AI が公開ページの検証を完了できないことを、顧客に説明してください。

顧客が開発段階で AI に公開ページを検証させる必要がある場合は、検証の間だけサイト空間コンソールでアクセスコードを一時的に無効にし、検証後に再び有効にするよう依頼してください。設定方法はサイト空間ドキュメントを参照してください。顧客が自発的にアクセスコードを提供した場合でも、AI に代わりに使用または保存させないでください。

4. 公開アクセス拒否(403)を識別する

公開 URL が 403 を返す場合、サイトゲートウェイがこのアクセスを拒否したことを示します。Web サイトのサービス障害でも、CLI 接続の失敗でもありません。判断する前にレスポンス本文を読み取り、以下の 3 つの状況を区別して対応してください。再試行、回避、出口 IP の変更は行わないでください。

レスポンス本文の特徴原因対応
This site does not accept requests from your IP address を含むアクセス元の IP アドレスが許可されていない星図コンソールのサイト空間ページで、そのサイトの IP ホワイトリストとブラックリストの設定を確認し、現在のアクセス元が許可されているか顧客に確認してもらいます
Domain not allowed を含むサイトにカスタムドメインが設定されており、そのドメインからのアクセスのみ許可されているCLI ではサイトに設定されたカスタムドメインを取得できません。AI はドメインを推測したり組み立てたりせず、公開ページの検証を顧客に委ね、星図コンソールで設定したカスタムドメインを使ってアクセスしてもらいます
Port not allowed を含む80 以外のポートにアクセスしたサイトで公開されているのはポート 80 のみです。ポート 80 に戻してアクセスし、サービスが 0.0.0.0:80 でリッスンしていることを確認してください。他のポートを通じて外部に公開しないでください

IP リストとカスタムドメインはいずれもサイト側の設定です。AI は CLI から照会または変更できないため、星図コンソールで設定を調整するか、カスタムドメインでアクセスするよう顧客に案内してください。この場合、サイト内の http://127.0.0.1:80 の検証結果は保持できますが、公開ページの検証が成功したと伝えてはいけません。

5. 統一された接続案内を返す

接続検証(成功または失敗)の完了後、この節の固定テンプレートに従ってユーザーに案内を返してください。フィールドを省略したり、文言を変更したり、別の形式に置き換えたりしないでください。テンプレートの <sandbox-id>、<region> は実際の値に置き換えてください。

接続成功時(手順 2 の exec 検証に合格した場合)は、次を返します。

已成功连接站点,可以开始开发。
- 沙箱 ID:<sandbox-id>
- 地域:<region>
- 工作目录:/home/user
- 连接技能:ucloud-sandbox-site(<技能状态>)

使用指引
- 开发站点:用自然语言描述你的想法,Agent 会帮你开发。
- 保存数据:站点已预装 PostgreSQL,默认未启动。需要时告诉 Agent:“使用预装数据库保存数据。”
- 查看效果:开发完成后,回到「站点空间」,点击「访问」即可查看,无需单独发布。

接続失敗時(接続 Key の検証には合格したものの、exec 検証に失敗した場合)は、次を返します。

连接失败,暂时无法访问站点。
- 沙箱 ID:<sandbox-id>
- 地域:<region>
- 失败原因:<根据实际返回信息填写>
- 连接技能:ucloud-sandbox-site(<技能状态>)

排查指引
- 更新技能:旧版技能可能导致连接失败,请重新安装最新版后重试。
- 核对连接信息:回到「站点空间」,重新复制完整连接语句后交给 Agent。
- 仍无法连接:将以上信息及错误提示提供给技术支持,协助排查。

各フィールドの取得元:

  • サンドボックス ID:接続 Key から導出したサンドボックス ID。接続コードは含めません。
  • リージョン:現在の CLI 設定または UCLOUD_SANDBOX_REGION にあるリージョン。ucloud-sandbox-cli auth show で確認できます。
  • 作業ディレクトリ:手順 2 の検証コマンドにおける pwd の出力。通常は /home/user です。
  • 失敗理由:CLI の実際のエラー出力から抜粋します。要約はできますが、内容を捏造してはいけません。また、接続 Key や接続コード全体を含めないでください。
  • 接続スキルの状態は次の 3 つから選びます。セッションまたはプラットフォームでスキルが最新版だと確認できた場合は「已是最新」、最新版ではないと確認できた場合は「请重新安装最新版,否则可能影响新功能使用」(成功テンプレート)または「请重新安装最新版,否则可能影响连接及新功能使用」(失敗テンプレート)、確認を完了できなかった場合は「未能检查更新,请确认是否为最新版」とします。確認結果を捏造してはいけません。

接続 Key が旧形式の場合、または検証に失敗した場合は失敗テンプレートを使用せず、「サイト接続 Key の取得と検証」の要件に従って返信してください。接続成功後にサイト操作を続行する場合、成功テンプレートを再度返す必要はありません。

よく使うコマンド

以下の例はすべて、現在のシェルに UCLOUD_SANDBOX_API_KEY と SANDBOX_ID が正しく設定されていることを前提としています。sandbox は sbx と略記できます。

コマンドの実行

コマンドの内容は、ひとつの完全な文字列として exec に渡す必要があります。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" "pwd && ls -la /home/user"
ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" "python3 --version && node --version && npm --version"

通常のプロジェクト操作では、sudo を使用しないでください。これには、コードを /home/user にアップロードまたは変更する操作、プロジェクトの依存関係のインストール、ビルドの実行、.site.env の読み取りが含まれます。そうしないと、root 所有のプロジェクトファイルが作成され、後続の更新に支障をきたします。

以下の操作では通常 root 権限が必要です。初回から sudo -n を使用してください。

  • 80 など 1024 未満の特権ポートでのリッスン、および root が起動したサービスプロセスの停止。
  • apt-get を使用したシステム依存関係のインストール。
  • systemctl、service の使用、またはシステムレベルのサービス設定の変更。
  • /etc、/usr、/usr/local、/var などのシステムディレクトリへの書き込み、または user に属さないファイルの権限や所有者の変更。

ucloud-sandbox-cli コマンド全体にローカルで sudo を使用しないでください。実際に必要な部分に限り、sandbox exec に渡すリモートコマンド内で権限を昇格してください。対話型の sudo は使用しないでください。権限昇格が必要な場合は、まず sudo -n true でパスワードなしの権限を確認してください。失敗した場合は問題を報告し、パスワード入力を待たないでください。

プロジェクトで追加のシステムパッケージが実際に必要な場合に限り、インストールしてください。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" "sudo -n apt-get update && sudo -n apt-get install -y <package>"
PostgreSQL 15 と pgvector(site テンプレートのみ対象)

site 系列のテンプレート(仕様テンプレートの命名形式は site-{CPU核数}c-{内存GiB数}g)をベースに構築されたサイトには、PostgreSQL 15、クライアント、pgvector が組み込まれています。サイト接続 Key だけからデータベースがインストール済みまたは起動済みだと判断せず、まず実際の環境を確認してください。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  "whoami && command -v start-postgres && command -v stop-postgres && psql --version"

デフォルトの Linux ユーザーは user です。base テンプレートにはこれらのデータベースコンポーネントは含まれていません。コマンドが見つからない場合は、サイトテンプレートと実際のインストール状況を確認してください。サイトの認証情報を使ってサンドボックスを作成または置き換えないでください。

起動、検証、停止
  • start-postgres は内部で sudo -n systemctl start postgresql-vector.service を実行し、依存関係を通じて [email protected] を起動します。呼び出し側でさらに sudo を重ねる必要はありません。
  • postgresql-vector.service は postgres として実行される oneshot 初期化ユニットです。必要に応じて enable-pgvector により、スーパーユーザーではないロール user と、そのロールが所有する ucloud データベースを作成し、ucloud 内で CREATE EXTENSION IF NOT EXISTS vector を実行します。
  • 初期化ユニットでは RemainAfterExit=yes が設定されています。active (exited) と表示されるのは正常です。すでにアクティブなユニットを再度起動しても、初期化 SQL は再実行されず、既存のロールやデータベースの属性も修正されません。

同じサンドボックス内でデータベースを起動します。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" "start-postgres"

Unix Socket を使って、サービス、接続ユーザー、ベクトル型を確認します。pg_isready で確認できるのはサービスの準備状態のみです。後続の SQL が成功して初めて、アプリケーションのユーザーで接続し、pgvector を使用できることが証明されます。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  "sudo -n systemctl is-active [email protected] && \
   sudo -n systemctl is-active postgresql-vector.service && \
   pg_isready -h /var/run/postgresql -p 5432 -U user -d ucloud && \
   psql -X -w -v ON_ERROR_STOP=1 -h /var/run/postgresql -p 5432 -U user -d ucloud \
     -c \"SELECT current_user, current_database(), '[1,2,3]'::vector;\""

クエリは user、ucloud、[1,2,3] を返す想定です。データベースを停止するには、次を実行します。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" "stop-postgres"

stop-postgres は内部で [email protected] を停止し、依存関係に従って初期化ユニットも停止します。データベースは削除されません。Web サイトが中断するのを防ぐため、接続検証の最後にデータベースを停止しないでください。

アプリケーション接続の設定

テンプレートでは、ローカルの Unix ソケットディレクトリ /var/run/postgresql、ポート 5432、データベース ucloud、ロール user をデフォルトで使用します。pg_hba.conf では、ローカルソケットに peer 認証を使用し、IPv4 および IPv6 のすべての TCP 接続(ループバックアドレスを含む)を reject に設定しています。また、テンプレートでは PostgreSQL の SSL を無効にしています。

  • アプリケーションとマイグレーションコマンドは、同じサンドボックス内で Linux ユーザー user として実行する必要があります。peer 認証は OS のユーザーを照合するため、設定にデータベースのユーザー名 user を指定しただけでは、root プロセスは認証されません。
  • ソケットディレクトリを明示的に指定し、127.0.0.1 や localhost は使用しないでください。host を省略すればソケットが使用されるとは限りません。たとえば、Node.js の pg はデフォルトで localhost に接続します。
  • ソケットディレクトリを指定した場合、port=5432 は .s.PGSQL.5432 ソケットファイルを選択するもので、TCP を使うという意味ではありません。この接続にデータベースのパスワードは不要です。接続を修復するために SSL を要求したり、pg_hba.conf の制限を緩めたりしないでください。
  • 業務アプリケーションの実行にスーパーユーザー postgres を使用しないでください。管理者操作が必要な場合は sudo -n -u postgres psql を使用します。

アプリケーションの接続例:

クライアント接続例
Python / psycopgpsycopg.connect("host=/var/run/postgresql port=5432 dbname=ucloud user=user")
Node.js / pgnew Pool({ host: '/var/run/postgresql', port: 5432, database: 'ucloud', user: 'user' })
Go / pgx または lib/pqhost=/var/run/postgresql port=5432 dbname=ucloud user=user sslmode=disable
peer 認証と 80 ポートの要件を両立する

データベースを使用する動的ウェブサイトに、後述の root による静的サービスの起動例を適用することはできません。systemd の User=user と AmbientCapabilities=CAP_NET_BIND_SERVICE を使用すれば、アプリケーションを user として実行しながら 0.0.0.0:80 にバインドできます。サービスの管理には sudo -n を使用します。この場合、プロセス、PID、ログは systemd が管理するため、PID ファイルを別途保存する必要はありません。環境変数の読み込みと HTTP の検証は、引き続きデプロイのセクションに従ってください。

データベースのトラブルシューティング
状況対処方法
ソケットが存在しない、または接続が拒否されるstart-postgres の結果、systemctl status [email protected] postgresql-vector.service、および /var/run/postgresql を確認します。ログが必要な場合は sudo -n journalctl -u [email protected] -u postgresql-vector.service -n 100 --no-pager を使用し、出力に機密情報が含まれていないか確認します
pg_hba.conf rejects connection、またはログに 127.0.0.1 / ::1 が表示されるクライアントが TCP を使用しています。host をソケットディレクトリに明示的に変更し、環境変数または接続 URL によって設定が上書きされていないか確認します
Peer authentication failed または role "root" does not exist実際のアプリケーションまたはマイグレーションプロセスの Linux ユーザーとデータベースロールを確認し、user に変更します。trust、パスワード、または TCP 接続の許可によって peer 認証を回避しないでください
ucloud、user、または vector 型が見つからない初期化ユニットの状態とログを確認し、ucloud に接続していることを確かめます。初期化スクリプトは、そのデータベース内でのみ vector を有効にします
ファイルの参照と読み取り
ucloud-sandbox-cli sandbox fs ls "$SANDBOX_ID" /home/user
ucloud-sandbox-cli sandbox fs ls "$SANDBOX_ID" /home/user --format json
ucloud-sandbox-cli sandbox fs cat "$SANDBOX_ID" /home/user/site/index.html

機密情報が含まれていないと確認できた通常のファイルに限り、fs cat を使用してください。/home/user/.site.env に fs cat を使用しないでください。

ディレクトリの作成
ucloud-sandbox-cli sandbox fs mkdir "$SANDBOX_ID" /home/user/site

ディレクトリがすでに存在する場合でも、コマンドは成功し、Directory already exists と表示されます。複数階層のディレクトリを作成する場合は、既存の親ディレクトリから fs mkdir を階層ごとに呼び出してください。ディレクトリツリー全体を一度に作成する必要がある場合は、検証済みの mkdir -p を sandbox exec で実行できます。

ファイルのアップロードとダウンロード

fs cp のリモートエンドポイントの形式は <sandbox-id>:<path> です。コピー元とコピー先のうち、リモートエンドポイントは必ず一方だけにしてください。一度にコピーできるのは 1 ファイルのみです。

# 上传
ucloud-sandbox-cli sandbox fs cp ./index.html "$SANDBOX_ID:/home/user/site/index.html"

# 下载
ucloud-sandbox-cli sandbox fs cp "$SANDBOX_ID:/home/user/site/service.log" ./service.log

ディレクトリをアップロードする場合は、まずローカルでアーカイブし、その後アップロードしてサイト内で展開してください。.env、認証情報、依存関係のディレクトリ、その他デプロイすべきでないローカルファイルは除外してください。

LOCAL_PROJECT_DIR='./site'
tar \
  --exclude='.git' \
  --exclude='.env' \
  --exclude='.env.*' \
  --exclude='node_modules' \
  -czf /tmp/site-release.tgz -C "$LOCAL_PROJECT_DIR" .

ucloud-sandbox-cli sandbox fs cp /tmp/site-release.tgz "$SANDBOX_ID:/tmp/site-release.tgz"
ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  "mkdir -p /home/user/site && tar -xzf /tmp/site-release.tgz -C /home/user/site && rm -f /tmp/site-release.tgz"

アップロード前に、対象ディレクトリを確認してください。すでにウェブサイトがある場合は、独立したリリースディレクトリを使用するか、今回の変更ファイルのみを上書きすることを優先してください。古いファイルと新しいビルド成果物が混在しないようにし、無条件にディレクトリを空にしないでください。

ファイルの移動と削除
ucloud-sandbox-cli sandbox fs mv "$SANDBOX_ID" /home/user/site/old.html /home/user/site/index.html
ucloud-sandbox-cli sandbox fs rm "$SANDBOX_ID" /home/user/site/obsolete.html

fs rm は破壊的な操作です。実行前に正確なパスを確認してください。ディレクトリや複数のファイルを削除する場合は、検証されていないユーザー入力を rm -rf に連結しないでください。

サイトの環境変数を安全に読み取る

ユーザーから設定済みの環境変数について質問された場合、変数が存在するかどうかを伝え、機密性のない変数を表示できます。変数名に大文字と小文字を区別せず API_KEY または KEY が含まれる場合、その値は絶対に出力せず、変数が存在することだけを伝えるか、<已隐藏> と表示してください。

認証情報が漏えいする可能性のある次のコマンドを直接実行しないでください。

  • fs cat ... /home/user/.site.env
  • cat /home/user/.site.env
  • フィルタリングされていない env、printenv、set、または export -p
  • 環境変数の読み込み時に set -x を有効にする

設定の概要を確認する必要がある場合は、サンドボックス内で各行を解析し、機密情報をマスキングしてください。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" 'awk '\''
  /^[[:space:]]*(#|$)/ { next }
  {
    line=$0
    sub(/^[[:space:]]*export[[:space:]]+/, "", line)
    eq=index(line, "=")
    if (!eq) next
    name=substr(line, 1, eq-1)
    gsub(/^[[:space:]]+|[[:space:]]+$/, "", name)
    if (name !~ /^[A-Za-z_][A-Za-z0-9_]*$/) next
    if (toupper(name) ~ /API_KEY|KEY/) print name "=<已隐藏>"
    else print line
  }
'\'' /home/user/.site.env'

特定の機密変数が存在するかどうかだけを確認する場合は、変数名が有効なシェル識別子であることを検証したうえで、「存在する」または「存在しない」のみを返し、値は返さないでください。.site.env が存在しない場合は、その事実を伝えてユーザーに確認してください。代わりに空のファイルを勝手に作成しないでください。

ユーザーのサイトをビルドまたは起動する際は、以下のパターンを使ってすべての変数を読み込み、内容を出力しないでください。

set -a
source /home/user/.site.env
set +a

ウェブサイトの作成とデプロイ

ユーザーの要望に応じて、適切なフロントエンドの技術スタックを選択してください。まず既存のファイルとプロジェクト設定を確認し、その後ローカルでコードを生成または変更してアップロードします。理由なくユーザーの既存フレームワークを置き換えないでください。デプロイ時は、次の必須要件を守ってください。

  1. サービスは 0.0.0.0:80 をリッスンする必要があります。127.0.0.1 のみをリッスンしたり、3000、5173、8080 などのポートに変更して納品したりしてはいけません。サンドボックスのデフォルトユーザーは user です。80 ポートにバインドする際は、初回の起動から sudo -n を使用する必要があります。
  2. サービスのビルド時と起動時には、どちらも source /home/user/.site.env を実行します。読み込み中に変数の内容を出力してはいけません。
  3. サービスは sandbox exec の終了後も継続して実行される必要があります。nohup またはサイトに既存のサービスマネージャーを使用し、標準入力、標準出力、標準エラーをリダイレクトしてください。
  4. PID とログを保存します。root サービスの稼働確認と停止にも sudo -n kill を使用してください。再起動時は、記録した自サービスの古い PID のみを終了し、他のプロセスに影響する pkill node、killall などの広範なコマンドは使用しないでください。
  5. サイト内から http://127.0.0.1:80 へのアクセスが成功してから、sandbox host を呼び出し、デプロイ成功をユーザーに伝えてください。
ビルド例

Node プロジェクトは、プロジェクト独自のロックファイルとスクリプトに従ってビルドしてください。以下は一般的なパターンにすぎません。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  "cd /home/user/site && set -a && source /home/user/.site.env && set +a && npm ci && npm run build"

package-lock.json がない場合は、プロジェクトで実際に使用しているパッケージマネージャーとロックファイルに応じてコマンドを選択し、機械的に npm ci を実行しないでください。

npm、pnpm、yarn、またはビルドスクリプトを sudo で実行しないでください。権限昇格が必要なのは、最終的な 80 ポートのサービスを起動するときだけです。

サービスの常時起動例

ビルド成果物が /home/user/site/dist にある静的ウェブサイトの場合は、インストール済みの Python を使って常時実行できます。

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" '
  set -e
  PID_FILE=/home/user/site/service.pid
  LOG_FILE=/home/user/site/service.log

  sudo -n true

  if [ -s "$PID_FILE" ]; then
    old_pid=$(cat "$PID_FILE")
    if sudo -n kill -0 "$old_pid" 2>/dev/null; then
      sudo -n kill "$old_pid"
    fi
  fi

  sudo -n touch "$PID_FILE" "$LOG_FILE"
  sudo -n chown user:user "$PID_FILE" "$LOG_FILE"
  sudo -n bash -lc "
    set -e
    set -a
    source /home/user/.site.env
    set +a
    nohup python3 -m http.server 80 --bind 0.0.0.0 --directory /home/user/site/dist \
      >/home/user/site/service.log 2>&1 </dev/null &
    echo \$! >/home/user/site/service.pid
  "
'

起動前に sudo でログファイルと PID ファイルを作成し、その後所有者を user に戻します。これにより、以前の試行で残った root 所有のファイルに対応でき、以降のメンテナンスで常に権限昇格が必要になることも避けられます。PID が外側の sudo ラッパープロセスではなく実際のウェブサイトサービスを指すよう、root の起動スクリプト内で $! を記録する必要があります。

ローカルの PostgreSQL を使用しない SSR、Node、またはその他の動的サービスの場合も、同じ sudo -n、PID、ログ、バックグラウンド実行、環境変数読み込みのパターンを維持し、exec python3 ... をプロジェクトの本番用起動コマンドに置き換えて、HOST=0.0.0.0 と PORT=80 を明示的に設定するか、渡してください。開発サーバーをデフォルトの本番デプロイ手段にしないでください。

验证并返回地址
ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  "curl -fsS --max-time 10 http://127.0.0.1:80/ >/dev/null && echo SITE_HTTP_OK"

ucloud-sandbox-cli sandbox host "$SANDBOX_ID" 80

把 sandbox host 输出的实际地址原样告知用户,不要猜测或拼接域名。同时简要说明已部署内容、监听端口和验证结果。

验证公共 URL 时同时读取 HTTP 状态码和响应体,先区分网关拒绝和服务故障,再决定是否排查服务:

  • 401 且响应体包含 Site protected:访问码保护,按“识别站点访问码保护”处理。
  • 403:访问被网关拒绝,按“识别公共访问被拒绝(403)”对照响应体判断是 IP 名单、自定义域名还是端口限制。

这两类情况都不表示网站服务异常,也不影响站点内 HTTP 验证结果,但都不能据此宣布公共页面验证成功。若验证失败且不属于上述两类,先检查进程、80 端口和服务日志:

ucloud-sandbox-cli sandbox exec "$SANDBOX_ID" \
  'if [ -f /home/user/site/service.pid ]; then pid=$(cat /home/user/site/service.pid); sudo -n ps -p "$pid" -o pid=,stat=,cmd=; fi; sudo -n ss -ltnp | grep '\'':80'\'' || true; tail -n 100 /home/user/site/service.log'

上例用单引号包住远端命令,使 $() 在沙箱中展开。改写命令或改变引号层级时,不要让本地 shell 提前执行远端表达式。

故障处理

现象处理
用户提供的是旧格式 site_<sandbox-id>不要尝试连接或补全连接码;告知格式已更新,请用户到星图控制台的站点空间页面重新复制站点连接语句
exec 提示无权限或鉴权失败确认完整 site_<sandbox-id>_<code> 被用作 API Key(连接码没有被截断),派生出的沙箱 ID 被用作资源 ID;仍失败时请用户确认连接语句是否已在控制台重新生成;不要改用 sandbox list 测试
提示找不到沙箱检查是否误把完整连接 Key 或带连接码的字符串当成沙箱 ID,沙箱 ID 只取第一个 _ 之前的部分,并向用户确认站点地域
.site.env 不存在报告缺失并询问用户;不要擅自创建或用本地 .env 覆盖
启动 80 端口时报 Permission denied确认启动命令从第一次执行就使用 sudo -n,不要先用普通用户尝试绑定 80 端口
sudo 等待密码或提示需要终端改用 sudo -n;若 sudo -n true 失败,报告免密 sudo 配置异常,不要尝试输入密码
exec 在启动服务后不返回确认服务已后台运行,并把 stdin、stdout、stderr 全部重定向
站点内访问 80 端口失败检查 PID、日志、启动命令和监听地址,确认服务监听 0.0.0.0:80
公共 URL 返回 401 且响应体包含 Site protected这是访问码保护,不是服务故障;不要索取或使用访问码,交给客户自行输入验证;如需 AI 验证,先让客户临时关闭访问码
公共 URL 返回 403 且响应体包含 This site does not accept requests from your IP address访问来源 IP 被拒绝;请客户在星图控制台的站点空间页面检查该站点的 IP 白名单和黑名单配置,不要重试或更换出口 IP
公共 URL 返回 403 且响应体包含 Domain not allowed站点配置了自定义域名,只能通过该域名访问;CLI 无法获取该域名,不要猜测或拼接,请客户用自己配置的自定义域名访问并验证
公共 URL 返回 403 且响应体包含 Port not allowed站点只开放 80 端口;改回 80 端口访问,并确认服务监听 0.0.0.0:80
sandbox host 有输出但页面打不开不要据此宣布成功;先在站点内用 curl 验证,再检查进程和日志
CLI 低于 v1.3.2 且出现 DNS/代理错误按“准备并验证 CLI”只申请一次主机安装命令,将 CLI 升级到真实用户目录;回到 Default 沙箱重试一次,不要切到主机执行站点命令
CLI 已是 v1.3.2 或更高但仍出现 DNS/代理错误保持 Default 沙箱;如平台要求,只申请一次当前会话的网络授权并重试一次。仍失败则报告域名、端口和原始错误,不要继续申请主机执行权限

コメント