Configuring S3 with Rails, Paperclip and Heroku

On my current project we are storing images on Amazon S3. We are using the very popular Paperclip gem to interact with images through ActiveRecord. Paperclip is very easy to configure with S3, you simply need to specify the name of your S3 bucket and Amazon access keys and you’re good to go.

However, what you probably don’t want to do is to check all these configuration settings into source control. In fact, you probably want a different set of keys for development, so the question is how do you manage all of this.

One solution is to have an S3 configuration file (config/s3.yml) which you don’t check into source control – each developer will simply have a local copy. Unfortunately this doesn’t work if you’re using Heroku as your deployment environment – Heroku doesn’t allow you to create files outside of a git repository.

A better solution is to use environment variables. Simply create an initializer (config/initializers/s3.rb) which looks something like this:

S3_CREDENTIALS = { 
    access_key_id: ENV['AWS_ACCESS_KEY_ID'], 
    secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], 
    bucket: ENV['AWS_ASSETS_BUCKET']
}

And now in your model you can do this:

has_attached_file :photo, :storage => :s3, :s3_credentials => S3_CREDENTIALS

Using Foreman for Development

Now we need a way to load these environment variables in development mode. This is easy if you’re using Foreman in development. It’s probably a good idea to use Foreman if you’re using Heroku since Heroku uses Foreman.

Simply add the Foreman gem:

gem 'foreman'

Now you need to create a .env file that contains your environment variables and a Procfile that contains the command needed to start your web server.

Here is an example of the .env file:

AWS_ASSETS_BUCKET=Your_Bucket_Name
AWS_ACCESS_KEY_ID=Your_Development_Access_Key_Id
AWS_SECRET_ACCESS_KEY=Your_Development_Secret_Access_Key

And here is an example Procfile:

web: bundle exec rails server -p $PORT

Now to start foreman simply run the following command:

bundle exec foreman start -p 3000

To make things a bit easier I alias this in my bashrc:

alias fm='bundle exec foreman start -p 3000'

Deploying to Heroku

The last part is to make Heroku aware of your S3 environment settings. Instead of using a .env file you simply use the heroku config command:

heroku config:add AWS_ASSETS_BUCKET=Your_Bucket_Name
heroku config:add AWS_ACCESS_KEY_ID=Your_Production_Access_Key_Id
heroku config:add AWS_SECRET_ACCESS_KEY=Your_Production_Secret_Access_Key

Note you don’t need to specify a port anywhere (like you do when starting foreman) – Heroku will do this for you automatically.

That’s all there is to it! Happy coding.