When it comes to using S3 with Rails, a quick Google search can line up lots of awesome resources and posts that discuss the process in full. I wanted to add to this list and highlight navigating S3 for the typical Rails configuration.
So let’s dive in!
Make sure you’re logged in to your AWS Console and are in a region you’d prefer. I use us-west-1
, but any should do! Just remember which one you pick because sometimes the AWS Console will default back to us-east-1
and leave you panicked about why all your AWS services disappeared! 🙉

AWS Setup
Before we make our bucket, you’ll need a user with permissions set up first. Navigate to the IAM dashboard and then to the Users section. From here click Create user. At the time of writing this (2025), the process seems mostly unchanged except that Access Keys aren’t auto-generated at creation anymore for security reasons.
IAM: Create a User with the S3 Policy
- Add a User name.
Attach the
AmazonS3FullAccess
policy.- You can select Attach policies directly and type
s3
into the search since there are A LOT of policies you can attach 🫣 This will allow us to keep the S3 bucket completely private and provide access to just this user.
- You can select Attach policies directly and type
Review and create. Nothing special here, just click Create user.
You’ll be redirected back to the Users page, from here click on your new User.
In the Summary section click Create access key to generate credentials for your User.
Select Local code. Again, a lot of options here! But because we will be encrypting these in Rails, they hopefully won’t need to be rotated! Don’t forget to check the Confirmation box.
Add a Description tag if you want. You could call it
s3-access
if ya want!Now you’ve got some credentials! You can either copy the values or download the
.csv
.🧩 Note: This is your only opportunity to save or copy these keys, make sure you grab em. If you don’t, or you lose them, you have to make a new set!
S3: Create your S3 bucket
It’s bucket time! 🪣 BUCKET TIME!!! 🪣🪣🪣🪣!!!

Navigate to the S3 dashboard and click Create bucket. Creating a bucket for this use case is literally one step: Add a name (and preferably something unique/specific. Maybe not my-bucket
) all the other options are good to go as their defaults. I know it may be overkill, but I like to use a Passphrase generator to make an extra-long name for the bucket, which requires minimal inspiration when thinking of a name. If you use the one I linked, uncheck Capitals as all S3 names need to be lowercase.
- Object Ownership: ACLs disabled (default)
- Block Public Access settings for this bucket: Block all public access (default)
- Bucket Versioning: Disabled (default)
- Default encryption: Server-side encryption with Amazon S3 managed keys (SSE-S3) (default)
- Bucket Key: Enabled (default)
Rails: Configure for Direct S3 Uploads
To start, in your Rails app, we need to initialize ActiveStorage
. This will put together all the pieces needed for image attachment & upload. More info in the docs.
rails active_storage:install
rails db:migrate
Now is a good time to install the required AWS S3 SDK as well. It's the library that allows ActiveStorage
to just work
out of the box with S3 by enabling Rails to communicate with S3 for uploading, downloading, and managing files. Neat-o!
bundle add aws-sdk-s3
Before getting to associating attachments and images in the Model of your choice, let's add our IAM User credentials. We will use Rails encrypted credentials. In the command, I have my IDE alias for VSCode passed to the EDITOR
variable, but you can add yours in its place.
'EDITOR="code --wait" rails credentials:edit'
In the credentials.yml
it opened, we can fill in our secrets and some other related variables in this format and close the file to save and encrypt.
aws:
access_key_id: <Your access key>
secret_access_key: <Your secret access key>
bucket_name: <Your bucket name>
region: <Your region>
Now in our config/storage.yml
, we can declare our S3 credentials for ActiveStorage
. And I gotta say, Rails encrypted credentials are nice vs. dealing with a .env
file! ⭐️ Those secrets are an easy call away.
amazon:
service: S3
access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
region: <%= Rails.application.credentials.dig(:aws, :region) %>
bucket: <%= Rails.application.credentials.dig(:aws, :bucket_name) %>
One more step. In the environment config files for Rails, we need to point ActiveStorage
towards AWS instead. You can point development
towards AWS too to test out uploads.
In your config/environments/production.rb
and config/environments/development.rb
(if you’d like to test it out locally) change the service from :local
to :amazon
config.active_storage.service = :amazon
Now we are ready to get photos uploaded however you might like! There are lots of ways to do this, have at thee!
