Перенос файлов в объектное хранилище.

Как перенести файлы из Amazon S3, Google Cloud Storage, любого S3-совместимого хранилища или папки на сервере в бакет: скопировать всё сразу или переносить постепенно, без простоя.

5 МИН ЧТЕНИЯ

Файлы уже хранятся где-то ещё? Перенесите их в бакет приложения одним из двух способов. Оба запускаются из панели: приложение → Хранилище → бакет → Перенести файлы.

Скопировать всё сейчасПереносить постепенно, без простоя
Что происходитвсе файлы копируются за один разфайл копируется, когда приложение впервые его читает
Когда переключать приложениепосле завершения копированиясразу
Ход работынайдено, скопировано, пропущено, не скопировано; пауза, продолжение, прерываниеработает, пока вы его не выключите
Старое хранилищеAmazon S3, Google Cloud Storage, S3-совместимоеAmazon S3, Google Cloud Storage

Копирование идёт на нашей стороне — компьютер не нужно оставлять включённым. Когда оно завершится (или остановится раньше), придёт письмо и сообщение в Telegram.

Переносить файлы могут владелец аккаунта и Администраторы приложения (см. Доступ команды); перенос доступен и через API, CLI и MCP.

Перед началом: ключ только для чтения

Создайте в старом хранилище отдельный ключ для переноса, который может только просматривать список и читать один бакет. Никогда не вставляйте основные ключи. Ключ используется только для этого переноса; мы его не храним, и он больше нигде не показывается. Когда перенос закончится, удалите ключ у старого провайдера.

Amazon S3

В IAM создайте пользователя (или роль с ключом доступа) с такой политикой — замените my-old-bucket на имя своего бакета:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:List*", "s3:Get*"],
      "Resource": ["arn:aws:s3:::my-old-bucket", "arn:aws:s3:::my-old-bucket/*"]
    }
  ]
}

Затем создайте для него ключ доступа. В панели понадобятся ID ключа доступа, секретный ключ, имя бакета и его регион (например, eu-central-1; он указан рядом с бакетом в консоли S3).

Google Cloud Storage

Создайте сервисный аккаунт с доступом на чтение бакета и скачайте его JSON-ключ:

gcloud iam service-accounts create rivervo-move --display-name="Move files to Rivervo"
gcloud storage buckets add-iam-policy-binding gs://my-old-bucket \
  --member="serviceAccount:rivervo-move@MY-PROJECT.iam.gserviceaccount.com" --role="roles/storage.objectViewer"
gcloud storage buckets add-iam-policy-binding gs://my-old-bucket \
  --member="serviceAccount:rivervo-move@MY-PROJECT.iam.gserviceaccount.com" --role="roles/storage.legacyBucketReader"
gcloud iam service-accounts keys create key.json \
  --iam-account="rivervo-move@MY-PROJECT.iam.gserviceaccount.com"

Storage Object Viewer читает файлы; Storage Legacy Bucket Reader позволяет прочитать сам бакет. В панель вставьте всё содержимое key.json, а затем удалите файл ключа со своего компьютера.

Другое S3-совместимое хранилище

Любое хранилище с S3 API подключается так же: создайте ключ, который может только просматривать список и читать бакет (обычно он называется «только для чтения» или «ограниченный»), и найдите адрес S3 региона бакета — например, https://s3.eu-central-003.backblazeb2.com. Адрес указывается без имени бакета.

Скопировать всё сейчас

  1. Приложение → Хранилище → бакет → Перенести файлы.
  2. Выберите Скопировать всё сейчас, старое хранилище, бакет в нём, регион или адрес S3 и вставьте ключ.
  3. Если нужно — папку: например, скопировать только photos/.
  4. Файлы, которые уже здесь: по умолчанию файл с таким же именем, уже лежащий в бакете, остаётся, а файл из старого хранилища пропускается. Включите Заменять, чтобы перезаписывать.
  5. Начать копирование и подтвердите.

На карточке видно, сколько файлов найдено, скопировано, пропущено и не скопировано, есть шкала прогресса; Показать журнал называет пропущенные и не скопированные файлы. Копирование можно Приостановить, Возобновить или Прервать — уже скопированные файлы останутся. Когда копирование завершится, переключите приложение на бакет (в нём уже есть переменные S3_*).

