Environment の config.storage.buckets[] に、所有する Alibaba Cloud OSS バケットを設定できます。この Environment で作成した Session は、各バケット(またはそのプレフィックス)をサンドボックスの /mnt/buckets/<name> にマウントします。Agent はローカルディレクトリと同様に読み書きできます。
マウントは Environment 単位の設定です。Session は作成時の設定のスナップショットを使用するため、その後 Environment を変更しても既存の Session には影響しません。
- 1 つの Environment に設定できるバケットは最大 8 個です。
- Alibaba Cloud OSS のみをサポートします(
provider: "aliyun-oss")。
- 読み取り専用と読み書きの両方に対応します。
- 読み取りは署名付き URL を使って OSS から直接ダウンロードし、書き込みはマルチパートアップロードで OSS に直接送信します(1 MiB 未満の書き込みは Qoder が中継します)。
- RAM ロールや AccessKey がサンドボックスに渡されることはありません。
この機能は Beta です。Environment の作成または更新後の config.storage.buckets が空でない場合、リクエストヘッダー x-qoder-beta: oss-bucket-2026-09-23 が必要です。Environment に初めてバケットを追加する場合、アカウントが Beta の利用対象(許可リストへの登録または全体公開)である必要もあります。対象外の場合は 503 feature_not_available が返されます。すべてのバケットを削除する場合、このヘッダーは不要です。
設定フィールド
config.storage で使用できるフィールドは buckets のみです。cloud Environment でのみ有効です。
{
"type": "cloud",
"storage": {
"buckets": []
}
}
各バケットのフィールド:
| フィールド | 型 | 必須 | 説明 |
|---|
name | string | はい | マウントディレクトリ名(/mnt/buckets/<name>)。英数字、.、_、- の 1~63 文字で、先頭は英数字。Environment 内で一意であること |
provider | string | はい | 固定値 "aliyun-oss" |
region | string | はい | cn-hangzhou や ap-southeast-1 などの OSS リージョン ID。リージョン ID のみ指定でき、カスタムエンドポイントは使用不可 |
bucket | string | はい | バケット名。/、*、? は使用不可 |
prefix | string | いいえ | このプレフィックス配下のオブジェクトのみをマウント。先頭と末尾の / は無視され、省略するとバケット全体をマウント。*、?、\、NUL、空のセグメント、.、.. は使用不可 |
access | string | いいえ | read_only(デフォルト)または read_write |
accelerator_endpoint | string | いいえ | <label>.oss-data-acc.aliyuncs.com 形式の OSS アクセラレーターホスト。バケットとサンドボックスが同じリージョンにある場合のみ使用 |
credential | object | はい | バケットの認証情報。認証情報を参照 |
同じリクエスト内で name は一意である必要があります。region + bucket + prefix が同じバケットを 2 つ指定すると拒否されます。
リクエストフィールドは厳密に検証されます。未知のフィールド、大文字と小文字が異なるキー、型が不正な値は 400 エラーになります。
設定例
2 つのバケットを持つ Environment を作成します。
curl -s -X POST "https://api.qoder.com/api/v1/cloud/environments" \
-H "Authorization: Bearer $QODER_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-H "x-qoder-beta: oss-bucket-2026-09-23" \
-d '{
"name": "with-oss-buckets",
"config": {
"type": "cloud",
"storage": {
"buckets": [
{
"name": "datasets",
"provider": "aliyun-oss",
"region": "cn-hangzhou",
"bucket": "my-bucket",
"prefix": "team/data/",
"access": "read_only",
"credential": {
"type": "ram_role",
"role_arn": "acs:ram::1234567890123456:role/qoder-oss-mount"
}
},
{
"name": "outputs",
"provider": "aliyun-oss",
"region": "cn-hangzhou",
"bucket": "my-bucket",
"prefix": "team/outputs/",
"access": "read_write",
"credential": {
"type": "access_key",
"access_key_id": "LTAI5tExampleAccessKey",
"access_key_secret": "ExampleSecret"
}
}
]
}
}
}'
レスポンスには、認証情報の読み取り用ビューのみが返されます。
{
"id": "env_019e44eb66bb748cabcd1489f6fa4428",
"type": "environment",
"name": "with-oss-buckets",
"description": "",
"config": {
"type": "cloud",
"storage": {
"buckets": [
{
"name": "datasets",
"provider": "aliyun-oss",
"region": "cn-hangzhou",
"bucket": "my-bucket",
"prefix": "team/data/",
"access": "read_only",
"credential": {
"type": "ram_role"
}
},
{
"name": "outputs",
"provider": "aliyun-oss",
"region": "cn-hangzhou",
"bucket": "my-bucket",
"prefix": "team/outputs/",
"access": "read_write",
"credential": {
"type": "access_key",
"access_key_id": "LTAI****sKey"
}
}
]
}
},
"metadata": {},
"archived_at": null,
"created_at": "2026-10-21T08:00:00.000000Z",
"updated_at": "2026-10-21T08:00:00.000000Z"
}
認証情報
credential.type には ram_role(推奨)または access_key を指定します。
RAM ロール(推奨)
- Alibaba Cloud アカウントに、Qoder が引き受ける RAM ロールを作成します。信頼ポリシーで Qoder サービスロールによる引き受けを許可する必要があります。Qoder サービスロールの情報はサポートにお問い合わせください。
sts:ExternalId で呼び出し元を制限します。
| Session の所有者 | sts:ExternalId |
|---|
| 個人ユーザー | ユーザー ID |
| 企業(サービスアカウント) | <organization ID>@<workspace ID> |
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"RAM": ["<Qoder service role ARN>"]
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": ["<your user ID or organization ID@workspace ID>"]
}
}
}
]
}
- ロールの ARN を
credential.role_arn に設定します。
Qoder は、宣言されたバケット、プレフィックス、アクセスモードに権限を限定するセッションポリシーも付与します。ロール自体にも権限のアクションを許可する必要があります。有効な権限は両方のポリシーで許可される範囲です。
AccessKey
専用の RAM ユーザーの AccessKey を使用し、以下のポリシーを付与してください。ルートアカウントの AccessKey は使用しないでください。
- AccessKey は Environment 設定とともに保存され、その後作成される Session のスナップショットに含まれます。
- Environment の読み取りでは、マスクされた
access_key_id(例:LTAI****sKey)のみが返されます。access_key_secret は返されません。
- AccessKey のローテーションは、その後作成される Session にのみ影響します。
- STS セッションポリシーはありません。Qoder がプレフィックスと読み取り専用の制限を適用し、ストレージ側の権限は AccessKey 自体の RAM ポリシーで決まります。
更新時の認証情報の保持
config は全体が置き換えられますが、storage.buckets[].credential は書き込み専用で、バケットの name ごとに保持されます。
- バケットの
credential を省略するか、読み取ったマスク済みの認証情報をそのまま送信すると、保存済みの認証情報が保持されます。
- バケット名の変更は新しいバケットの作成として扱われ、完全な認証情報が必要です。
credential.type を変更するか、"credential": null を送信する場合は、完全な新しい認証情報が必要です。
- 配列からバケットを削除するか、
"buckets": [] を送信すると、その後作成される Session ではマウントされなくなります。既存の Session は作成時のスナップショットを保持します。
バケットのマウント許可
バケットの所有者は、Qoder によるマウントを明示的に許可する必要があります。許可にはバケットタグと任意のアクセスリストファイルを使用します。少なくとも一方でマウントを許可する対象を指定しないと、マウントは拒否されます。
OSS コンソールでバケットにタグを追加します。ユーザー ID、組織 ID、ワークスペース ID は Qoder コンソールで確認できます。
| タグ | 必須 | 説明 |
|---|
qoder-mount | はい | enabled を指定し、Qoder によるバケットのマウントを許可 |
qoder-mount-users | いいえ | マウントを許可する個人ユーザー ID(カンマ区切り) |
qoder-mount-organizations | いいえ | マウントを許可する組織 ID(カンマ区切り) |
qoder-mount-workspaces | いいえ | マウントを許可するワークスペース ID(カンマ区切り) |
ルール:
- タグ値の上限は 128 文字です。少数の ID を指定する場合に使用してください。
- 個人の Session は
qoder-mount-users のみ、企業の Session は qoder-mount-organizations のみと照合します。名前空間が異なるため、同じ文字列の ID でも相互にアクセスは許可されません。
qoder-mount-workspaces を設定した場合、Session のワークスペースが一致する必要があります。
- 制限タグが存在する場合、設定されたすべてのディメンションが一致する必要があります。
- タグは約 1 分間キャッシュされます。読み取りに失敗した場合、以前の値を最大 10 分間使用します。明示的な拒否(403)は直ちに適用されます。
アクセスリスト(任意)
Agent または Session ごとに細かく制御するには、マウントディレクトリの隣にアクセスリストファイルを配置します。このファイルはマウントディレクトリの外にあるため、サンドボックスからの参照や変更はできません。
- ファイル名:
<末尾のスラッシュを除いた prefix>.qoder-acl.json。例えば、prefix が team/data/ の場合は team/data.qoder-acl.json です。
- バケット全体のマウント(
prefix なし)ではアクセスリストは使用できず、タグのみで制御します。
- マウントディレクトリと同じ階層のファイルのみを読み取り、親ディレクトリのリストは参照しません。
{
"version": 1,
"grants": [
{"users": ["<user ID>"]},
{"organizations": ["<organization ID>"], "workspaces": ["<workspace ID>"], "agents": ["<agent ID>"], "sessions": ["<session ID>"]}
]
}
ルール:
users、organizations、workspaces、agents、sessions の 5 つのディメンションをサポートします。
- 1 つの grant 内では、設定されたすべてのディメンションが一致する必要があります。未設定のディメンションは制限なし、空の配列は誰にも一致しません。
- いずれかの grant に一致すれば許可されます。一致する grant がなければ 403 で拒否されます。
- タグとアクセスリストの両方を設定した場合、両方に一致する必要があります。
- 64 KB を超えるファイル、不正な version 1 JSON、未知のキー、
null の grant、空でない文字列の配列以外のディメンションは拒否されます。
agents と sessions はマウント時に検証され、Environment の保存時には検証されません。
- リストは約 1 分間キャッシュされます。期限切れ後に読み取りが失敗した場合、以前の値を最大 10 分間使用します。403 の場合は以前の値を使用しません。
- ファイルが存在しなくてもエラーにはなりませんが、その場合はタグでマウントを許可する対象を指定する必要があります。
RAM ロールまたは RAM ユーザーに最小限の権限を付与します。
| アクション | 用途 | 必要なアクセスモード |
|---|
oss:ListObjects | ディレクトリの一覧取得 | 読み取り専用 / 読み書き |
oss:GetBucketTagging | バケットタグの読み取り(マウント許可) | 読み取り専用 / 読み書き |
oss:GetObject | ファイル、アクセスリスト、名前変更元の読み取り | 読み取り専用 / 読み書き |
oss:HeadObject | ファイル情報の取得(stat) | 読み取り専用 / 読み書き |
oss:PutObject | ファイルの書き込み、マルチパートアップロード、ディレクトリの作成、名前変更先の書き込み | 読み書きのみ |
oss:DeleteObject | ファイルと空ディレクトリの削除、名前変更元の削除 | 読み書きのみ |
oss:AbortMultipartUpload | 中断したアップロードのパートの削除 | 読み書きのみ |
oss:ListParts | アップロード完了前のパート確認。この権限がないと大きなファイルの書き込みが失敗 | 読み書きのみ |
読み取り専用ポリシーの例(prefix は team/data/):
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": ["oss:ListObjects", "oss:GetBucketTagging"],
"Resource": ["acs:oss:*:*:my-bucket"]
},
{
"Effect": "Allow",
"Action": ["oss:GetObject", "oss:HeadObject"],
"Resource": ["acs:oss:*:*:my-bucket/team/data/*"]
},
{
"Effect": "Allow",
"Action": ["oss:GetObject"],
"Resource": ["acs:oss:*:*:my-bucket/team/data.qoder-acl.json"]
}
]
}
読み書きのマウントでは、2 つ目の statement の Action に oss:PutObject、oss:DeleteObject、oss:AbortMultipartUpload、oss:ListParts も必要です。
保存時の検証
Environment の保存時(作成時、または更新でバケットを追加・変更した場合)、Qoder は保存を行うユーザーの ID と送信された認証情報を使ってマウントを検証します。
- 認証情報を取得します(ロールの引き受けまたは AccessKey の使用)。
- バケットタグを読み取ります。
- アクセスリストがあれば読み取ります。
- プレフィックスの一覧を 1 回取得します(
max-keys=1)。
新規または変更されたバケットのみを検証します。変更のないバケットは再検証しません。検証は 15 秒でタイムアウトします。
- 設定または権限が拒否された場合、400
invalid_request_error と Bucket '<name>' cannot be mounted: <reason>. などのメッセージを返します。
- OSS / STS が利用できない場合、503
api_error を返します。再試行できます。
- アクセスリストの
agents / sessions は保存時には検証せず、マウント時に検証します。
サンドボックス内での動作
マウント先は /mnt/buckets/<name> です。access: read_only では読み取り専用のファイルシステムとなり、read_write ではファイルの作成、変更、削除ができます。
- ディレクトリ:オブジェクトストレージには実際のディレクトリはありません。オブジェクトキーのプレフィックスがディレクトリを表します。空のディレクトリは、OSS コンソールや ossutil と同様に、0 バイトの
<path>/ プレースホルダーオブジェクトで保持されます。
- 読み取り:Qoder は署名付き URL への 302 を返し、サンドボックスは OSS から直接ダウンロードします。
- 書き込み:1 MiB 未満のファイルは Qoder が中継する通常のアップロード、1 MiB 以上はマルチパートアップロードを使用します(サンドボックスが各パートを署名付き URL に PUT してから確定します)。
- 名前変更:単一ファイルの名前変更はコピーと削除で行われ、アトミックではありません。複数の Session が同じパスに同時に書き込むと、書き込みが失われることがあります。Qoder は Session 間の競合を調整しません。
- ディレクトリ名の変更:ネイティブには対応しておらず、クライアントがファイルを 1 つずつ移動します。
- ディレクトリの削除:空でないディレクトリは 409 を返します。先に中のファイルを削除してください。
- 一覧の上限:単一ディレクトリに 100,000 件を超えるエントリがある場合、一覧を省略せず 507 を返します。
- ファイルサイズの上限:直接アップロードは最大 10,000 パート × 64 MiB、つまり 625 GiB です。バケット自体のクォータと制限も適用されます。
- 中断したアップロード:中断した書き込みの未完了パートはバケットに残ります。削除用のライフサイクルルールを設定してください。
- リージョン:バケットとサンドボックスが同じリージョンなら OSS の内部エンドポイントを使用します。異なる場合はパブリックエンドポイントを使用するため、レイテンシーが高くなります。OSS アクセラレーターは同じリージョンでのみ使用できます。
- ネットワーク:読み取りと 1 MiB 以上の書き込みでは、サンドボックスが OSS に直接アクセスします。Environment でネットワークを制限している場合、対応する OSS ドメインを許可してください。
エラー
| HTTP | type | 説明 |
|---|
| 400 | invalid_request_error | バケットフィールドが不正、認証情報または x-qoder-beta ヘッダーがない、または保存時の検証で拒否された |
| 401 | authentication_error | PAT または SAT が無効または期限切れ |
| 403 | permission_error | 対象 Environment へのアクセス権限がない |
| 503 | feature_not_available | アカウントが oss_bucket Beta の利用対象外 |
| 503 | api_error | 保存時の検証で OSS / STS が一時的に利用不可。再試行可能 |
マウント時の拒否(バケットタグで許可されていない、アクセスリストに一致しない、認証情報に権限がないなど)は、サンドボックス内の EACCES として現れ、Environment API のエラーにはなりません。まずバケットタグ、アクセスリスト、RAM ポリシーを確認してください。
制限事項
- Alibaba Cloud OSS のみをサポートします。S3、COS、MinIO、カスタムエンドポイントには対応していません。
- Qoder はオブジェクトのバージョン、ライフサイクルルール、バケット ACL などの OSS 設定を管理しません。
- 1 つの Environment で同じバケットの同じ
prefix を複数回指定することはできません。同じバケットの複数のディレクトリをマウントする場合、異なる name と prefix を使用してください。
- マウントは Environment のスナップショットを使用するため、Environment を変更しても既存の Session は変わりません。