I'm using paperclip, fog, figaro gems to upload images to amazon S3. In production works fine as I introduced the env variables in heroku by hand.
But in development, it is suposed to use the env from the aplication.yml file (added to .gitignore). It is not using this file, as in development the ENV[] placed in application.yml do not exist.
I followed several tutorial for this, and in all of them I understand that the ENV[] introduced in applicaction.yml should be used. Am I wrong? Am I missing something? Do I need something else? I read that I can introduce the ENV[] by hand typing export, but I need to know if it is not enough to write them down at application.yml
#config/application.yml
MAPS_API_KEY: 1234googlemapapikey56788
SECRET_KEY_BASE: ab1234567longkeyy2979127401411124
AWS_ACCES_KEY_ID: ACCESSKEYID1234567
AWS_SECRET_ACCESS_KEY: SECRETKEY123456788/jaa\12345
AWS_REGION: eu-west-1
S3_HOST_NAME: s3-eu-west-1.amazonaws.com
development:
FOG_DIRECTORY: example-dev
S3_BUCKET_NAME: example-dev
production:
FOG_DIRECTORY: example-production
S3_BUCKET_NAME: example-production
in development and production I use the same code:
#config/environments/development.rb && config/environments/production.rb
config.paperclip_defaults = {
storage: :s3,
s3_credentials: {
bucket: ENV.fetch('S3_BUCKET_NAME'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
s3_region: ENV.fetch('AWS_REGION'),
}
}
In production works fine, and in development I get errors like:
development.rb:54:in `fetch': key not found: "AWS_ACCESS_KEY_ID" (KeyError)
# config/initializers/paperclip.rb
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'
The config/application.yml you list above has a typo.
The key you want is AWS_ACCESS_KEY_ID, but the copied file uses AWS_ACCES_KEY_ID (where access is missing the second s).
I suspect that should get things working for you again.
Related
I am using node & expressjs as an app. I have problem in deploying it to serverless with dotenv (without using any dotenv plugin).
My serverless.yml is this:
functions:
server:
handler: index.server
events:
- http: ANY /
- http: "ANY /{proxy+}"
environment:
ENV_VAR1: ${env:ENV_VAR1}
and my .env.staging is this:
ENV_VAR1='ENV_VAR1 using .env.staging'
ENV_VAR2='ENV_VAR2 using .env.staging'
I use AWS Lambda and deploy it using sls deploy --stage staging. So far I can read the ENV_VAR1from .env.staging by calling process.env.ENV_VAR1 because I explicitly define it in the serverless.yml file. But that's not the case with ENV_VAR2.
My question is, how to load all the .env.{stage} file without defining the key one by one?
I hope to load it similar to something like this:
environment: ${file(.env.${self:stage})}
Thank you in advance.
As I know, there is no way, you'll have to do it one by one (you have to have an object with key-value pairs inside environment, but you are trying to give it a string - even if it is going to be interpreted as a file containing something, it is still a string when you are referencing it).
I'm not an expert, so there still might be some tricks.
I've moved a Rails 3.2.5 app from Heroku to a VPS and while the app was working beautifully on Heroku in terms of the log drain output, unfortunately all log output on the VPS and even running locally lacks timestamps or any other tags I'd like to prepend.
After attempting to create a fresh test app and including the following one of the config/envrionments or config/application.rb I've found that it prepends the indicated tags:
config.log_tags = [:uuid, :remote_ip, lambda { |req| Time.now }]
Notwithstanding, I've tried everything I can think of so far from combing through the app gems to grepping everything for any occurrence of "log" within the config and lib folders and subfolders (such as initializers).
I don't know, if somehow the Rails logger may be disabled, how can I find this out? Or what else could be going on here? Or what should I look for precisely?... Or should I attempt to force Rails logger and, if so, where & what should I insert Rails logger reset code to find out in an attempt to isolate where during system init the problem is occurring?
I had the same issue, you probably need to use ActiveSupport::TaggedLogging.
config.logger = ActiveSupport::TaggedLogging.new(Logger.new($stdout))
I have a pretty straightforward model and attachment
has_attached_file :upload,
:storage => :s3,
:bucket => 'bestofbauer',
:s3_credentials => {
:access_key_id => ENV['MyAccessKEY'],
:secret_access_key => ENV['MySecretKey']
}
I have a bucket setup with s3 called bestofbauer.
I know I could refactor the credentials into an initializer but I haven't gotten this to save an attachment yet so I haven't worried about it.
When I run the save for the object and its attachement I get:
RuntimeError in RecommendationsController#create
Missing credentials
I have poured over: Credentials missing when uploading photos with Paperclip and Amazon s3 but that didn't resolve my issue.
I am using the following gems:
gem "paperclip"
gem "sws-sdk"
gem 'aws-s3'
Any other ideas?
You need to set your environment variables. Here's two different ways to do it:
Every time you run rails server or any other command that accesses your S3 account you need to include your keys:
$ MyAccessKEY=ACCESS_KEY MySecretKEY=SECRET_KEY rails server
I'm assuming you're using bash so edit your ~/.bash_rc or ~/.bash_profile to set your environment variables
export MyAccessKEY=ACCESS_KEY
export MySecretKEY=SECRET_KEY
Then open a new terminal window and double-check that they're set
$ echo $MyAccessKey
> ACCESS KEY PRINTS OUT HERE
If you're deploying to Heroku then you'll want to provide your environment variables there as well:
$ heroku config:add MyAccessKEY=ACCESS_KEY MySecretKEY=SECRET_KEY
You can review your Heroku config:
$ heroku config
It will list out all of the config variables you have for that app.
You'll probably want to put your S3 bucket name in an ENV setting as well so you don't mess up your bucket when testing locally.
Background
I have an app that I recently updated to Rails 3.2.1 (from Rails 3.0.x) and have refactored the JS and CSS assets to make use of the new asset pipeline. The app is hosted on Heroku with the Celadon Cedar stack.
App Config
I keep application specific configuration in a YAML file called app_config.yml and load it into a global APP_CONFIG variable using an initializer:
# config/initializers/load_app_config.rb
app_config_contents = YAML.load_file("#{Rails.root.to_s}/config/app_config.yml")
app_config_contents["default"] ||= {}
APP_CONFIG = app_config_contents["default"].merge(
app_config_contents[Rails.env] || {} ).symbolize_keys
Asset Compilation on Heroku
Heroku has support for the Rails asset pipeline built into the Cedar stack. When you push an app to Heroku it automatically calls rake assets:precompile on the server as a step in the deploy process. However it does this in a sandboxed environment without database access or normal ENV vars.
If the application is allowed to initialize normally during asset precompilation an error is thrown trying to connect to the database. This is easily solved by adding the following to the application.rb file:
# Do not load entire app when precompiling assets
config.assets.initialize_on_precompile = false
My Problem
When initialize_on_precompile = false is set, none of the initializers in config/initializers/* are run. The problem I am running into is that I need the APP_CONFIG variable to be available during asset precompilation.
How can I get load_app_config.rb to be loaded during asset compilation without initializing the entire app? Can I do something with the group parameter passed to Rails::Application.initialize! ?
Rails lets you register initializers only in certain groups, but you need to use the Railtie API:
# in config/application.rb
module AssetsInitializers
class Railtie < Rails::Railtie
initializer "assets_initializers.initialize_rails",
:group => :assets do |app|
require "#{Rails.root}/config/initializers/load_config.rb"
end
end
end
You don't need to check if AppConfig is defined since this will only run in the assets group.
And you can (and should) continue to use initialize_on_precompile = false. The load_config.rb initializer will be run when initializing the app (since it's in config/initializers) and when pre-compiling without initializing (because of the above code).
Definitely check out asset_sync on github. Or our Heroku dev centre article on Using a CDN asset Host with Rails 3.1 on Heroku.
The issues with environment variables have recently been solved by a Heroku labs plugin, that makes your application's heroku config variables accessible during compilation time. To enable this, read about the user_env_compile plugin.
Also. There is quite a big performance improvement in using asset_sync vs letting your application lazily compile assets in production or serving them precompiled directly off your app servers. However I would say that. I wrote it.
With asset_sync and S3 you can precompile assets meaning all the assets are there ready to be served on the asset host / CDN immediately
You can only require the :assets bundle in application.rb on precompile, saving memory in production
Your app servers are NEVER hit for asset requests. You can spend expensive compute time on, you know. Computing.
Best practice HTTP cache headers are all set by default
You can enable automatic gzip compression with one extra config
Here's what I came up with. In the assets that need app configuration, I place this line at the very beginning:
<% require "#{Rails.root}/config/initializers/load_config.rb" unless defined?(AppConfig) %>
... and add .erb to the file name, so that video_player.js.coffee becomes video_player.js.coffee.erb. Then I can safely use AppConfig['somekey'] afterwards.
During the asset pre-compilation, it loads app config despite the initialize_on_precompile set to false, and does it only once (which avoids constant redefinition issues).
Yes, it's a kludge, but many times nicer than embedding configs in asset files.
For Heroku I am running the Asset Sync gem to store my files on a CDN to avoid hitting Heroku for static images. It works nicely. I also have initialize on precompile false, but the Asset Sync runs it's own initializer so you could put your code in that. https://github.com/rumblelabs/asset_sync
Although your intializer is not run when the assets are precompiling, you should still find that they run as Rails boors up as normal, however, this will be on the first hit to the application rather than at the deploy step.
I'm not entirely sure what the issue you're having is, but if you follow the Rails conventions the deploy will work as expected.
I'm currently using Compass with Heroku using this configuration recommended on the Heroku knowledge base. Heroku has a read-only file system, and so the compiled stylesheets need to be stored in /tmp. This works fine remotely on Heroku; locally, however, Rails expects to find stylesheets in /public/stylesheets (when called through = stylesheet_link_tag 'screen.css', :media => 'screen, projection').
In order to solve the problem, I have created symbolic links in /public/stylesheets using ln -s tmp/stylesheets/screen.css public/stylesheets/screen.css and that seems to work.
Is there a way to solve this problem without using symbolic links, perhaps by changing some configuration in Rails? I've poked around without much success.
Here is my config/initializers/compass.rb:
require 'compass'
require 'compass/app_integration/rails'
Compass::AppIntegration::Rails.initialize!
# Required for Heroku:
require 'fileutils'
FileUtils.mkdir_p(Rails.root.join("tmp", "stylesheets"))
Compass::AppIntegration::Rails.initialize!
Rails.configuration.middleware.delete('Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Rack::Static',
:urls => ['/stylesheets'],
:root => "#{Rails.root}/tmp")
And here is my config/compass.rb:
project_type = :rails
project_path = Compass::AppIntegration::Rails.root
# Set this to the root of your project when deployed:
http_path = "/"
# Necessary for Heroku (original commented out:
css_dir = 'tmp/stylesheets'
#css_dir = "public/stylesheets/compiled"
sass_dir = 'app/views/stylesheets'
environment = Compass::AppIntegration::Rails.env
Any help would be greatly appreciated.
I was actually just about to set up Compass with our Rails application, which is hosted on Heroku, so cheers for giving me an excuse to work through this. :)
The answer is simple:
Modify 'config/compass.rb':
project_type = :rails
project_path = Compass::AppIntegration::Rails.root
http_path = "/"
environment = Compass::AppIntegration::Rails.env
if environment == 'production'
css_dir = "tmp/stylesheets"
sass_dir = "app/views/stylesheets"
else
css_dir = "public/stylesheets"
sass_dir = "app/stylesheets"
end
Then modify 'config/initializers/compass.rb':
require 'compass'
require 'compass/app_integration/rails'
Compass::AppIntegration::Rails.initialize!
require 'fileutils'
FileUtils.mkdir_p(Rails.root.join("tmp", "stylesheets"))
environment = Compass::AppIntegration::Rails.env
if environment == 'production'
Compass::AppIntegration::Rails.initialize!
Rails.configuration.middleware.delete('Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Sass::Plugin::Rack')
Rails.configuration.middleware.insert_before('Rack::Sendfile', 'Rack::Static',
:urls => ['/stylesheets'],
:root => "#{Rails.root}/tmp")
end
... and voila, you're good.
ok, I'm a big heroku and compass fan myself so i've been through this many times
Heroku's docs, whilst giving correct information, provide poor advice in this instance.
When using compass, the best thing to do, 99.999% of the time is turn it off in production mode.
This means that you compile your stylesheets on your development machine and then add them to your git repo before pushing to heroku.
You will suffer a reasonably sizeable performance hit if you allow compass to compile on the server.
So here's what I do:
You should have a config.ru file at the base of your app. Open it and add the following:
require 'sass/plugin/rack'
use Sass::Plugin::Rack
Sass::Plugin.options[:never_update] = true
You can then remove quite a lot of the code from your initializer (especially the part where you unload Sass::Plugin::Rack). Additionally you will want to remove the if statement from compass.rb in config folder
Think about it, why would you want Sass to compile a stylesheet on the server? It just eats up processing power. Hope this helps,
EDIT::
PS - I should add that you will need to run compass watch from the command line now in order to get your stylesheets to compile in your dev environment
The recommended Heroku configuration will also work locally.
Removed the second 'Compass::AppIntegration::Rails.initialize!' from config/initializers/compass.rb, you only need it once.
Ensure your scss files are in 'app/views/stylesheets'
On both local and production servers the stylesheets will be compiled to tmp/stylesheets, and a request to /stylesheets will resolve to tmp/stylesheest. No need for two separate configurations.