Храним файлы Strapi в облаке Selectel

Привет, я некоторое время работаю над своим пет проектом, где в основном занимаюсь фронтом, а для данных использую headless CMS под названием strapi.io. В какой-то момент у меня появилась потребность вынести медиа хранилище из локальной папки в облако. А так-как основной проект уже находился долгое время на серверах Selectel, я решил воспользоваться их объектным хранилищем и подключится к нему с помощью плагина »@strapi/provider-upload-aws-s3». И в этой статье я вам опишу краткий гайд как это сделать.

Для начала у вас уже должно быть strapi приложение, версии приближенной к 4.20.0, и аккаунт в Selectel. Открываем личный кабинет, ищем в сайдбаре раздел «Облачные услуги» и открываем вкладку «Объектное хранилище». Кликаем кнопку «Создать контейнер» и видим следующий интерфейс.

Untitled

Интерфейс создания контейнера в Selectel

Напишите имя, оно станет названием контейнера для s3, так что рекомендую использоваться только английские буквы и тире. Тип — публичный, ибо изображения будут доступны на сайте. И адресация — галочка на Virtual-Hosted, ниже пояснение из доки плагина.

AWS SDK V3 adopts the virtual-hosted–style URI format for S3 URLs. This format is recommended by AWS and is likely to become required in the near future, as the path-style URI is being deprecated. More details on this format can be found in the AWS User Guide.

Далее отправляемся в «Профиль и настройки», там ищем вкладку «Управление пользователями» и нажимаем кнопку «Добавить пользователя».

Untitled

Интерфейс добавления пользователя в Selectel

Переключаем тип на «Сервисный пользователь», выбираем роль «Пользователь объектного хранилища» и указываем проект в котором мы создали контейнер. Добавляем пользователя и заходим в него, листаем до заголовка «S3 ключи», нажимаем «Добавить ключ», снова выбираем проект и генерируем Access key и Secret key.

Untitled

Интерфейс добавление S3 ключа в Selectel

Чтобы не потерять ключи, предлагаю сразу их добавить в переменную окружения.

# .env

AWS_ENDPOINT=https://s3.storage.selcloud.ru
AWS_REGION=ru-1
AWS_ACCESS_KEY_ID=
AWS_ACCESS_SECRET=
AWS_BUCKET=<Название контейнера>

В проект strapi устанавливаем »@strapi/provider-upload-aws-s3», добавляем конфигурацию провайдера.

// path: ./config/plugins.ts

export default ({ env }) => ({
  upload: {
    config: {
      provider: "aws-s3",
      providerOptions: {
        s3Options: {
          endpoint: env("AWS_ENDPOINT"),
          credentials: {
          accessKeyId: env("AWS_ACCESS_KEY_ID"),
          secretAccessKey: env("AWS_ACCESS_SECRET"),
        },
          params: {
            Bucket: env("AWS_BUCKET"),
          },
        },
      },
    },
  },
})

Возвращаемся в Selectel, нам осталось выдать новому пользователю права на доступ к конкретному контейнеру. Переходим в нашем контейнере, во вкладку «Политика доступа» и нажимаем «Создать политику доступа».

Untitled

Политика доступа к контейнеру в Selectel

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

Нажимаем «Сохранить» и возвращаемся в интерфейс Strapi, чтобы протестировать загрузку.

Untitled

Медиа библиотека в Strapi

Загрузка работает, но изображение не отображается, и над этим вопросом я долго ломал голову, но после крупного обновления личного кабинета Selectel решение нашлось очень быстро. В самом начале мы указали тип контейнера — публичный, и соответственно во вкладке «Домены» мы находим публичный домен для доступа к загруженным файлам. Добавляем его в файл окружения и прописываем в конфиге провайдера.

# .env

CDN_URL=<Публичный домен контейнера>
// path: ./config/plugins.ts

provider: "aws-s3",
providerOptions: {
  baseUrl: env("CDN_URL"),
  s3Options: {
  ...

А так же нам нужно подправить конфигурацию Content Security Policy (CSP), пример взят из доки провайдера.

// path: ./config/middlewares.ts

export default ({ env }) => [
  ...
  {
    name: "strapi::security",
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          "connect-src": ["'self'", "https:"],
          "img-src": [
          "'self'",
          "data:",
          "blob:",
          "https://strapi.io",
          "https://market-assets.strapi.io",
          env("CDN_URL"),
        ],
        "media-src": [
          "'self'",
          "data:",
          "blob:",
          "https://strapi.io",
          "https://market-assets.strapi.io",
          env("CDN_URL"),
        ],
        upgradeInsecureRequests: null,
        },
      },
    },
  },
  ...

Удаляем тестовое изображение и загружаем заново. Теперь все работает.

Untitled

Медиа библиотека в Strapi

Вместо публичного домена Selectel так же предлагает подключить свой собственный или воспользоваться услугой CDN. Но в этой статье на этом все. До встречи!

© Habrahabr.ru