AWS S3 upload not working on HEROKU

Hello,

I am using @strapi/provider-upload-aws-s3 (from official strapi docs).

PROBLEM: AWS S3 upload not working on HEROKU

.

I tried both IAM user and direct access through root credentials but no luck. Everything works fine but my media are not uploaded to AWS s3.
.
.
.

here’s my setup:

Deploy output:

Time │ Wed Jan 05 2022 13:31:38 GMT+0100 (GMT+01:00) │
│ Launched in │ 882 ms │
│ Environment │ production │
│ Process PID │ 22 │
│ Version │ 4.0.2 (node v14.18.2) │
│ Edition │ Community

Setup for production:

The approach I used is folder based so these are the configurations to override the defaults only in production.

This allows me to have a double env and test on my local machine.

:open_file_folder: config/env/production:

//database.js

const path = require("path");
const parse = require('pg-connection-string').parse;

module.exports = ({ env }) => {
    const dbUrl = env('DATABASE_URL')
    const config = parse(dbUrl);
    return {
      connection: {
        client: 'postgres',
        connection: {
          host: config.host,
          port: config.port,
          database: config.database,
          user: config.user,
          password: config.password,
          ssl: {
            rejectUnauthorized: false
          },
        },
        debug: false,
      },
    };
};

//plugins.js
module.exports = ({ env }) => ({
  upload: {
    provider: 'aws-s3'
    },
  });
//server.js
module.exports = ({ env }) => ({
  host: env('HOST'),
  port: env.int('PORT'),
  admin: {
    auth: {
      secret: env('ADMIN_JWT_SECRET'),
    },
  }
});

the package.json:

//package.json
{
  "name": "my-app-name",
  "private": true,
  "version": "0.1.0",
  "description": "A Strapi application",
  "scripts": {
    "develop": "strapi develop",
    "start": "strapi start",
    "build": "strapi build",
    "strapi": "strapi"
  },
  "devDependencies": {},
  "dependencies": {
    "@strapi/plugin-i18n": "4.0.2",
    "@strapi/plugin-users-permissions": "4.0.2",
    "@strapi/provider-upload-aws-s3": "^4.0.2",
    "@strapi/strapi": "4.0.2",
    "pg": "^8.7.1",
    "pg-connection-string": "^2.5.0",
    "sqlite3": "5.0.2",
    "strapi-provider-upload-aws-s3": "^3.6.8"
  },
  "author": {
    "name": "A Strapi developer"
  },
  "strapi": {
    "uuid": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  },
  "engines": {
    "node": ">= 12.x <= 14.x.x",
    "npm": ">=6.0.0"
  },
  "license": "MIT"
}

.


HEROKU CONFIG VARS:

AWS_ACCESS_KEY_ID
AWS_ACCESS_SECRET
AWS_BUCKET
AWS_REGION
DATABASE_URL
MY_HEROKU_URL

The AWS credentials are from an IAM user.

AWS settings:

Block all public access is completely turned off (public)


Bucket policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "userExampleName",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::12345678910123:user/userExampleName"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::bucketName",
                "arn:aws:s3:::bucketName/*"
            ]
        },
        {
            "Sid": "open",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::bucketName",
                "arn:aws:s3:::bucketName/*"
            ]
        }
    ]
}

Cross-origin resource sharing (CORS)

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD",
            "POST",
            "PUT"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": []
    }
]

IAM user policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::bucketName/*",
                "arn:aws:s3:::bucketName"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::*"
        }
    ]
}

You’re plugins.js seems to be wrong.

provider: 'aws-s3',
    providerOptions: {
      accessKeyId: env('AWS_ACCESS_KEY_ID'),
      secretAccessKey: env('AWS_ACCESS_SECRET'),
      region: env('AWS_REGION'),
      params: {
        Bucket: env('AWS_BUCKET'),
      },
    },

There are more options you need to provide currently you are only providing provider

Hi! Thanks for repying :slight_smile:


These are provided in:

. / src / extensions / upload / config / settings.js

//settings.js

module.exports = {
  provider: "aws-s3",
  providerOptions: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    secretAccessKey: process.env.AWS_ACCESS_SECRET,
    region: process.env.AWS_REGION,
    params: {
      Bucket: process.env.AWS_BUCKET_NAME,
    },
  },
};

(tried both approaches btw)

@Eventyret

Sorry but you gave a wrong answer.

Luckly I found a solution on github.

I hope people will find this post instead of spending sleepless nights trying to make it work…

SOLUTION

//plugins.js

module.exports = ({ env }) => ({
  // ...
  upload: {
    config: {             // <-- this is missing in the official docs
      provider: 'aws-s3',
      providerOptions: {
        accessKeyId: env('AWS_ACCESS_KEY_ID'),
        secretAccessKey: env('AWS_ACCESS_SECRET'),
        region: env('AWS_REGION'),
        params: {
          Bucket: env('AWS_BUCKET'),
        },
      },
    },
  },
  // ...
});

Your right I didn’t even see in your title you used v4. Glad you got it sorted… What I suggested was from what I saw of your code. Hence v3

It tells you directly on the package on npm how to configure: @strapi/provider-upload-aws-s3 - npm

1 Like