If you’re using CarrierWave to upload images to your web application, and you haven’t changed how the images get stored, you’re going to run into problems when you push up to heroku. Heroku allows us to store our code, and the images we know about as we’re building our web application, but they don’t play nicely with user uploaded files (like images), and they are quite clear about that in their documentation. This means we’ll need to figure out a different place to put our images.

Amazon S3

One of the places that will gladly take these user uploaded images is the Amazon S3 service. Think of it like a dropbox, except instead of being designed for people to upload files by hand, it’s designed for computers (like your web app) to upload files to it.

This article will walk you through how to configure your web application to connect to your Amazon Account to upload images.

Step 1 – create an account: go to aws.amazon.com, press the yellow sign up button and go through the flow. It’s going to ask you for a bunch of information to verify your account. It’s going to need a phone number, and credit card number. Using S3 is free for the basic tier, but if you start uploading a ton of gigabytes of data (which you won’t for almost all web apps), they’ll start charging you a few dollars per month.

Step 2 – create an S3 Bucket:

Visit the AWS Console page, navigate through and select the option for S3 in the AWS search window.

 

Press the blue Create Bucket button in the top right corner of the page.

 

In the dialog box that pops up, enter a unique bucket name (without periods), and select US East (North Virginia) for the region.  Selecting this region is important, because it is the default region that CarrierWave uses, and if you select a different region you will see errors in future steps.

Then press Next.

The next window that will be displayed will prompt you to optionally set VersioningLogging, and Tags.  These options can be skipped and you can press the Next key again.

On the next window that will allow you to manage Users and Permission, simply press the Next key again.

Finally, on the last window, press the Create Bucket button and your bucket will be created.

If you have trouble following along, visit this screencast, that performs the actions.

Step 3 – setup Amazon API keys:

To start, visit the Amazon IAM Dashboard.

In the left pane select the menu item for Users.

Press the blue button on the top of the page to Add a User.

In the window that appears enter a User name and set the Access Type to be set to Programmatic Access.  Then press the Next: Permissions button.

Choose the option to Attach Existing Policies Directly.

In the Search window start typing a search query to find the option that is listed as exactly AmazonS3FullAccess then press the checkbox to the left of the option.  There are many different options, so make sure to select the exact correct one.

Scroll down the page and press the blue button for Next Review.

On the next page simply press the blue button on the bottom right corner of the page for “Create User“.

Finally, on the last page, press the button to Download .csv, which will contain a CSV with API keys that you will be able to use in your account.

A CSV file containing both your Access key ID and Secret access key, which will allow your web application to upload files to your Amazon S3 bucket you just created, will be downloaded to your computer.

If you have trouble following along, visit this screencast, which performs those actions.

Figaro

Now we want to be able to pull these secret values into our web application, but we don’t want to have these values accidentally checked into our public GitHub page. We can achieve this by using the Figaro Gem.

Once you have the figaro gem inside your Rails application, you’ll want to include your amazon credentials inside your “application.yml” file. To start with, let’s get the values from the file we downloaded from amazon early.

To start with, let’s get the values from the file we downloaded from amazon early. In sublime, click on the menu File>Open… and navigate to the your downloads folder and open “credentials.csv” file that was downloaded. It should look like this, however it will have different values in the file:

This file will show you your username, access key id and secret access key. First, let’s pull out everything after the first comma and before the second comma and put this into our application.yml file. So first I’ll copy this:

Now you want to add a line to “config/application.yml”, so it has this at the bottom (replace the paste-aws-access-key-here with your real access key!):

Now we want to find our secret key and copy that into our clipboard. So open back up that credentials.csv file and copy everything after the last comma (make sure to get everything after the last comma. Even if there are weird characters like + or /):

Now you want to add a line to “config/application.yml”, so it has this at the bottom after the line we just put there (replace the paste-aws-secret-key-here with your real key!):

Finally we want to store our AWS bucket name into this file as well. So find the page that you left open in the “AWS” management page, on this step, that looks like this:

Now we want to copy EXACTLY (this is case sensitive) the name of the bucket that we have in the page, into our application.yml file.

And we want to put this into the bottom of application.yml file so the last line looks like this (replace enter-your-bucket-name-here with EXACTLY what you see on that last page):

Configuring CarrierWave

First in order for carrierwave to be able to communicate with Amazon S3, it needs to have the fog gem in the project. So open up your Gemfile and add the following line:

And then make sure to save the file, and run a bundle install.

Finally we have two steps to switch our uploader from using regular file storage to use amazon s3 along with the access key and secret key we just setup in the previous section.

Make a new file thats located in our application’s config/initializers folder, and call it “carrierwave.rb”. Put the following content in this file:

Now make sure to save the file. Also whenever initializers get created or changed you’ll need to restart your rails server, so do that now.

Then finally open up the file you created in the carrierwave step, in app/uploaders. Right now line 10/11 will look like this:

This is saying the place it should store the image is on the file system (which heroku doesn’t like), but is showing us how we could switch to use s3, but it’s commented out (that’s why there’s the hashtag in front of it). We want to change this, so make the line that says to use the file system commented out (start with a hashtag), and remove the hashtag from the line that says it should be on S3.

Nice. Now save that file.

Finally restart your server and try to upload a new image. Should work like a charm!

Syncing Credentials to Heroku

Finally we need to push our values stored on figaro up to heroku. We can do that by running this command:

Awesome! Now we’re good to go!

Recommended For You

8 thoughts on “Switching CarrierWave to use S3 with Heroku and localhost

  1. Hey , Thanks a lot for this, The only complete post I found on how to setup S3 with step by step. Screens are little changed now, but it wont effect the output of the tutorial.

    I was able to setup

    carrierwave
    carrierwave-aws

    by following this,

    Thanks again 👍👍

  2. I would hug you right now if I could. I’ve been having issues for a entire day getting this set up and working. I started over and followed everything you did (minor differences on Amazon’s interface), and it worked! Much thanks!

  3. Awesome! Thanks for your post!! ^^ Really is very useful.
    But in “config/initializers/carrierwave.rb” file I add the attribute “region” and my carrierwave file is as follow:

    # config/initializers/carrierwave.rb
    CarrierWave.configure do |config|
    config.fog_credentials = {
    :provider => ‘AWS’,
    :aws_access_key_id => ENV[“AWS_ACCESS_KEY”],
    :aws_secret_access_key => ENV[“AWS_SECRET_KEY”],
    :region => ENV[‘S3_REGION’]
    }
    config.fog_directory = ENV[“AWS_BUCKET”]
    end

    Thanks again ^^

    1. Good call, Leonel. If you use non default regions on S3, passing through the value makes a ton of sense.

      Happy coding! :)

Leave a Reply

Your email address will not be published. Required fields are marked *