Getting paperclip, heroku and aws s3 non-us region bucket working together

As I have found out earlier, images uploaded via paperclip to heroku will go missing after each push of code to heroku.

One way to keep images uploaded via paperclip permanent is to use a 3rd party storage service like s3 or keep it on a ftp server. I went for s3, mainly want to learn dealing with Amazon Web Services, might turn to ftp server later on if needed. If you would like to go the ftp server way, there are gem like FTP Storage for Paperclip and PaperclipFTP to make life easier.

  1. Add paperclip and aws-sdk to your gemfile
    gem 'paperclip'
    gem 'aws-sdk'

    Follow by the usual

    bundle install
  2. To start working with s3, first you need to signup for an aws account.
  3. Once you have an account, login then go to My Account/Console > AWS Management Console
    aws_mgt
  4. Select s3 from a host of services
  5. Create a bucket
    “A bucket is a container for objects stored in Amazon S3. When creating a bucket, you can choose a Region to optimize for latency”, that is what mentioned in the guide, so I chose Singapore as it is closest to my location.
    region
    Now if you have chosen “US standard” region, things will work out much straightforward, any non-us region will need some tweaks in the configuration. The documentation in heroku did mentioned that some international users may need to override the default URL structure and place the bucket’s name “domain-style” in the URL. Following that guide didn’t solve my problem though. I googled around, found a few more useful guides

    • Stackoverflow on setting env variables
    • Techspry on s3 configuation
    • DCChua on how to get Paperclip and AWS-S3 Singapore (and European) buckets working

    Coupled with the heroku documentation, I finally get my setup working combining them and change a bit here and there.

  6. Get your aws access key and secret access key from the Security Credential option
  7. In ./config/production.rb, defined this environment variables
      config.paperclip_defaults = {
    			    :storage => :s3,
    			    :s3_credentials => {
    			      :bucket => ENV['AWS_BUCKET'],
    			      :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
    			      :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
    			    },
    			    :path => ":class/:id/:basename_:style.:extension",
    			    :url => ":s3_sg_url"
    		  }
  8. Then set them by doing these in terminal from your apps
    heroku config:set AWS_BUCKET=your_bucket_name
    heroku config:set AWS_ACCESS_KEY_ID=your_access_key_id
    heroku config:set AWS_SECRET_ACCESS_KEY=your_secret_access_key

    You can of course set these values in the ./config/production.rb file, but then it is not protected if your repo is not private.

  9. In ./config/initializer, create paperclip.rb, and add these lines
    Paperclip.interpolates(:s3_sg_url) do |att, style| 
    "#{att.s3_protocol}://s3-ap-southeast-1.amazonaws.com/#{att.bucket_name}/#{att.path(style)}"
    end

git commit, push and then push to heroku, images uploaded from your apps should now store in s3.

2 thoughts on “Getting paperclip, heroku and aws s3 non-us region bucket working together

  1. Hey there!

    Just noticed the pingback!

    Glad that you found my little blog post useful. I like your blog posts and what you’re doing.

    Hopefully we could meet up one day over coffee!

    Cheers,
    David

  2. David, thanks for stopping by, and hey, your post “How to get Paperclip and AWS-S3 Singapore (and European) buckets working” really help me a lot 🙂

Leave a Reply

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