ActiveStorage with AWS S3

How to setup ActiveStorage with S3 in Rails 7

Follow Chris Oliver's 2023 tutorial here:

Steps for setting up S3 for staging and production:

For reference, see official rails guide here: https://guides.rubyonrails.org/active_storage_overview.html#s3-service-amazon-s3-and-s3-compatible-apis

Setup config/storage.yml

  • Uncomment the amazon block

    • Add public: true to that block (so that S3 files are always visible to public viewers, which is the case most of the time... Unless you're building an app where S3 files should be protected for each user).

    • Update the bucket name to be bucket: appname-<%= Rails.env %>

Create the bucket(s) in S3

  • I like to name them, so that it's easy to define dynamically in config/storage.yml:

    bucket: appname-<%= Rails.env %>

    So name the S3 buckets:

    • appname-staging

    • appname-production

  • Select "ACLs Enabled"

  • In "Block public access" settings, check only the bottom 2 boxes. It should look like this: https://share.cleanshot.com/YyxCMyVD

    • Note: In Chris Oliver's video, near the beginning he mistakenly checked 3 boxes, but around 14:00 in the video, he fixed it to check only the bottom 2 boxes.

Leave everything else set to default, then "Create".

Setup IAM Policy

Go to IAM -> Policies here -> "Create a policy"

  • Service: S3 (only)

  • Access level: Check all of the following:

    • List > ListBucket

    • Read > GetObject

    • Write > PutObject

    • Write > DeleteObject

    • Permissions Management > PutObjectAcl

  • Resources:

    • Set it to "Specific"

    • Then add 2 lines each for production and staging buckets. Name the bucket name, and then name the bucket name and append /*, like this: https://share.cleanshot.com/Lrhtqt4r

  • Name the policy: appname-s3 then "Create" policy.

Create IAM User

Go to IAM -> Users here -> Create a User

  • Username: appname

    • Leave option for giving access to AWS console to unchecked.

  • In Step 2, Permissions, select "Attach policies directly"

    • Search for the policy name we just created (appname-s3) and check its box

"Create user"

Edit the User's security credentials & and save to credentials

Click the user that you just created -> "Security Credentials"

  • Access Keys -> "Create Access Key"

  • Select "Application running outside AWS"

    • skip "tag description"... click "Create access key"

  • Save the access key and secret key to both staging and production credentials

    • (in this example, we're using the same AWS user and policy for both staging and production, which is fine in most cases).

Update config/staging & production.rb active_storage setting

Open config/environments/staging.rb and config/environments/production.rb and update the following line to :amazon:

config.active_storage.service = :amazon

Add S3 Gem

Following instructions from the official rails guide here

Add the following gem to gemfile:

gem "aws-sdk-s3", require: false

Also ensure that the image_processing gem is in gemfile (it should already be there)

bundle install

Update CORS configuation

  • In S3 -> Edit each of the buckets you've created -> "Permissions" tab

  • Scroll all the way down to "Cross-origin resource sharing (CORS)"

    • (not to be confused with "Bucket Policy")

  • Copy the example S3 CORS configuration from rails guides here

    • Edit the "AllowedOrigins" to include:

      • http://127.0.0.1:3000

      • The The URL of the staging or production domain (whichever S3 bucket this is)

      • Optional: The temporary URL of the domain on heroku (or whatever hosting service you're using).

    • It should look something like this: https://share.cleanshot.com/kNJd7jgV

Last updated