# S3 互換性

Storage Buckets は **S3 互換 API** 経由でアクセスでき、既存の S3 ツール（AWS CLI、`boto3`、`s5cmd`、およびその他のほとんどの S3 SDK）を、コードを変更せずにバケットに対して使用できます。リクエストは `https://s3.hf.co` のゲートウェイサービスを経由します。

S3 APIは、バケットデータにアクセスするための複数の方法の一つです。個別のS3認証情報なしでHugging Faceネイティブなアクセス（`hf` CLI、`hf://`パス、ファイルシステムマウント）を行う場合は、[アクセスパターン](./storage-buckets-access)を参照してください。

> [!NOTE]
> S3 APIは[Storage Buckets](./storage-buckets)でのみ動作します。その他のHugging Faceリポジトリタイプ（モデル、データセット、Spaces）は公開されていません。

## S3認証情報の生成

ゲートウェイは、Hugging Faceの[ユーザーアクセストークン](./security-tokens)から派生したAWSスタイルのアクセスキーを使用して認証を行います。

1. [アクセストークンの設定](https://huggingface.co/settings/tokens)に移動します。まだトークンを持っていない場合は、**新しいトークンの作成**ボタンでトークンを作成してください。トークンの権限がS3認証情報の権限となります。バケットへの読み取り専用アクセスには**Read**を、読み書きアクセスには**Write**を選択してください。
2. リストからトークンを見つけ、そのドロップダウンメニューを開いて、**Generate S3 credentials**を選択します。

   
   
   
   

3. 生成された**アクセスキーID**（`HFAK…`で始まる）と**シークレットアクセスキー**を安全な場所にコピーしてください。シークレットは一度のみ表示されます。

S3の認証情報は、基盤となるアクセストークンの権限を継承します。細粒度のトークンの場合、使用する予定のネームスペースとバケットにのみスコープを限定してください。

> [!TIP]
> 組織のバケットにアクセスする自動化ワークフローでは、User Access Token の代わりに、[サービスアカウント](./enterprise-service-accounts#generating-s3-credentials)トークンから S3 認証情報を生成することもできます。

## クライアントの構成

S3クライアントをゲートウェイエンドポイントに向かせ、必要なオプションをいくつか設定します。エンドポイントURLには、Hugging Faceの**namespace**（ユーザー名または組織名）を使用します。詳細は以下の[バケットのアドレス指定](#addressing-buckets)を参照してください。

| 設定                        | 値                          | なぜ                                                           |
|--------------------------------|--------------------------------|---------------------------------------------------------------|
| `endpoint_url`                 | `https://s3.hf.co/<namespace>` | あなたの名前空間にスコープが設定されたゲートウェイ                         |
| `region`                       | `us-east-1`                    | 必須。ゲートウェイは現在シングルリージョンです              |
| `s3.addressing_style`          | `path`                         | バケットはサブドメインではなく、パスセグメントとしてアドレス指定されます        |
| `request_checksum_calculation` | `when_required`                | 最近のクライアントが末尾チェックサムを送信することを防止します       |
| `response_checksum_validation` | `when_required`                | 最近のクライアントがレスポンスにチェックサムを期待することを防止します |

最近のクライアントでは、2つのチェックサム設定が重要です。AWS CLI ≥ 2.23 および最近の `boto3` バージョンは、デフォルトで末尾の CRC32 チェックサムを送信します（`aws-chunked` フレームワーク経由）。しかし、ゲートウェイはこれを解析しません。これらの設定により、クライアントは操作が厳密にチェックサムを要求する場合にのみ送信するようになります。

以下は任意ですが、大規模なアップロードでマルチパートの数をできるだけ少なくするために推奨されます:

| 設定                  | 値 |
|--------------------------|-------|
| `s3.multipart_threshold` | `2GB` |
| `s3.multipart_chunksize` | `2GB` |

### 例: AWS CLI プロファイル

`~/.aws/config` にプロファイルを追加します:

```ini
[profile hf]
region = us-east-1
endpoint_url = https://s3.hf.co/<namespace>
s3 =
    addressing_style = path
    multipart_threshold = 2GB
    multipart_chunksize = 2GB
request_checksum_calculation = when_required
response_checksum_validation = when_required
```
注: 上記の`<namespace>`は、バケットが保存されているユーザー名または組織名に置き換えてください。

プロファイルに対応する認証情報を`~/.aws/credentials`に追加します:

```ini
[hf]
aws_access_key_id = HFAK...
aws_secret_access_key = ...
```

その後、プロファイルを使用して任意の S3 コマンドを実行します:

```bash
aws --profile hf s3 ls
aws --profile hf s3 mb s3://my-bucket
aws --profile hf s3 cp ./model.safetensors s3://my-bucket/models/model.safetensors
```

## バケットの処理

AWS S3は、バケット名に対して単一のフラットでグローバルに一意な名前空間を使用しており、SDKはバケット名が`/`を含まないプレーンな文字列であることを前提としています。一方、Hugging Faceのバケットは`namespace/bucket`として識別され、`namespace`はユーザー名または組織名です。この追加の階層がS3クライアントとの不一致を引き起こします。多くのクライアントはバケット名に`/`を受け入れないか、正しくURLエスケープしません。この問題を回避するには、2つの方法があります。

**1. エンドポイント URL に名前空間を含める**（ほとんどのケースで推奨）。これにより、すべての操作がその名前空間にスコープが設定され、クライアントに渡すバケット名は HF バケット名のみで済みます。自分のバケットや単一の組織内のバケットには有効ですが、名前空間をまたぐ場合は機能しなくなります。例えば、個人バケットから組織バケットへのサーバーサイドのコピーなどが該当します。

```bash
aws --endpoint-url https://s3.hf.co/my-org s3api get-object \
  --bucket my-bucket --key some/object.txt ./object.txt
```

**2. namespace をバケットとして扱う**方法で、オブジェクトキーの先頭に HF バケット名を付加します。これによりオブジェクトレベルの操作（アップロード、ダウンロード）は機能しますが、バケットの作成や削除などのバケットレベルの操作では問題が発生します。

```bash
aws --endpoint-url https://s3.hf.co s3api get-object \
  --bucket my-org --key my-bucket/some/object.txt ./object.txt
```

## AWS S3との制限事項および違い

Storage Buckets はすべての S3 の概念をモデル化していないため、一部の動作が異なるか、サポートされていない場合があります。

### オブジェクトのダウンロード

ゲートウェイは現在、単一リージョン構成です。ダウンロードパフォーマンスを向上させるため、`GetObject` は通常、バイトを直接配信するのではなく、最も近い Hugging Face CDN エッジへの HTTP 302 リダイレクトで応答します。

一部のSDKはS3エンドポイントからのリダイレクトに従わないため、ゲートウェイは`aws-cli`、`botocore`（`boto3`を含む）、または`aws-sdk-rust`と識別されるクライアントを検出し、それらのためにデータをゲートウェイ経由でプロキシします。その他のすべてのクライアント（`rclone`、`s5cmd`、`curl`、AWS Go SDKなど）は302を受け取り、ネイティブに従うため、ゲートウェイをデータパスから外し、より高速なダウンロードを実現します。

### オブジェクトキーの命名

バケットのオブジェクトキーはS3よりも制限が厳しく、キーは以下を満たさ**ない**必要があります:

- `/`で始まるか終わる
- 連続スラッシュ(`//`)を含む
- `../` シーケンスを含む
- `./`で始まる
- `..`で終わる
- バックスラッシュ (`\`) またはヌルバイト (`\0`) を含む

### ListObjects

- `ListObjectsV1` はサポートされていません。`ListObjectsV2` を使用してください。一部のクライアント（rclone など）では、`ListObjectsV2` のみを使用するように設定する必要がある場合があります。
- 区切り文字として許可されているのは`/`のみです。

### その他のAPIの違い

- **オブジェクトメタデータ**: ユーザーが任意に設定するメタデータ (`x-amz-meta-*`) は保存も返却もされません。 `Content-Type` はサポートされています。
- **サポートされていない機能**: ACL、バケットポリシー、オブジェクトタグ付け、オブジェクトバージョニング、ライフサイクルルール、サーバーサイド暗号化（SSE）、バケット通知はサポートされていません。オブジェクトは常に`STANDARD`ストレージクラスとして報告されます。関連するリクエストヘッダーおよびパラメーターは受け入れられますが、無視されます。
- **CopyObject**: サーバーサイドコピーは、単一のネームスペース内でのみ動作します。ネームスペースをまたぐコピーおよび`UploadPartCopy`（既存のオブジェクトからマルチパートアップロードにパートをコピーする操作）はサポートされていません。
- **条件付きリクエスト**: `If-Match` / `If-None-Match` の前提条件は、`PutObject` および `CopyObject` のコピー元では尊重されますが、`GetObject` では尊重されません。
- **マルチパートアップロードの有効期限**: 完了または中止されないまま進行中のマルチパートアップロードは、7日後に自動的に期限切れとなり、クリーンアップされます。

## 例

一般的なタスク向けの実際のレシピです。それぞれは、上記の[クライアント設定](#configuring-a-client)を基に構築されています。

### `boto3`での読み書き

[`boto3`](https://docs.aws.amazon.com/boto3/latest/) は、上記の[クライアント設定](#configuring-a-client)でゲートウェイに対して動作します。`<namespace>`をユーザー名または組織名に置き換えてください:

```python
import boto3
from botocore.config import Config

s3 = boto3.client(
    "s3",
    endpoint_url="https://s3.hf.co/<namespace>",
    aws_access_key_id="HFAK...",
    aws_secret_access_key="...",
    config=Config(
        region_name="us-east-1",
        s3={"addressing_style": "path"},
        request_checksum_calculation="when_required",
        response_checksum_validation="when_required",
    ),
)

s3.upload_file("model.safetensors", "my-bucket", "models/model.safetensors")
s3.download_file("my-bucket", "models/model.safetensors", "model.safetensors")
```

### DuckDBでバケットをクエリする

DuckDB 2.0以降では、`httpfs`拡張機能により`hf://buckets/`パスを直接読み取ることができ、`hf`拡張機能を使用すればBucketsへの書き込みも可能です。[DuckDBでのクエリ](./storage-buckets-access#query-with-duckdb)を参照してください。

DuckDBの以前のバージョンの場合、または拡張機能なしで`COPY ... TO`を使用してクエリ結果をバケットに書き戻す場合は、代わりにS3ゲートウェイ経由で実行してください:

```sql
INSTALL httpfs;
LOAD httpfs;

CREATE SECRET hf (
    TYPE s3,
    KEY_ID 'HFAK...',
    SECRET '...',
    ENDPOINT 's3.hf.co/<namespace>',
    URL_STYLE 'path',
    REGION 'us-east-1'
);

SELECT * FROM read_parquet('s3://my-bucket/data.parquet');
```

> [!NOTE]
> `URL_STYLE 'path'` は必須です。これを指定しないと、DuckDB は仮想ホスト形式のアドレス指定（`my-bucket.s3.hf.co`）を使用しますが、ゲートウェイではこれをサポートしていません。その場合、「Could not resolve hostname」エラーが発生します。

### `rclone`を使用してデータをインポートします

[`rclone`](https://rclone.org/)は、2つのS3互換ストレージ間でデータをコピーする便利な方法であり、既存のAWS S3バケット（または任意のS3互換ソース）をStorage Bucketへ移行する用途に最適です。

アイデアは、ソースバケットと Hugging Face ゲートウェイという2つのリモートを宣言し、`rclone` がオブジェクトをストリーミングで転送できるようにすることです。両方のリモートを `~/.config/rclone/rclone.conf` に追加します。最初のものは既存の S3 バケットを指します。ソースに合わせて調整してください（ここではプレーンな AWS S3 を想定しています）:

```ini
[aws]
type = s3
provider = AWS
access_key_id = AKIA...
secret_access_key = ...
region = us-east-1
```

2番目のポイントは Hugging Face のゲートウェイを指しています。他のクライアントと同様に、エンドポイントを[namespace](#addressing-buckets)にスコープし、`path` アドレッシングを使用し、ListObjectsV2 を強制（ゲートウェイがサポートする唯一のリスト表示バージョン）し、マルチパートのサイズを大きくしてアップロードで使用するパート数を最小限に抑えてください:

```ini
[hf]
type = s3
provider = Other
endpoint = https://s3.hf.co/<namespace>
access_key_id = HFAK...
secret_access_key = ...
region = us-east-1
force_path_style = true
list_version = 2
upload_cutoff = 2G
chunk_size = 2G
```

注: 上記の`<namespace>`は、バケットが保存されているユーザー名または組織名に置き換えてください。また、アクセストークンから生成された[S3認証情報](#generating-s3-credentials)を使用してください。宛先バケットは、その名前空間の下に既に存在している必要があります。

次に、ソースバケットをStorage Bucketにコピーします:

```bash
rclone copy aws:my-source-bucket hf:my-bucket --progress
```

`rclone copy` は、転送先で欠落しているか変更されたオブジェクトのみを転送するため、中断されたインポートを再開したり、新しいオブジェクトを取得したりするために再実行しても安全です。ソースに存在しなくなったオブジェクトを転送先から削除して、転送先をソースの完全なミラーにするには、代わりに`rclone sync`を使用します:

```bash
rclone sync aws:my-source-bucket hf:my-bucket --progress
```

> [!TIP]
> 大規模なインポートを行う場合は、`--transfers` と `--checkers` を追加して並行度を上げてください（例: `--transfers 16 --checkers 16`）。その後、`rclone check aws:my-source-bucket hf:my-bucket` を実行して、すべてのオブジェクトが正常に転送されたことを確認してください。

### DVCでバージョン管理

[DVC](https://dvc.org/) は、リポジトリ内に小さなポインタファイルを保持し、実際のデータをリモートにプッシュすることで、git 上でデータセットとモデルのバージョン管理を行います。バケットはゲートウェイを介して DVC リモートとして機能するため、コードと`.dvc` ポインタは git に残ったまま、データはバケットに格納されます。S3 対応の DVC をインストール（`pip install 'dvc[s3]'`）し、上記の[クライアント設定](#configuring-a-client)を使用してリモートを追加します。

```bash
dvc remote add -d hf-bucket s3://my-bucket/dvc-store
dvc remote modify hf-bucket endpointurl https://s3.hf.co/<namespace>
dvc remote modify hf-bucket region us-east-1
```

[S3認証情報](#generating-s3-credentials)を環境変数として渡すか、`dvc remote modify --local` を使用して渡すことで、gitに含めずに済みます:

```bash
export AWS_ACCESS_KEY_ID=HFAK...
export AWS_SECRET_ACCESS_KEY=...
```

その後、通常通りトラッキング、プッシュ、プルを行います — `dvc push` はバケットにアップロードし、新しいクローンでの `dvc pull` はそれをダウンロードします:

```bash
dvc add data/
git add data.dvc .gitignore .dvc/config && git commit -m "Track data with DVC"
dvc push
```

> [!NOTE]
> `endpointurl` には [namespace](#addressing-buckets) を、`s3://` URL にはバケット名のみを使用してください。

