Configure MINIO as Strapi media storage

2 min read - February 27, 2024

Recently i started creating this Blog and one of the features i wished to have was to host all the media in something scalable like Minio.

There are no officialy supported plugins from Strapi but you have @strapi/provider-upload-aws-s3 which was tailored for being used mainly with S3 but it also state, inside the documentation, the following:

This plugin may work with S3 compatible services by using the endpoint option instead of region.

So being Minio an S3 compatible we just need the following configurations for make them work togheter.

Create a new Strapi app

npx create-strapi-app blog --quickstart --ts

Enter inside the project directory

cd blog

Install the S3 Strapi plugin

npm install @strapi/provider-upload-aws-s3 --save

Create a Minio instance

With this docker-compose file we are setting up locally a minio instance and creating a public bucket called blog.

docker-compose.yml
version: '3.7'

services:
  minio:
    image: minio/minio
    ports:
      - "9000:9000"
      - "9001:9001"
    environment:
      MINIO_ROOT_USER: minio_access_key
      MINIO_ROOT_PASSWORD: minio_secret_key
    command: server --address 0.0.0.0:9000  --console-address :9001 /data
  createbuckets:
    image: minio/mc
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      /usr/bin/mc alias set myminio http://minio:9000 minio_access_key minio_secret_key;
      /usr/bin/mc mb myminio/blog;
      /usr/bin/mc anonymous set public myminio/blog;
      exit 0;
      "

Inside your .env file add the following variables

.env
# MINIO
MINIO_ROOT_USER=minio_access_key
MINIO_ROOT_PASSWORD=minio_secret_key
MINIO_PRIVATE_ENDPOINT=http://localhost:9000
MINIO_PUBLIC_ENDPOINT=http://localhost:9000/blog
MINIO_REGION=us-west-rack2
MINIO_BUCKET=blog

Modify the plugins config file

config/plugins.ts
export default ({env}) => ({
  upload: {
    config: {
      provider: 'aws-s3',
      providerOptions: {
        baseUrl: env('MINIO_PUBLIC_ENDPOINT'),
        s3Options: {
          credentials: {
            accessKeyId: env('MINIO_ROOT_USER'),
            secretAccessKey: env('MINIO_ROOT_PASSWORD'),
          },
          endpoint: env('MINIO_PRIVATE_ENDPOINT'),
          region: env('MINIO_REGION'),
          forcePathStyle: true,
          params: {
            Bucket: env('MINIO_BUCKET'),
          },
        }
      },
    },
  },
})

Modify the middlewares config file

So we are basically commenting out the default configuration strapi::security and adding a custom one which is simply adding the minio url localhost:9000 to the allowed contentSecurityPolicy as img-src and media-src.

config/middlewares.ts
// 'strapi::security',
  {
    name: 'strapi::security',
    config: {
      contentSecurityPolicy: {
        useDefaults: true,
        directives: {
          'connect-src': ["'self'", 'https:'],
          'img-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'localhost:9000',
          ],
          'media-src': [
            "'self'",
            'data:',
            'blob:',
            'market-assets.strapi.io',
            'localhost:9000',
          ],
          upgradeInsecureRequests: null,
        },
      },
    },
  },

Start docker-compose

sudo docker-compose up -d

Build and start the app

npm run build
npm run start

Visit the admin panel and test the media upload/display

http://localhost:1337/admin

Now your medias will be stored inside the minio instance.

About the Author

Hi, I'm Mario an Italian Software Engineer with over 11+ years of hands-on experience.