Имена файлов (ключи) сохраняются. Повторный запуск копирует только то, чего не хватает (если Заменять выключено).

Переносить постепенно, без простоя

Подходит, когда приложение должно работать без перерыва, а файлы всё время добавляются:

  1. Перенести файлы → Переносить постепенно, без простоя, старое хранилище, бакет и ключ → Включить постепенный перенос.
  2. Сразу переключите приложение на этот бакет (его переменные S3_*) и разверните его.
  3. Когда приложение читает файл, которого в бакете ещё нет, он в этот момент копируется из старого хранилища и отдаётся. Новые загрузки сразу попадают в бакет.
  4. Чтобы завершить: запустите Скопировать всё сейчас для файлов, которые ещё никто не читал (с выключенным Заменять, чтобы новые файлы остались), дождитесь завершения и Выключите постепенный перенос.

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

Из папки на сервере

Чтобы перенести файлы с VPS или любого другого сервера (например, storage/app/public сайта на Laravel), используйте rclone с ключами самого бакета. Они на вкладке Переменные приложения: S3_ENDPOINT, S3_BUCKET, S3_KEY и S3_SECRET (у второго бакета впереди его имя: MEDIA_S3_KEY …).

# Установить rclone (Linux)
curl https://rclone.org/install.sh | sudo bash
 
# Ключи бакета — переменными окружения, они не попадут в файл настроек
export RCLONE_CONFIG_RIVERVO_TYPE=s3
export RCLONE_CONFIG_RIVERVO_PROVIDER=Other
export RCLONE_CONFIG_RIVERVO_REGION=auto
export RCLONE_CONFIG_RIVERVO_ENDPOINT='значение S3_ENDPOINT'
export RCLONE_CONFIG_RIVERVO_ACCESS_KEY_ID='значение S3_KEY'
export RCLONE_CONFIG_RIVERVO_SECRET_ACCESS_KEY='значение S3_SECRET'
 
# Скопировать папку в бакет (значение S3_BUCKET) с сохранением структуры
rclone copy /var/www/shop/storage/app/public rivervo:BUCKET/public --progress --transfers 16
 
# Проверить, что дошли все файлы
rclone check /var/www/shop/storage/app/public rivervo:BUCKET/public --one-way

rclone copy ничего не удаляет в бакете и пропускает файлы, которые уже там и не изменились, поэтому после перерыва его можно запустить снова. Долгое копирование запускайте на сервере внутри tmux или screen — тогда оно продолжится, даже если SSH-соединение оборвётся.

Сколько это стоит

За сам перенос отдельной платы нет. Файлы в бакете оплачиваются по обычным ценам объектного хранилища с баланса:

  • хранение: $0.025 за ГБ в месяц — 50 ГБ стоят около $1.25 в месяц;
  • запись: $6 за миллион операций — каждый скопированный файл это примерно одна операция записи, поэтому 100 000 файлов стоят около $0.60 (очень большой файл загружается частями и считается за несколько операций);
  • чтения при постепенном переносе — обычные операции чтения ($0.50 за миллион).

Большинство облачных хранилищ берут плату за исходящий трафик. Прежде чем переносить много данных, проверьте прайс старого провайдера.

Для переноса нужен положительный баланс — как и для добавления бакета. Перенос недоступен в пробный период и в бакет, который сейчас только для чтения (превышен его лимит размера или то, что оплачивает баланс), — панель объяснит причину и, если это поможет, предложит пополнить баланс. Если во время копирования бакет становится только для чтения, копирование приостанавливается и продолжается само, когда запись снова возможна.

Ограничения

  • В один бакет одновременно — одно копирование и один постепенный перенос.
  • Файлы больше 1 ТБ копирование пропускает.
  • Файлы в архивных классах, которые нужно восстанавливать перед чтением (S3 Glacier Flexible Retrieval, Glacier Deep Archive), пропускаются; сначала восстановите их.
  • Вместе с файлом переносятся только ваши метаданные (x-amz-meta-*); ETag файла может отличаться от прежнего.
  • Файл, удалённый из бакета при включённом постепенном переносе, при следующем чтении скопируется снова.

Всё ещё не можете разобраться?

Напишите живому инженеру — медианный ответ менее 3 минут в любое время суток.

Написать в поддержку