2 апреля 2025 • 3 минуты чтения
5
💽 Переход на S3 через ActiveStorage Mirroring
В этом посте я расскажу, как безопасно перейти на S3 для хранения всех файлов Ruby on Rails-приложения.
Краткий план
Чтобы безопасно перейти на S3 (self-hosted/AWS), сначала нужно скопировать все существующие файлы так, чтобы они хранились и у нас (local), и на сервере (S3). Только после этого можно спокойно удалить локальные файлы и полностью перейти на удалённое хранение.
Настройка зеркалирования
В config/storage.yml
добавляем конфигурации для локального, S3 и mirror-сервисов:
local:
service: Disk
root: <%= Rails.root.join("storage") %>
s3: # имя можно выбрать любое, например aws
service: S3
endpoint: "https://s3.example.com"
access_key_id: <%= Rails.application.credentials.dig(:s3, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:s3, :secret_access_key) %>
region: us-east-1 # укажите ваш регион
bucket: <%= Rails.application.credentials.dig(:s3, :bucket) %>
force_path_style: true
mirror:
service: Mirror
primary: local
mirrors: [s3]
Я использовал
Rails.application.credentials
для хранения чувствительных токенов, но вы можете взять их из любых ENV-переменных или другого хранилища.
Секция mirror
— это и есть «магия»: здесь мы указываем, что хотим хранить файлы и локально, и дублировать их в S3.
Далее в нужном окружении (config/environments/production.rb
, config/environments/staging.rb
и т. п.) переключаем сервис:
# config/environments/production.rb
config.active_storage.service = :mirror
Советую включать :mirror
только в окружениях на серверах, а в development
и test
оставить :local
.
Копирование существующих файлов
После обновления конфигурации новые файлы сразу будут сохраняться через mirror, а старые останутся в локальной папке. Чтобы их перенести, выполняем в консоли:
# Один раз
ActiveStorage::Blob.update_all(service_name: "mirror")
ActiveStorage::Blob.find_each { |blob| blob.mirror_later }
Этот код обновит все записи и запустит фоновые задачи для загрузки файлов в S3. После этого все старые файлы появятся в облаке, и новые тоже будут дублироваться.
Спасибо Oliver Eidel за его пост, который помог разобраться с миграцией.
Полный переход на S3
Когда все файлы успешно скопированы:
- Удаляем секцию
mirror
изconfig/storage.yml
— она больше не нужна. - Меняем в окружениях
config.active_storage.service = :mirror
наconfig.active_storage.service = :s3
(или на имя вашего S3-сервиса).
Чтобы сделать S3 «мастером» для всех существующих записей, выполняем:
ActiveStorage::Blob.update_all(service_name: "s3")
Опционально: можно очистить локальное хранилище:
Сначала убедитесь, что все файлы хранятся в s3!
rm -rf storage/
Готово! Теперь ваше Ruby on Rails-приложение хранит все файлы только в S3.