# Совместимость с S3

Storage Buckets доступны через **совместимый с S3 API**, что позволяет использовать существующие инструменты S3 — AWS CLI, `boto3`, `s5cmd` и большинство других S3 SDK — для работы с вашими бакетами без изменения кода. Запросы обрабатываются через шлюзовой сервис по адресу `https://s3.hf.co`.

S3 API — один из нескольких способов доступа к данным в бакете. Для доступа, нативного для Hugging Face (`hf` CLI, пути `hf://` и монтирование файловой системы) без отдельных S3-учётных данных, см. [Access Patterns](./storage-buckets-access).

> [!NOTE]
> API S3 работает только с [Storage Buckets](./storage-buckets). Он не предоставляет доступ к другим типам репозиториев Hugging Face (модели, наборы данных, Spaces).

## Генерация учётных данных S3

Шлюз выполняет аутентификацию с помощью ключей доступа в стиле AWS, полученных из [User Access Token](./security-tokens) Hugging Face.

1. Перейдите в [настройки токенов доступа](https://huggingface.co/settings/tokens). Если у вас ещё нет токена, создайте его с помощью кнопки **Create new token**. Права токена становятся правами учётных данных S3 — выберите **Read** для доступа только на чтение к вашим бакетам или **Write** для доступа на чтение и запись.
2. Найдите токен в списке, откройте его выпадающее меню и выберите **Generate S3 credentials**.

   
   
   
   

3. Скопируйте сгенерированный **идентификатор ключа доступа** (с префиксом `HFAK…`) и **секретный ключ доступа** в безопасное место — секрет отображается только один раз.

Учётные данные S3 наследуют разрешения базового токена доступа. Для токенов с детализированными правами ограничьте их область действия только теми пространствами имён и хранилищами, которые вы планируете использовать.

> [!TIP]
> Для автоматизированных рабочих процессов, обращающихся к бакетам организации, вы также можете генерировать учётные данные S3 из токена [service account](./enterprise-service-accounts#generating-s3-credentials), а не из User Access Token.

## Настройка клиента

Настройте ваш S3-клиент на использование конечной точки шлюза и задайте несколько обязательных параметров. В URL конечной точки укажите ваше **пространство имён** Hugging Face (имя пользователя или название организации) — см. раздел [Адресация бакетов](#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`                | Предотвращает ожидание контрольных сумм в ответах со стороны недавних клиентов |

Два параметра контрольных сумм важны для последних версий клиентов: AWS CLI ≥ 2.23 и недавние версии `boto3` по умолчанию отправляют контрольные суммы CRC32 в конце (через фрейминг `aws-chunked`), которые шлюз не обрабатывает. Эти параметры указывают клиенту отправлять контрольные суммы только в тех случаях, когда операция строго их требует.

Следующие параметры необязательны, но рекомендуются. При значении по умолчанию на стороне клиента 8 МБ большой файл разбивается на множество частей; значение 256 МБ означает значительно меньшее количество частей на загрузку, при этом каждая часть остаётся достаточно малой для эффективной обработки шлюзом:

| Настройка                  | Значение   |
|--------------------------|---------|
| `s3.multipart_threshold` | `256MB` |
| `s3.multipart_chunksize` | `256MB` |

### Пример: профиль AWS CLI

Добавьте профиль в `~/.aws/config`:

```ini
[profile hf]
region = us-east-1
endpoint_url = https://s3.hf.co/<namespace>
s3 =
    addressing_style = path
    multipart_threshold = 256MB
    multipart_chunksize = 256MB
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. Существует два способа обойти эту проблему:

**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. Рассматривайте пространство имён как бакет** и добавляйте имя 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` обычно отвечает HTTP-редиректом 302 на ближайший узел CDN Hugging Face, а не передаёт байты напрямую.

Некоторые SDK не следуют перенаправлениям с конечной точки S3, поэтому шлюз определяет клиентов, идентифицирующих себя как `aws-cli`, `botocore` (что покрывает `boto3`), или `aws-sdk-rust` и проксирует данные для них через себя. Все остальные клиенты (`rclone`, `s5cmd`, `curl`, AWS Go SDK и т. д.) получают ответ 302 и следуют ему нативно, исключая шлюз из пути данных для более быстрого скачивания.

### Именование ключей объектов

Ключи объектов в Bucket более ограничены, чем в S3. Ключ не должен **содержать**:

- начинается или заканчивается на `/`
- содержат последовательные слэши (`//`)
- содержат последовательности `../`
- начинается с `./`
- заканчиваются на `..`
- содержат обратные слэши (`\`) или нулевые байты (`\0`)

### ListObjects

- `ListObjectsV1` не поддерживается — используйте `ListObjectsV2`. Обратите внимание, что некоторые клиенты (например, rclone) могут требовать настройки для использования исключительно `ListObjectsV2`.
- В качестве разделителя допускается только `/`.

### Другие различия в API

- **Метаданные объекта**: произвольные пользовательские метаданные (`x-amz-meta-*`) не сохраняются и не возвращаются. Поддерживается `Content-Type`.
- **Неподдерживаемые функции**: ACL, политики хранения, метки объектов, версионирование объектов, правила жизненного цикла, серверное шифрование (SSE) и уведомления о событиях в хранилище не поддерживаются. Объекты всегда сообщаются с классом хранения `STANDARD`. Соответствующие заголовки и параметры запроса принимаются, но игнорируются.
- **CopyObject**: серверное копирование работает только в пределах одного пространства имён. Копирование между пространствами имён и `UploadPartCopy` (копирование части из существующего объекта в multipart-загрузку) не поддерживаются.
- **Условные запросы**: предикаты `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/) — удобный способ копирования данных между двумя хранилищами, совместимыми с S3, поэтому он хорошо подходит для переноса существующего бакета AWS S3 (или любого другого источника, совместимого с S3) в Storage Bucket.

> [!TIP]
> Переносите большой набор данных? При монтировании источника и запуске `hf sync` дедупликация выполняется на стороне клиента, поэтому обычно загружается меньше байтов, чем при использовании rclone. См. [Руководство по миграции](./storage-buckets-migration).

Идея состоит в том, чтобы объявить два удалённых хранилища — исходный бакет и шлюз Hugging Face — и позволить `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
```

Второй указывает на шлюз Hugging Face. Как и в случае с любым другим клиентом, ограничьте конечную точку вашим [пространством имён](#addressing-buckets), используйте адресацию по `path`, принудительно включите ListObjectsV2 (единственную поддерживаемую шлюзом версию перечисления) и установите размер части 256 МБ. Это значительно больше значения 5 МБ по умолчанию в rclone, поэтому крупные файлы загружаются меньшим количеством частей, а размер остаётся достаточно малым для эффективной обработки шлюзом и контроля за использованием памяти rclone (он удерживает в памяти 4 части на передачу):

```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 = 256M
chunk_size = 256M
```

Примечание: замените `<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, а данные хранятся в вашем бакете. Установите DVC с поддержкой S3 (`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]
> Используйте свой [namespace](#addressing-buckets) в `endpointurl` и имя «голого» бакета в URL `s3://`.

