Fog/Carrierwave config for Rails app on AWS Elastic Beanstalk - ruby-on-rails

I'm trying to set up Carrierwave and Fog to handle image and file uploads on a rails app that I have hosted on AWS' Elastic Beanstalk.
I'm a little confused on how to properly set up the Fog config.
I tried using my AWS Access and Secret keys (commented out in the example below). That through an error on my EB CLI (ERROR: NotAuthorizedError - Operation Denied. The security token included in the request is invalid.)
I'm tyring to use IAM instead of having my Access/Secret codes in my ruby code. Can anyone tell me how to set this up properly?
Here's my config file:
CarrierWave.configure do |config|
# Use local storage if in development or test
if Rails.env.development? || Rails.env.test?
CarrierWave.configure do |config|
config.storage = :file
end
end
# Use AWS storage if in production
if Rails.env.production?
CarrierWave.configure do |config|
config.storage = :fog
end
end
config.fog_credentials = {
:provider => 'AWS', # required
# :aws_access_key_id => 'My Access', # required
# :aws_secret_access_key => 'My Secret', # required
:use_iam_profile => true,
:region => 'eu-west-2' # optional, defaults to 'us-east-1'
}
config.fog_directory = 'elasticbeanstalk-us-west-2-XXXXXXXXXX' # required
#config.fog_host = 'https://assets.example.com' # optional, defaults to nil
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>'max-age=315576000'} # optional, defaults to {}
end

This is a setup that works for me:
config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV['aws_access_key_id'], # required
aws_secret_access_key: ENV['aws_secret_access_key'], # required
#region: 'Singapore', # optional, defaults to 'us-east-1'
#host: 's3.example.com', # optional, defaults to nil
#endpoint: 'olucube-images.s3-website-ap-southeast-1.amazonaws.com', # optional, defaults to nil
}
config.fog_directory = ENV['fog_directory'] # required
#config.fog_public = false # optional, defaults to true
# config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" }, # optional, defaults to {}
end
and I used figaro gem to hold my credentials as follow:
config/application.yml
aws_access_key_id: 'XXXXXXXXXXXXXXXXXXXX'
aws_secret_access_key: 'XXXXXXXXXXXXXXXXXX'
fog_directory: 'myAppName'

This was a bit a of a wild ride. I had a hard time figuring out that Figaro gem. It's probably simple but I didn't really understand it. So for a test, I put my keys directly in the code. It still didn't work.
I pushed my code to github (publicly) and didn't think too much of it. I was going to change the keys just in case. Before I was able to do that someone found my code on github and gained access to my AWS account. They started a bunch of EC2 instances and racked up $3000 worth of usage in a few hours!
My AWS account got suspended and I'm still dealing with having the charges reversed.
Anyway. I found out that you can actually set environment variables on the Elastic Beanstalk web interface. Its under Configuration → Software Configuration. So I did that instead of using Fiagro (much safer IMO). Now it works great. I simplified my Carrierwave config file to only use AWS calling the environment variables from EB. Here's the file:
# config/initializers/carrierwave.rb
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws'
config.fog_credentials = {
provider: 'AWS',
aws_access_key_id: ENV['S3_KEY'],
aws_secret_access_key: ENV['S3_SECRET'],
region: ENV['S3_REGION']
}
config.fog_directory = ENV['S3_BUCKET']
config.fog_public = false
config.storage = :fog
end
I changed my uploader files to use fog too. Here's an example:
# app/uploaders/image_uploader.rb
class ImageUploader < CarrierWave::Uploader::Base
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_white_list
%w(jpg jpeg gif png)
end
end
Everything works great now. I hope this helps someone else.

Related

Can carrierwave direct upload to local storage?

Sometimes I am away from internet and still need to work on upload pages. Carrierwave Direct seems to force storage :fog; with no way of overriding in dev.
Is it possible to tell Carrierwave Direct to use local storage (:file) and simply fallback to Carrierwave's development config settings?
Setting storage :file in carrierwave initializer under development config settings doesnt work...carrierwave_direct errors with "is not a recognized provider" from "<%= direct_upload_form_for #uploader do |f| %>".
I have attempted to work around carrierwave direct, but between forcing :fog, expecting a redirect url and expecting the direct_upload_form_for form method...carrierwave_direct is pretty much in charge.
Using storage :file in development would be a welcome feature for the carrierwave_direct gem. Does anyone know how to cleanly do this?
I think it can be done as follows:
CarrierWave.configure do |config|
if Rails.env.development? || Rails.env.test?
config.storage = :file
config.asset_host = ENV["dev_url"]
else
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV["aws_id"], # required
aws_secret_access_key: ENV["aws_key"], # required
region: ENV["aws_zone"] # optional, defaults to 'us-east-1'
}
config.fog_directory = ENV["aws_bucket"] # required
config.max_file_size = 600.megabytes # defaults to 5.megabytes
config.use_action_status = true
config.fog_public = false # optional, defaults to true
config.fog_attributes = { cache_control: "public, max-age=#{365.day.to_i}" } # optional, defaults to {}
end
end
And in your Uploader add in:
class SomeUploader < CarrierWave::Uploader::Base
if Rails.env.development? || Rails.env.test?
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
end

CarrierWave With Cloudfront Generating wrong URL

