# Migrando dados para buckets de armazenamento

Este guia mostra como mover grandes conjuntos de dados para um [Storage Bucket](./storage-buckets) de onde eles estão atualmente: disco local, outra nuvem ou o Hub. Encontre sua origem na tabela abaixo e vá para a seção correspondente.

Sempre que possível, faça com que seus dados sejam legíveis como um sistema de arquivos e execute `hf sync`. Ele remove duplicatas no cliente, de modo que você envia menos bytes do que em uma cópia bruta.

## Visão geral

| Onde seus dados estão agora | Recomendado | Alternativas |
|---|---|---|
| Disco local ou sistema de arquivos do cluster | [`hf sync`](#from-local-disk-or-a-cluster-filesystem) | — |
| AWS S3 ou compatível com S3 (R2, MinIO) | [Monte com `mount-s3` e, em seguida, execute `hf sync`](#from-aws-s3-or-s3-compatible-storage) | [rclone por meio do gateway S3](#alternative-rclone-through-the-s3-gateway) |
| Google Cloud Storage | [Monte com `gcsfuse` e depois execute `hf sync`](#from-google-cloud-storage-or-azure-blob-storage) | rclone, ou um [Job](#run-the-migration-in-the-background-with-jobs) |
| Azure Blob Storage | [Monte com `blobfuse2` e depois execute `hf sync`](#from-google-cloud-storage-or-azure-blob-storage) | rclone, ou um [Job](#run-the-migration-in-the-background-with-jobs) |
| Um repositório do Hub ou outro bucket | [`hf buckets cp` (lado do servidor)](#from-a-hub-repository-or-another-bucket) | — |
| Prefixo S3 muito grande | [hf-s3ream (alpha)](#very-large-s3-prefixes-with-hf-s3ream) | Mount + `hf sync`, [dividido por subcaminho](#split-by-subpath-experimental) |

Por que `hf sync` é o padrão:

- **Você faz upload de menos.** `hf sync` faz upload por meio do cliente [Xet](./xet/index), que divide e deduplica seus dados primeiro, de modo que apenas os blocos que o Hub ainda não viu são enviados. Uma cópia bruta (por exemplo, rclone por meio do gateway S3) transfere cada byte.
- **É pelo menos tão rápido.** Nas migrações que suportamos até agora, o `hf sync` sobre uma fonte montada igualou ou superou o rclone em throughput.

## Antes de começar

Todos os comandos neste guia usam `hf`, o [Hugging Face CLI](https://huggingface.co/docs/huggingface_hub/guides/cli). A saída de ajuda é legível por agentes, então um agente de código pode montar e monitorar uma migração para você (veja [CLI para Agentes de IA](./agents-cli)). Revise os comandos antes de executá-los em escala.

1. **Instale o CLI.** O cliente Xet é distribuído junto com ele.

   ```bash
   curl -LsSf https://hf.co/cli/install.sh | bash
   hf version
   ```

2. **Faça login** com um token que tenha acesso de **Escrita** ([crie um](https://huggingface.co/settings/tokens)):

   ```bash
   hf auth login
   hf auth whoami
   ```

3. **Crie o bucket de destino.** `<namespace>` é seu nome de usuário ou organização. Sem `--region`, o bucket é criado na [região de armazenamento](./storage-regions) padrão do namespace, que é sempre os EUA fora dos planos Team & Enterprise. Nesses planos, passe `--region us` ou `--region eu` para escolher.

   ```bash
   hf buckets create <namespace>/<bucket> --private
   ```

> [!TIP]
> Comece com uma execução de teste. Independentemente do caminho que você usar, ensaie-o em um subconjunto pequeno (uma pasta, ou um padrão `--include`), verifique o resultado com `--dry-run` e `hf buckets ls` e, em seguida, inicie a migração completa. Todos os caminhos neste guia podem ser retomados, portanto, uma execução de teste não tem custo.

## De um disco local ou de um sistema de arquivos de cluster

Use isso quando seus dados estiverem em um disco local, um volume anexado ou no scratch do cluster: qualquer coisa que a máquina possa ler como arquivos. Este também é o último passo de todos os caminhos de nuvem abaixo, uma vez que a origem esteja montada.

```bash
hf sync ./data hf://buckets/<namespace>/<bucket>/data
```

`hf sync` compara a origem e o destino e transfere apenas a diferença, portanto, reexecutar o mesmo comando retoma uma migração interrompida: os arquivos já enviados são ignorados. Variantes comuns:

```bash
# Mirror exactly: also delete destination files that are gone from the source
hf sync ./data hf://buckets/<namespace>/<bucket>/data --delete

# Preview what would transfer, without uploading
hf sync ./data hf://buckets/<namespace>/<bucket>/data --dry-run

# Only some files
hf sync ./data hf://buckets/<namespace>/<bucket>/data --include "*.parquet" --exclude "tmp/*"
```

Para revisar uma migração de grande porte antes de executá-la, escreva o plano em um arquivo, verifique-o e, em seguida, aplique-o. Isso varre a origem e o destino uma única vez, em vez de uma vez para uma simulação e outra para a execução real.

```bash
hf sync ./data hf://buckets/<namespace>/<bucket>/data --plan plan.jsonl   # scan once, write the plan
hf sync --apply plan.jsonl                                                # run exactly that plan
```

Execute `--apply` a partir do diretório onde você criou o plano, pois o plano registra o caminho de origem exatamente como você o digitou. `--apply` não verifica o que já foi enviado, portanto, para retomar uma execução interrompida, execute novamente o comando simples `hf sync`.

Para verificar, confira se uma execução de teste não tem mais nada para transferir e verifique o conteúdo:

```bash
hf sync ./data hf://buckets/<namespace>/<bucket>/data --dry-run
hf buckets ls hf://buckets/<namespace>/<bucket>/data
```

### Ajuste

- **Mantenha o cache em um disco rápido.** O cliente Xet faz o cache de blocos e de um índice de deduplicação (o cache de shard) em `HF_HOME`. Aponte `HF_HOME` para um NVMe local se o seu diretório home não estiver em um.
- Ative o **modo de alto desempenho** para migrações em massa em uma máquina com recursos abundantes. `HF_XET_HIGH_PERFORMANCE=1` aumenta a concorrência, os tamanhos de buffer e o número de arquivos ingeridos de uma vez, permitindo que o cliente utilize todos os núcleos de CPU e sature a rede. Ele é destinado a máquinas com alta largura de banda e disco rápido; com versões do `hf_xet` anteriores à 1.7.0, use-o apenas com pelo menos 64 GB de RAM (verifique o seu com `hf env`). Consulte [Variáveis de Ambiente](./xet/using-xet-storage#environment-variables).
- **Limite do cache de shards.** Seu limite de tamanho é flexível: o cache é reduzido apenas no início de uma execução, portanto, dentro de uma única execução longa, ele pode crescer bem além do limite. Em uma migração grande, especialmente no modo de alto desempenho, ele pode crescer para centenas de GB e encher o disco, interrompendo a execução. Defina `HF_XET_SHARD_CACHE_SIZE_LIMIT` confortavelmente abaixo do seu espaço livre em disco, mas não menor do que o necessário: um cache de tamanho *X* deduplica em relação a aproximadamente 1000 × *X* de dados. Veja [Shard Cache](./xet/using-xet-storage#shard-cache).

Defina esses valores antes de iniciar a sincronização. Os tamanhos aceitam valores legíveis por humanos, como `64gb`:

```bash
export HF_HOME=/mnt/nvme/hf                 # chunk and shard caches on NVMe
export HF_XET_HIGH_PERFORMANCE=1            # use all cores and the full network
export HF_XET_SHARD_CACHE_SIZE_LIMIT=64gb   # keep the shard cache under free disk space

hf sync ./data hf://buckets/<namespace>/<bucket>/data
```

### Dividir por subcaminho (experimental)

Para conjuntos de dados muito grandes, você pode dividir a origem em subcaminhos e executar vários processos `hf sync` simultaneamente. Testes iniciais sugerem que a taxa de transferência escala aproximadamente de forma linear, mas isso precisa de mais validação. Duas regras:

- Divida com base em dados relacionados, para que os arquivos de cada worker sejam deduplicados de forma eficaz entre si.
- Dê a cada worker seu próprio `HF_HOME` para que eles não disputem o cache. Cada cache ocupa espaço em disco, então divida `HF_XET_SHARD_CACHE_SIZE_LIMIT` entre os workers.

```bash
HF_HOME=/mnt/nvme/hf-a hf sync ./data/groupA hf://buckets/<namespace>/<bucket>/groupA &
HF_HOME=/mnt/nvme/hf-b hf sync ./data/groupB hf://buckets/<namespace>/<bucket>/groupB &
wait
```

Um único processo compartilha um único cache e deduplica melhor, portanto, divida apenas quando um processo não consegue saturar sua rede.

### Solução de problemas

| Sintoma | Corrigir |
|---|---|
| `401` ou erro de autenticação | Execute `hf auth login` com um token **Write** e verifique com `hf auth whoami`. |
| Mais lento do que o esperado | Coloque `HF_HOME` em NVMe, defina `HF_XET_HIGH_PERFORMANCE=1` e [execute perto dos seus dados](#where-to-run-a-large-migration). |
| A execução é interrompida com um erro de disco cheio | O cache de shards preencheu o disco. Defina `HF_XET_SHARD_CACHE_SIZE_LIMIT` abaixo do seu espaço livre ou mova `HF_HOME` para um disco maior. |
| Transferência interrompida | Execute novamente o mesmo comando `hf sync`. Os arquivos já enviados são ignorados. |

## De AWS S3 ou armazenamento compatível com S3

`hf sync` não lê URLs `s3://`, então monte o bucket de origem como um sistema de arquivos com [Mountpoint for Amazon S3](https://github.com/awslabs/mountpoint-s3) e, em seguida, sincronize a partir do mount. Seus dados ainda passam pelo cliente Xet, então você obtém deduplicação no lado do cliente.

```bash
mount-s3 my-source-bucket /mnt/src
hf sync /mnt/src hf://buckets/<namespace>/<bucket>
umount /mnt/src
```

Para stores compatíveis com S3, como Cloudflare R2 ou MinIO, adicione `--endpoint-url <url>` ao `mount-s3`. Para um bucket público que permite leituras anônimas, como aqueles no [registro AWS Open Data](https://registry.opendata.aws/), adicione `--no-sign-request`. A verificação, o ajuste fino e a solução de problemas são os mesmos que [para dados locais](#from-local-disk-or-a-cluster-filesystem).

### Alternativa: rclone através do gateway S3

Use isso se você já executa rclone e prefere não montar. A desvantagem: o rclone envia cada byte através do [gateway S3](./storage-buckets-s3) sem deduplicação no lado do cliente, então transfere mais do que `hf sync`. Você precisa de [credenciais S3](./storage-buckets-s3#generating-s3-credentials) para o gateway.

> [!WARNING]
> Use o rclone 1.70 ou mais recente (verifique com `rclone version`, faça o upgrade a partir de [rclone downloads](https://rclone.org/downloads/)). Versões mais antigas podem esgotar a memória ao listar buckets muito grandes. Conselhos antigos frequentemente recomendam [`--fast-list`](https://rclone.org/docs/#fast-list); com um rclone recente, você não precisa dele, e em um listagem enorme ele mantém tudo na memória e pode causar a mesma falha.

Adicione o gateway como um remoto em `~/.config/rclone/rclone.conf`, ao lado do remoto da sua origem (`aws` abaixo):

```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
```

O gateway suporta apenas ListObjectsV2, portanto `list_version = 2` é obrigatório. Com 256M de partes, arquivos grandes são divididos em muito menos partes do que com o padrão de 5M do rclone. O rclone mantém 4 partes por transferência em memória, portanto `--transfers 16` abaixo requer cerca de 16 GB de RAM; reduza esse valor em uma máquina menor. Em seguida, copie e verifique:

```bash
rclone copy aws:my-source-bucket hf:<bucket> --transfers 16 --checkers 16 --progress
rclone check aws:my-source-bucket hf:<bucket>
```

`rclone copy` transfere apenas objetos ausentes ou alterados, portanto é seguro reexecutar para retomar. Antes de uma importação grande, leia as [limitações do gateway](./storage-buckets-s3#limitations-and-differences-from-aws-s3), especialmente as regras de nomenclatura das chaves de objeto.

## Do Google Cloud Storage ou do Azure Blob Storage

Mesma abordagem que no S3: monte a origem com o driver próprio da nuvem e, em seguida, execute `hf sync`.

**Google Cloud Storage**: monte com [gcsfuse](https://cloud.google.com/storage/docs/gcsfuse).

```bash
gcsfuse my-gcs-bucket /mnt/src
hf sync /mnt/src hf://buckets/<namespace>/<bucket>
```

**Azure Blob Storage**: monte com [blobfuse2](https://learn.microsoft.com/azure/storage/blobs/blobfuse2-what-is). O arquivo de configuração nomeia sua conta de armazenamento e seu contêiner.

```bash
blobfuse2 mount /mnt/src --config-file=./blobfuse2.yaml
hf sync /mnt/src hf://buckets/<namespace>/<bucket>
```

Sem um mount, você pode usar o rclone (ele lê GCS e Azure nativamente; reutilize o remote `hf` [acima](#alternative-rclone-through-the-s3-gateway), com o mesmo compromisso de não deduplicação), ou [executar a migração como um Job](#run-the-migration-in-the-background-with-jobs).

## Execute a migração em segundo plano com Jobs

[Jobs](./jobs) executa um script na infraestrutura de computação do Hugging Face: você escolhe o hardware, inicia a execução pela CLI e [paga por minuto](./jobs-pricing). Use-o quando quiser que uma migração longa, de múltiplos TB, seja executada de forma autônoma, em vez de no seu laptop ou em uma sessão que você precisa manter aberta.

**1. Escreva o script de migração** (`migrate.py`). Este exemplo copia cada objeto em um prefixo do S3 para um bucket por meio do cliente Xet, de modo que as gravações sejam deduplicadas. Ele é adequado para uma cópia pontual de um prefixo de tamanho moderado; para prefixos muito grandes, consulte [hf-s3ream](#very-large-s3-prefixes-with-hf-s3ream). Adapte as configurações no topo:

```python
# /// script
# dependencies = ["huggingface_hub", "boto3", "tqdm"]
# ///
import boto3
from botocore import UNSIGNED
from botocore.config import Config
from huggingface_hub import HfFileSystem
from tqdm.contrib.concurrent import thread_map

# --- adapt these ---
SRC_BUCKET = "my-source-bucket"
SRC_PREFIX = "some/prefix/"
DST = "buckets/<namespace>/<bucket>"
WORKERS = 8   # files copied in parallel
# -------------------

s3 = boto3.client("s3")   # AWS credentials come from the Job's secrets
# For a public bucket (for example from the AWS Open Data registry), read anonymously
# instead, and drop the AWS secrets from the launch command:
# s3 = boto3.client("s3", config=Config(signature_version=UNSIGNED))
fs = HfFileSystem()       # HF token comes from the Job's HF_TOKEN secret

# List the destination once: {path: size} of the files already copied
done = {path: info["size"] for path, info in fs.find(DST, detail=True).items()}

# List the source and keep the objects not copied yet
todo = []
pages = s3.get_paginator("list_objects_v2").paginate(Bucket=SRC_BUCKET, Prefix=SRC_PREFIX)
for page in pages:
    for obj in page.get("Contents", []):
        key = obj["Key"]
        if key.endswith("/"):
            continue  # folder marker: bucket keys can't end with "/"
        if done.get(f"{DST}/{key}") != obj["Size"]:
            todo.append(key)

def copy(key):
    body = s3.get_object(Bucket=SRC_BUCKET, Key=key)["Body"]
    with fs.open(f"{DST}/{key}", "wb") as out:
        for chunk in iter(lambda: body.read(64 << 20), b""):
            out.write(chunk)

# Copy WORKERS files at a time, with a progress bar
thread_map(copy, todo, max_workers=WORKERS)
```

- Cada objeto é armazenado no disco do Job e enviado quando é fechado, portanto, o disco deve comportar `WORKERS` dos seus maiores objetos ao mesmo tempo. Aumente `WORKERS` para acelerar o processamento de muitos objetos pequenos; diminua-o para objetos muito grandes.
- Arquivos que já estão no bucket com o mesmo tamanho são ignorados, portanto, reexecutar o script retoma uma cópia interrompida. Ele não recopiará um arquivo de origem que foi alterado, mas manteve o mesmo tamanho: para manter um bucket sincronizado com uma origem em constante mudança, [monte a origem e execute `hf sync`](#from-aws-s3-or-s3-compatible-storage) em vez disso.

Para GCS ou Azure, substitua `boto3` pelo SDK da nuvem correspondente (`google-cloud-storage`, `azure-storage-blob`) e ajuste as chamadas de listagem e leitura. A metade de destino permanece a mesma.

**2. Inicie-o como um Job em segundo plano**, passando suas credenciais como segredos:

```bash
hf jobs uv run --detach --flavor cpu-performance --timeout 24h \
  --secrets HF_TOKEN \
  --secrets AWS_ACCESS_KEY_ID \
  --secrets AWS_SECRET_ACCESS_KEY \
  migrate.py
```

Cada `--secrets NAME` passa o valor dessa variável do seu ambiente (para `HF_TOKEN`, o seu token de login é usado se ele não estiver definido). Os Jobs param após 30 minutos por padrão, então defina `--timeout` com tempo suficiente para a transferência inteira; se um Job parar antes, inicie-o novamente e ele pulará os arquivos já copiados.

`--detach` retorna imediatamente com um ID de Job. Acompanhe o progresso com `hf jobs logs -f <job_id>`, liste as execuções com `hf jobs ls` e veja as opções de hardware com `hf jobs hardware`.

## De um repositório do Hub ou de outro bucket

Se os dados já estiverem no Hub, em um repositório de modelo ou dataset ou em outro bucket, copie-os no lado do servidor. Para arquivos rastreados por [Xet](./xet/index), apenas os hashes de conteúdo são movidos, portanto a cópia é quase instantânea e nada é reenviado.

```bash
# From a dataset repository into a bucket
hf buckets cp hf://datasets/<org>/<dataset>/<path> hf://buckets/<namespace>/<bucket>/<path>

# From one bucket to another
hf buckets cp hf://buckets/<namespace>/<bucket-a>/<path> hf://buckets/<namespace>/<bucket-b>/<path>
```

- A origem e o destino devem estar na mesma região de armazenamento.
- Você precisa de acesso de leitura à origem e acesso de escrita ao destino.
- Arquivos pequenos que não são rastreados pelo Xet (configurações, READMEs) são baixados e reenviados automaticamente.
- Copiar de um bucket de volta para um repositório ainda não está disponível; está no roadmap.

Veja [Copiar arquivos entre repositórios e buckets](./storage-buckets#copying-files-between-repos-and-buckets) para o equivalente em Python.

## Prefixos S3 muito grandes com hf-s3ream

> [!WARNING]
> hf-s3ream é uma ferramenta comunitária em estágio inicial (alpha), não sendo um produto oficialmente suportado pela Hugging Face. Teste-o em um prefixo pequeno antes de usá-lo para uma migração de grande escala.

[hf-s3ream](https://huggingface.co/spaces/glutamatt/hf-s3ream) ([fonte no GitHub](https://github.com/glutamatt/hf-s3ream), Apache-2.0) executa uma cópia grande de S3 para bucket a partir de uma interface web:

1. Faça login com o Hugging Face.
2. Insira o prefixo de origem do S3, o bucket de destino e suas credenciais da AWS. Para um bucket público que permite leituras anônimas, ative **Public bucket**: não são necessárias credenciais da AWS e os Jobs leem o S3 sem assinatura.
3. **Analyze** executa uma simulação de baixo custo que verifica o acesso, detecta a região de origem e recomenda uma configuração. Ele cria o bucket de destino (privado) caso ele não exista.
4. **Executar** inicia um trabalho de planejador. O planejador cria um plano de cópia baseado em intervalos, inicia os trabalhos de copiador e exibe o progresso em um gráfico ao vivo. A cópia continua sendo executada se você fechar a aba, mas a página não se reconectará a ela. Para interromper uma cópia, clique em **Interromper cópia** ou cancele o trabalho do planejador (`hf jobs cancel <planner-job-id>`): o planejador cancela seus copiadores.

hf-s3ream é executado em [Jobs](./jobs) sob sua conta, portanto, os Jobs são cobrados a você. Buckets S3 que permitem acesso apenas de uma rede privada (VPC) não podem ser acessados a partir de Jobs.

## Onde executar uma migração de grande escala

Para uma migração de múltiplos TB, você geralmente executa a transferência em uma VM na nuvem, em vez de em um laptop. Se você preferir não gerenciar uma VM, [execute como um Job](#run-the-migration-in-the-background-with-jobs).

- **Execute na mesma nuvem e região da sua origem.** Ler a origem pela rede local é o mais rápido e barato, e a saída (egress) da nuvem de origem costuma ser o maior custo. Os uploads, então, passam pela internet até o Hugging Face (a região dos EUA está na AWS `us-east-1`).
- **Use um processo com muitas threads.** Um único `hf sync` em modo de alto desempenho compartilha um cache de deduplicação. [Divida por subcaminho](#split-by-subpath-experimental) apenas quando um processo não consegue saturar sua rede.
- **Mantenha execuções longas ativas.** Por SSH, inicie a migração dentro de [`tmux`](https://github.com/tmux/tmux/wiki) (ou `screen`, ou `nohup`) para que ela sobreviva a uma sessão interrompida: `tmux new -s migrate`, desconecte com Ctrl-b e depois d, e reconecte mais tarde com `tmux attach -t migrate`.

Pontos de partida para dimensionamento, a serem validados em uma execução de teste:

| Recurso | Orientações | Exemplo da AWS | Exemplo do GCP |
|---|---|---|---|
| Disco | NVMe local para `HF_HOME`, com espaço livre acima do limite do cache de shards. Evite discos conectados à rede para o cache. | NVMe de loja de instâncias (variantes `c7i`/`m7i` `d` ou `i4i`) | SSD local em uma VM `n2` ou `c3` |
| CPU | Muitos vCPUs: o cliente divide e calcula o hash dos dados na CPU. | `c7i.8xlarge` ou maior | `c3-standard-22` ou maior |
| Memória | Suficiente para os buffers do modo de alto desempenho; pelo menos 64 GB com `hf_xet` antes da 1.7.0. | — | — |
| Rede | Alta largura de banda para a internet (classe de 25 Gbps). | — | — |

## Próximas etapas

- **Use os dados no local.** Monte o bucket como um sistema de arquivos local com [hf-mount](./storage-buckets-access#mount-as-a-local-filesystem) ou como um [volume em Jobs e Spaces](./storage-buckets-access#volume-mounts-in-jobs-and-spaces).
- **Leia a partir das suas ferramentas.** pandas, Dask, PyArrow, Daft, DuckDB, 🤗 Datasets e Spark leem caminhos `hf://buckets/...` diretamente. Consulte [Integrações de Bucket](./storage-buckets-integrations).

> [!WARNING]
> Não execute uma ingestão em massa por meio de um mount. O hf-mount faz o staging das gravações em um cache em disco (`/tmp/hf-mount-cache` por padrão) e uma migração grande por ele pode encher esse disco. Use um dos caminhos acima para colocar os dados em um bucket. Se você precisar gravar muito por meio de um mount, aponte o cache para um disco com bastante espaço livre: `hf-mount start --cache-dir /mnt/big bucket <namespace>/<bucket> /mnt/data` (a flag vem antes de `bucket`).

