How to set up Amazon S3, paperclip, and ENV variables - ruby-on-rails

I have tried many different ways to set up S3 using ENV variables for image uploads and cannot get it to work. I know my keys and bucket name work, because when I put them straight into the code, my images upload correctly. However, when I try to switch to ENV variables, things do not work.
I used the figaro gem, which created application.yml. In that file, I have:
S3_BUCKET_NAME "xxxxx"
AWS_ACCESS_KEY_ID: "AAAAAAAAA"
AWS_SECRET_ACCESS_KEY: "BBBbbbBBBB"
Not sure if there should be any quotation marks there or not, but right now, I have them in. I have tried without, also.
In my model (listing.rb), I have:
has_attached_file :image,
:styles => { :medium => "200x" , :thumb => "100x100" },
:default_url => "default.png",
:storage => :s3,
:s3_credentials => Proc.new{|a| a.instance.s3_credentials }
def s3_credentials
{:bucket => ENV["S3_BUCKET_NAME"], :access_key_id => ENV["AWS_ACCESS_KEY_ID"],
:secret_access_key => ENV["AWS_SECRET_ACCESS_KEY"]
end
Like I said, when I hard code the values into def s3_credentials, everything works fine. It's just when I try to swap out ENV variables that things fall apart.
In paperclip.rb, I have:
Paperclip::Attachment.default_options[:s3_host_name] = 's3-us-west-2.amazonaws.com'
I also have this code in both production.rb and development.rb:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
Here is the error message I get when uploading a new image: "The request signature we calculated does not match the signature you provided. Check your key and signing method." On line: "if #listing.save". The ones that were uploaded w/ the credentials hard-coded are still able to be seen in my app.
I'm fairly new to rails and have looked here and other places, including the S3 and paperclip docs, and cannot find a solution that will work. Please let me know if you need to see any other code. I plan on deploying to heroku, if that matters, and saw that figaro is supposed to play nicely with heroku. THANK YOU.
EDIT/UPDATE: For anyone else reading this in the future, Sachin's answer below worked. However, there was a '+' in one of my key IDs. When trying to added the ENV variable via command line, all the characters after the '+' (and including it) were cut off. Simply wrap them in "", and you should be good to go.
Also, I dropped use of the figaro gem, and set up an aws.rb initializer file (per Amazon's instructions). Here are the contents of that file:
AWS.config(
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
)
S3_BUCKET = AWS::S3.new.buckets[ENV['S3_BUCKET']]
And I don't know if this made any difference, but my development.rb and production.rb files now have the following as paperclip defaults:
config.paperclip_defaults = {
:storage => :s3,
:bucket => "your_real_bucket_name_here_in_quotes",
:s3_credentials => {
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
Also note the switch to referring to the ENV bucket name as S3_BUCKET vs. S3_BUCKET_NAME.
And the code in my model (listing.rb) is now this:
has_attached_file :image, :styles => { :medium => "200x", :thumb "100x100"}, :default_url => "default.png", :storage => :s3, :bucket => "your_real_bucket_name_here_in_quotes"
validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]

You can do one thing:
You can set this configuration in your development.rb or production.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
And If you want to set this environment variables into local then use this:
sudo nano ~/.profile
Then add your variables over here
export S3_BUCKET_NAME="your bucket name"
export AWS_ACCESS_KEY_ID="your access key id"
export AWS_SECRET_ACCESS_KEY="your secret access key"
And then reload your ~/.profile with . ~/.profile
Check added variable with echo $S3_BUCKET_NAME
And for Heroku
You can set your variable like:
heroku config:set S3_BUCKET_NAME="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"
Check that variables added or not in heroku with heroku config
For more detail you can refer form here.
Let me know if you need me more..

Related

Rails ArgumentError (missing required :bucket option) fixes not working?

My Rails app is hosted on Heroku but I need to get Paperclip working locally so I can upload photos in testing. I'm really close, but I'm stuck on the "missing required :bucket option" error.
I've tried moving around settings in my environment files as well as well as adding a config/application.yml file with my AWS credentials in it, but no dice.
Here's my config from development.rb (looks the same in production.rb):
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
I've tried moving :bucket attribute outside of :s3_credentials but it didn't change anything. Application.yml looks like this:
AWS_ACCESS_KEY_ID="xxxxxxxxxxxxxxxxx"
AWS_SECRET_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx"
S3_BUCKET_NAME="xxxxxx"
I also installed the dot-env gem and added an s3.env file to the index of my app which contains the same credentials as above, but even that hasn't worked. Nor did adding my Paperclip config inline with the has_attached_file in my model.
What do I do??
Alternatively, if someone runs into this problem and doesn't want to use a .env file, the following works.
Assuming your bucket is hosted in the US region, put a file called aws.yml under the config dir. The file should be in the following format:
development:
access_key_id: AWS_ACCESS_KEY_ID
secret_access_key: AWS_SECRET_KEY_ID
production:
access_key_id: AWS_ACCESS_KEY_ID
secret_access_key: AWS_SECRET_KEY_ID
In your model:
class Model < ActiveRecord::Base
has_attached_file :avatar, styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'}, :storage => :s3,
:s3_credentials => "#{Rails.root}/config/aws.yml",
:bucket => "your_bucket_name"
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
Replace your_bucket_name with the name of your actual bucket.
Gemfile:
gem 'aws-sdk', '< 2.0'
Under Environments, production and development:
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
To put it in production on Heroku, you have to set the following using the terminal:
$ heroku config:set S3_BUCKET_NAME=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
Your Application.yml file doesn't look like YAML. It should look like this:
AWS_ACCESS_KEY_ID: "xxxxxxxxxxxxxxxxx"
AWS_SECRET_ACCESS_KEY: "xxxxxxxxxxxxxxxxxxxx"
S3_BUCKET_NAME: "xxxxxx"
If you are loading the yml file like they advise here you'll want your yml file to look like this:
development:
AWS_ACCESS_KEY_ID: "xxxxxxxxxxxxxxxxx"
AWS_SECRET_ACCESS_KEY: "xxxxxxxxxxxxxxxxxxxx"
S3_BUCKET_NAME: "xxxxxx"
You need a way to set the environment variables for your app in your development environment. Using Application.yml or .env file should work, but you probably don't need both.

Trouble uploading files to Amazon s3 in development

Able to upload files to Amazon s3 in my production environment with Heroku, but unable to do this in my development environment. Here is how the situation looks currently
Development.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
After following the advice of this S.O. Post, I created a file application.yml in my config directory with the following code:
AWS_ACCESS_KEY_ID: "***"
AWS_SECRET_ACCESS_KEY: "***"
AWS_BUCKET: "themoderntrunk"
I didn't change my design model though
has_attached_file :photo, :styles => { :thumbnail => "80x80#",
:small => "150x150>"
}
When I'm uploading file's now, i get this error
missing required :bucket option
Many people I've seen had this same problem, but none of the answers have been able to solve my problem. Any guidance would be truly appreciated. Thanks.
Allegorically, this particular issue has commonly been resolved using Fog, Ruby's canonical cloud services library.
# Gemfile
gem 'fog'
Run bundle install, then modify your configuration file as follows:
# config/environments/development.rb
Paperclip::Attachment.default_options.merge!(
:storage => :fog,
:fog_credentials => {
:provider => 'AWS',
:aws_access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:aws_secret_access_key => ENV['AWS_SECRET_ACCESS_KEY'],
},
:fog_directory => ENV['AWS_BUCKET'],
:bucket => ENV['AWS_BUCKET']
)
Restart your server to reload the environment – uploads should work.
UPDATE:
Upon a rereading of your question, I noticed that you're to passing an environment global named ENV['S3_BUCKET_NAME'], but the variable you should actually pass is named ENV['AWS_BUCKET']. I suspect this is why the missing required :bucket option was being thrown. Renaming the variable may resolve your original issue:
# config/environments/development.rb
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['AWS_BUCKET'], # Matches global declaration in `application.yml`
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}

AWS Credentials Missing when pushing to Heroku

Answered: I misspelled AWS_SECRET_ACCESS_KEY when setting the environment variables for Heroku. I left off the second S.
I'm building a Rails 4 application, and using Paperclip and AWS for image uploading. Every time I try to upload an image, I get AWS::Errors::MissingCredentialsError (Missing Credentials in the Heroku logs.
In my gem file I have
gem 'paperclip'
gem 'aws-sdk'
In my production.rb file I have
config.paperclip_defaults = {
:storage => :s3,
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
I have an initializer named aws-sdk.rb that only has this in it:
AWS.config({
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
})
And in my relevant model file I have
has_attached_file :picture,
:storage => :s3,
:s3_credentials => {
:bucket => 'MyBucketName',
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
},
styles: {
thumb: '100x100>',
square: '200x200#',
medium: '300x300>'
}
I didn't think that I needed to explicitly include the s3 credentials with the has_attached_file method? I tried it anyway. Still not working.
When I run heroku config it shows my access key, key id, and bucket names correctly.
I have no idea what's going wrong.

Getting S3 Credentials from the database at startup in rails

Using a combination of the rails-settings gem and paperclip, I've got my application set up such that one can specify S3 credentials in the database (through an interface in the front end) and can then declare attachments like this;
class Asset < ActiveRecord::Base
has_attached_file :attachment,
:default_url => "content/no-img.jpg",
:s3_credentials => {
:access_key_id => Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => Settings.AWS_SECRET_ACCESS_KEY
}
This works great, but this isn't the only type of attachment in the application (there are other things such as client logos). I'm finding that I need to specify the S3 credentials on every one. I've already tucked some of the defaults away in my app config file;
class Application < Rails::Application
#Paperclip Defaults
config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name"
}
And this all works great, but if I try to pull down the username and password into the app config too, I get the following error;
ActiveRecord::ConnectionNotEstablished (ActiveRecord::ConnectionNotEstablished)
A fairly self explanatory error message, but how do I get around it? If I put the config in the environment files I get the same issue, and if I put them in an initializer like this;
#Paperclip Defaults
MyApp::Application.config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name",
:s3_credentials => {
:access_key_id => RailsSettings::Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => RailsSettings::Settings.AWS_SECRET_ACCESS_KEY
}
}
Then the values don't seem to get picked up and paperclip defaults back to storing the files in my local system directory. Could anyone advise on the best approach to handling this?
EDIT
So after re-reading the documentation I discovered "After Initializers", which gets around the whole active-record not being loaded issue. I have this in my app config;
config.after_initialize do
#Paperclip Defaults
config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name",
:s3_credentials => {
:access_key_id => RailsSettings::Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => RailsSettings::Settings.AWS_SECRET_ACCESS_KEY
}
}
end
And specify this in each model;
has_attached_file :attachment,
:default_url => "content/no-img.jpg",
:path => "#{Rails.env}/:client_name/#{DateTime.now.year}/:name/:basename/:basename-:style.:extension"
yet it still isn't picking up the defaults I specify (it still tries to put them in the public/system folder)
Right, sorted. If anyone has this issue, here's the solution (you basically need to use the "initializers" method to switch active record on before you set the config);
initializer "active_record.initialize_database" do |app|
app.config.paperclip_defaults =
{
:storage => :s3,
:bucket => "my-bucket-name",
:s3_credentials => {
:access_key_id => RailsSettings::Settings.AWS_ACCESS_KEY_ID,
:secret_access_key => RailsSettings::Settings.AWS_SECRET_ACCESS_KEY
}
}
end

Using a non - US s3 server with rails, heroku and paperclip

I'm trying to set this up using the article on herokus developer site.
https://devcenter.heroku.com/articles/paperclip-s3
# config/environments/production.rb
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'],
:url => 'https://s3-ap-southeast-2.amazonaws.com'
}
}
However all of my images are pointing to the us http://s3.amazonaws.com/ server
How can i set paperclip to use the sydney server?
UPDATE:
paperclip successfully uploads files to the sydney server, it just wrongly uses the US server rather than the sydney one when trying to view them
Paperclip provides a handful of options, to optimize the configuration of your bucket.
The ones you're interested are url and s3_alias_url.
Your configuration would look like something like this :
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'],
},
:url => ':s3_alias_url',
:s3_alias_url => 's3-ap-southeast-2.amazonaws.com'
}
You can find more information and an other example in this google groups discussion.

Resources