Hello I am using Cloudfront with CarrierWave and S3. For some reason in my app I am getting very strange URLs for my cloudfront path when using image_tag and I don't know where I am going wrong. Here is my carrierwave config file
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws' # required
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: 'accesskey', # required
aws_secret_access_key: 'secretaccess key', # required
region: 'us-east-1', # optional, defaults to 'us-east-1'
}
config.fog_directory = 'bwautosales' # required
# config.asset_host = 'randomletters.cloudfront.net'
config.asset_host = 'randomletters.cloudfront.net'
config.fog_public = true
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
and my production.rb file I have
config.action_controller.asset_host = 'randomletters.cloudfront.net'
but in my view when I do something like
<%= link_to image_tag(car.images[0], class: "img-responsive right-block", id: index), car %>
I get this -
src = https://randomletters.cloudfront.net/images/randomletters.cloudfront.net/uploads/car/images/28/car.png"
I'm sure this is an easy fix but don't know where I'm going wrong. Any help would be appreciated!
Image Uploader `
class ImageUploader < CarrierWave::Uploader::Base
include CarrierWave::MiniMagick
storage :fog
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
def extension_whitelist
%w(jpg jpeg gif png)
end
end
`
In your Carrierwave initializer change the line,
config.asset_host = 'randomletters.cloudfront.net' to config.asset_host = 'http://randomletters.cloudfront.net' to get the required cloudfront URL you needed.
You can also remove the line, config.action_controller.asset_host = 'randomletters.cloudfront.net' from Production.rb as the carrierwave itself fetches from the cloud-front url.
CarrierWave.configure do |config|
config.fog_provider = 'fog/aws'
config.fog_credentials = {
--------------
--------------
}
config.fog_directory = 'bwautosales'
config.asset_host = 'http://randomletters.cloudfront.net' # please check the change in this line.
config.fog_public = true
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
Just for the sake of adding credibility to Sravan's answer, I had the same problem and when I followed his instructions it started working properly. If you leave out the http:// from
config.asset_host = <>
It gets confused and tries to use a different path with your site's domain name. I had the same issue, but adding http:// to the beginning of the url fixed it.

Carrierwave and S3 not working

I have a problem with authentication, i try to upload but i get this
The request signature we calculated does not match the signature you provided. Check your key and signing method.
initializer carrierwave.rb
CarrierWave.configure do |config| # optional, defaults to "fog"
config.fog_credentials = {
provider: 'AWS', # required
aws_access_key_id: ENV["AWS_ACCESS_KEY_ID"], # required
aws_secret_access_key: ENV["AWS_ACCESS_SECRET_KEY"], # required
}
config.fog_directory = ENV["AWS_BUCKET_NAME"] # required
config.fog_attributes = { 'Cache-Control' => "max-age=#{365.day.to_i}" } # optional, defaults to {}
end
gem "carrierwave"
gem "fog"
gem "figaro"
set the environment variables
i also created a bucket in S3.
Is there anything i am missing here? It works locally though.
Also changed the image_uploader.rb to storage :fog

ckeditor Rails 4 carrierwave s3 fog

I am having a lot of difficulties uploading images to S3 via CarrierWave & Fog. I already had set up carrierwave and s3 and had no problems but then I added Ckeditor. The biggest problem I am having is that all the images I upload using the Ckeditor photouploader have an expiration time. I don't want them to expire and I can't find any documentation on how to change this.
CarrierWave.configure do |config|
config.root = Rails.root.join('tmp') # adding these...
config.cache_dir = 'carrierwave' # ...two lines
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => ENV['AWS_KEY'], # required
:aws_secret_access_key => ENV['AWS_SECRET'], # required
:region => ENV['AWS_REGION'], # optional, defaults to 'us-east-1'
}
config.fog_directory = ENV['FOG_DIR'] # required
config.fog_public = false # optional, defaults to true
config.fog_attributes = {'Cache-Control'=>"max-age=#{365.day.to_i}"} # optional, defaults to {}
end
So I have solved the fact that config.fog_public needs to be set to true on s3 to receive urls without expiration dates. Does anyone know how to change a lot of images that are on s3 with expiration dates to public without having to reupload all of the images?

Rspec and Carrierwave. When changing config.storage to file for testing, I get an ArgumentError is not a recognized storage provider exception

I have two carrierwave uploaders in my application. ImageUploader is for uploading locally and ImageRemoteUploader for uploading to Amazon S3 storage using fog. ImageUploader has storage set to :file and ImageRemoteUploader has storage set to :fog. This setup works fine, but when I start to set up my rspec tests, things change.
The problem arises when I change the ImageRemoteUploader to use :file storage during testing. I do this in my fog initialization file. The file,
/config/initializers/fog.rb, looks like:
CarrierWave.configure do |config|
if Rails.env.test?
config.storage = :file
config.enable_processing = false
else
config.fog_credentials = {
:provider => 'AWS', # required
:aws_access_key_id => 'XXXXXXXX', # required
:aws_secret_access_key => 'XXXXXX', # required
:region => 'XXXX' # optional, defaults to 'us-east-1'
}
config.fog_directory = 'xxx' # required
config.fog_public = true
end
end
When I do this, I get an ArgumentError is not a recognized storage provider carrierwave exception. When I use the fog credentials (I don't set config.storage to :file), the test works as expected.
Carrierwave 0.7.1, Rails 3.2.8, Ruby 1.9.3, Rspec 2.10
Thanks.
I'd try moving the config.storage and config.enable_processing lines into lib/initializers/carrierwave.rb, as recommended in the Carrierwave docs.
Fog also has its own mocking support, which is enabled by running Fog.mock! before the examples. This might be a better approach.

Resources