Configure Nginx to work with Rails 3 assets pipeline - ruby-on-rails-3

I am trying to configure Nginx to be used with Rails 3 assets pipeline.
http {
passenger_root /home/ubuntu/.rvm/gems/ruby-1.9.3-p327/gems/passenger-3.0.18;
passenger_ruby /home/ubuntu/.rvm/wrappers/ruby-1.9.3-p327/ruby;
include mime.types;
default_type application/octet-stream;
sendfile on;
#keepalive_timeout 0;
keepalive_timeout 65;
server {
listen 80;
server_name myprojecthost.com *.myprojecthost.com;
#charset koi8-r;
#access_log logs/host.access.log main;
root /var/www/<my proj>/current/public;
location / {
passenger_enabled on;
rails_env staging;
root /var/www/<my proj>/current/public;
}
location ~ ^/(assets)/{
root /var/www/<my proj>/current/public;
expires max;
add_header Cache-Control public;
}
}
}
Rails is configured as follows:
MyProj::Application.configure do
# Code is not reloaded between requests
config.cache_classes = true
# Full error reports are disabled and caching is turned on
config.consider_all_requests_local = false
config.action_controller.perform_caching = true
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_assets = true
# Compress JavaScripts and CSS
config.assets.compress = true
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
# Generate digests for assets URLs
config.assets.digest = true
# Defaults to Rails.root.join("public/assets")
# config.assets.manifest = YOUR_PATH
# Specifies the header that your server uses for sending files
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
# config.force_ssl = true
# See everything in the log (default is :info)
config.log_level = :debug
# Use a different logger for distributed setups
# config.logger = SyslogLogger.new
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation can not be found)
config.i18n.fallbacks = true
# Send deprecation notices to registered listeners
config.active_support.deprecation = :notify
end
My css files return 404 error.
If I remove the block "location ~ ^/(assets)/{" it works well but it is terribly slow.
Can someone help me?

Are you precompiling your assets? rake assets:clean and rake assets:precompile ?

Related

Unable to login to my rails app after implenting secure_headers gem in my local environment

My website uses Rails 3, in which I am trying to fix CSP(Content Security Policy) related issues.
I have installed secure_headers gem.
Then after adding the below code in Application Controller:
SecureHeaders::Configuration.default do |config|
config.secure_cookies = true # mark all cookies as "secure"
config.hsts = "max-age=#{20.years.to_i}; includeSubdomains; preload"
config.x_frame_options = "DENY"
config.x_content_type_options = "nosniff"
config.x_xss_protection = "1; mode=block"
config.x_download_options = "noopen"
config.x_permitted_cross_domain_policies = "none"
config.csp = {
# "meta" values. these will shaped the header, but the values are not included in the header.
report_only: true, # default: false
preserve_schemes: true, # default: false. Schemes are removed from host sources to save bytes and discourage mixed content.
# directive values: these values will directly translate into source directives
default_src: %w(https: 'self'),
# frame_src: %w('self' *.twimg.com itunes.apple.com),
# connect_src: %w(wws:),
font_src: %w('self' https://fonts.gstatic.com https://cdnjs.cloudflare.com/ajax/libs/font-awesome https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/fonts/glyphicons-halflings-regular.svg https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/fonts/glyphicons-halflings-regular.ttf https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/fonts/glyphicons-halflings-regular.woff ),
img_src: %w('self' https://*.youtube.com https://cdnjs.cloudflare.com/ajax/libs/font-awesome data: ),
media_src: %w('self' https://img.youtube.com ),
object_src: %w('self'),
script_src: %w('self' 'unsafe-inline' https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js https://www.google-analytics.com/ga.js http://www.google-analytics.com/ga.js),
style_src: %w('self' 'unsafe-inline' https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.2.0/css/font-awesome.min.css https://fonts.googleapis.com https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.min.css http://fonts.googleapis.com https://fonts.googleapis.com/css?family=Raleway:400,700 https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.1/css/bootstrap.min.css https://fonts.googleapis.com/css?family=Roboto:400,700 http://fonts.googleapis.com/css?family=Roboto:400,700),
base_uri: %w('self'),
child_src: %w('self'),
# form_action: %w('self' ),
frame_ancestors: %w('none'),
plugin_types: %w(application/x-shockwave-flash),
# block_all_mixed_content: true, # see [http://www.w3.org/TR/mixed-content/](http://www.w3.org/TR/mixed-content/)
# upgrade_insecure_requests: true, # see https://www.w3.org/TR/upgrade-insecure-requests/
report_uri: %w(https://report-uri.io/example-csp)
}
end
I am unable to perform login action. Is there any other way to implement CSP in rails, I am implementing it in a wrong way. I could not find any blog which explains implementation of the gem. Please help.
Update:
On changing the value of secure_cookies to false I am able to login to my website, but then I am sure making secure_cookies false will have some bad effect on my app.
It sounds like the login isn't happening over https, the cookies are getting marked as secure, and then are not included on subsequent requests. I opened github.com/twitter/secureheaders/issues/243 to handle this. Using https and strict transport security would also fix this.

Meteor on httpd (Apache/2.4.6 CentOS) proxy and WebSockets

I can't workout how to get WebSockets to work when I deploy my meteor app online. I keep getting this error:
WebSocket connection to 'ws://website.com/sockjs/***/********/websocket' failed: Unexpected response code: 400
I think this is due to the fact that apache sits in front of my meteor app. I know Apache 2.4 had a bug to make ws:// working, but I think this should be resolved by modules/mod_proxy_wstunnel.so, which I have enabled (of course I have enabled also modules/mod_proxy.so)
Here's my config. I'm running Meteor 1.2.1 as a systemd service (/etc/systemd/system/meteor.service) like so:
[Unit]
Description=meteor nodejs daemon
After=network.target remote-fs.target
[Service]
User=root
ExecStart=/usr/bin/node /home/root/www/main.js
Restart=always
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=meteor
Environment=ROOT_URL=http://website.com
Environment=PORT=3000
Environment=NODE_ENV=production
Environment=MONGO_URL=mongodb://127.0.0.1:27017/meteor
[Install]
WantedBy=multi-user.target
This is the output of httpd -v
Server version: Apache/2.4.6 (CentOS)
Server built: Aug 28 2015 22:11:18
And this is the relevant part in my vhost config (/etc/httpd/conf/httpd.conf) for website.com:
<VirtualHost my.ser.ver.ip:8080>
ServerName website.com
ServerAlias www.website.com
ProxyRequests Off
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
<Proxy *>
Allow from all
</Proxy>
</VirtualHost>
I've already tried to add the RewriteCond as suggested here but no success...
Any idea? I'm also having issue getting oauth to work with the accounts-facebook package and I guess the problem is for the same reason? As in, there is something wrong in my proxy settings?
Solved the mystery. Of course it was my bad: I forgot all about Varnish.
I had Varnish set on port 80 forwarding the request to Apache, which was in turn proxying the request to node.js. I resolved by removing apache and thus configuring Varnish to serve straight to node.js for that specific domain.
This is what I did:
Implemented this default.vcl in /etc/varnish/
Removed import directors and all the content inside sub vcl_init {} (as I only have a single server)
Replaced set req.backend_hint = vdir.backend(); in sub vcl_recv {} with:
if (req.http.Host ~ "^(www\.)?website.com") {
set req.backend_hint = nodejs;
} else {
set req.backend_hint = apache;
}
Created the two backends like so:
backend apache {
.host = "127.0.0.1";
.port = "8080";
.max_connections = 300;
.probe = {
.request =
"HEAD / HTTP/1.1"
"Host: localhost"
"Connection: close";
.interval = 5s;
.timeout = 1s;
.window = 5;
.threshold = 3;
}
.first_byte_timeout = 300s;
.connect_timeout = 5s;
.between_bytes_timeout = 2s;
}
backend nodejs {
.host = "127.0.0.1";
.port = "3000";
.connect_timeout = 1s;
.first_byte_timeout = 2s;
.between_bytes_timeout = 60s;
.max_connections = 800;
}

Altering CSS in Rails 3.2 does not change styles without precompiling assets first

I upgraded an app to Rails 3.2 and installed Bourbon on it. When I make a CSS change locally, for some reason I'm not seeing any change made. Only when I precompile the assets after making a change do I see it in development. Does anyone know what might be going wrong?
Here's my development.rb:
POP::Application.configure do
# Settings specified here will take precedence over those
# in config/application.rb
# In the development environment your application's code is reloaded on
# every request. This slows down response time but is perfect for development
# since you don't have to restart the web server when you make code changes.
config.cache_classes = false
# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true
# Show full error reports and disable caching
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
# Don't care if the mailer can't send
config.action_mailer.raise_delivery_errors = false
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
# Only use best-standards-support built into browsers
config.action_dispatch.best_standards_support = :builtin
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
# # GMail settings
# ActionMailer::Base.smtp_settings = {
# :address => "smtp.gmail.com",
# :port => 587,
# :authentication => "plain",
# :enable_starttls_auto => true
# }
end
And application.rb:
require File.expand_path('../boot', __FILE__)
require 'rails/all'
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
module POP
class Application < Rails::Application
# Settings in config/environments/* take precedence over those specified
# here.
# Application configuration should go into files in config/initializers
# -- all .rb files in that directory are automatically loaded.
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
# Only load the plugins named here, in the order given (default is
# alphabetical).
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running.
# config.active_record.observers = :cacher, :garbage_collector,
# :forum_observer
# Set Time.zone default to the specified zone and make Active Record
# auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
# Default is UTC.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from
# config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales',
# '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
# Configure the default encoding used in templates for Ruby 1.9.
config.encoding = "utf-8"
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
# Use SQL instead of Active Record's schema dumper when creating the
# database.
# This is necessary if your schema can't be completely dumped by the
# schema dumper,
# like if you have constraints or database-specific column types
# config.active_record.schema_format = :sql
# Enforce whitelist mode for mass assignment.
# This will create an empty whitelist of attributes available for
# mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or
# blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
config.active_record.whitelist_attributes = true
# Enable the asset pipeline
config.assets.enabled = true
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
# Config spec generators
config.generators do |g|
g.test_framework :rspec,
:fixtures => true,
:view_specs => false,
:helper_specs => false,
:routing_specs => false,
:controller_specs => true,
:request_specs => true
g.fixture_replacement :factory_girl, :dir => "spec/factories"
end
config.assets.initialize_on_precompile = false
end
end
Looks like a previous question I hadn't found had the answer. All I needed to do was run:
bundle exec rake assets:clean

Speeding up Rails 3.2.1 Development Environment

I'm running a rather large project in Development and its just too slow. I believe the reason is because on each request Rails reloads every class. This project literally has hundreds of classes so the response time is too slow.
How can I speed up my development environment?
I'm running Apache server, the latest version of Passenger, RVM ruby 1.9.2-p180 (which I'm more or less locked into the ruby version).
development.rb:
# (Development-only) what is our localhost called?
LOCALDOMAIN = File.read("/etc/context_dev_host").strip
# Don't verify SSL connections.
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
SMSAdmin::Application.configure do
config.cache_classes = false # reload on every request
config.whiny_nils = true # Log error messages when you accidentally call methods on nil.
config.consider_all_requests_local = true # Show full error reports and disable caching
config.action_controller.perform_caching = false # Show full error reports and disable caching
config.action_mailer.raise_delivery_errors = false # Don't care if the mailer can't send
config.action_mailer.default_url_options = { :host => "#{APP_HOSTNAME}" } # default url_for :host
config.action_mailer.raise_delivery_errors = false
# Distributed Assets will expect an asset host for path resolution:
config.action_controller.asset_host = Proc.new do |source, request|
ssl = request && request.ssl?
hash = false
subd = true
host = ( hash ? "a#{source.hash % 4}." : "" ) + ( subd && request && request.host || APP_HOSTNAME )
( ssl ? "https://" : "http://" ) + host
end
ActionMailer::Base.delivery_method = :sendmail
config.after_initialize do
# Custom developer files (generally to support Rake tasks, where we don't have a request to determine the FB API Key)
dh = File.read("/etc/context_dev_host").strip.split(".").first
df = File.expand_path("../#{dh}.rb", __FILE__)
if File.exists?(df) then
silence_warnings do
require(df)
end
end
end
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = false
config.assets.digest = false
# Raise exception on mass assignment protection for Active Record models
config.active_record.mass_assignment_sanitizer = :strict
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
end

nginx upload module

I am having some trouble getting the nginx upload module working with my rails application.
my route
match '/images/fast_upload' => 'images#create', :via => :post
image model
attr_accessor :tmp_upload_dir
after_create :clean_tmp_upload_dir
# handle new param
def fast_asset=(file)
if file && file.respond_to?('[]')
self.tmp_upload_dir = "#{file['filepath']}_1"
tmp_file_path = "#{self.tmp_upload_dir}/#{file['original_name']}"
FileUtils.mkdir_p(self.tmp_upload_dir)
FileUtils.mv(file['filepath'], tmp_file_path)
self.asset = File.new(tmp_file_path)
end
end
private
# clean tmp directory used in handling new param
def clean_tmp_upload_dir
FileUtils.rm_r(tmp_upload_dir) if self.tmp_upload_dir && File.directory? (self.tmp_upload_dir)
end
nginx.conf
upload_pass #fast_upload_endpoint;
upload_store /pathto/shared/uploads_tmp 1;
upload_store_access user:rw group:rw all:r;
upload_set_form_field upload[fast_asset][original_name] "$upload_file_name";
upload_set_form_field upload[fast_asset][content_type] "$upload_content_type";
upload_set_form_field upload[fast_asset][filepath] "$upload_tmp_path";
upload_pass_form_field "^image_id$|^authenticity_token$|^format$";
upload_cleanup 400 404 499 500-505;
}
location #fast_upload_endpoint {
passenger_enabled on;
rails_env production;
}
location / {
rails_env production;
passenger_enabled on;
}
In the controller my create method
def create
#image = current_user.images.build(params[:image])
if #image.save
Basically I'm not sure how to get this create method to use nginx to upload. I tried to use #image = #resource.current_user.images.build(params[:image]) but that was giving me an undefined method error.
What you should check is what parameters nginx passes when creating the upload. I have the same logic like you do. The create action i've got is as follows. Bear with me because i'm not able to test the parameters nginx passes now. But I think it's not "image" but "upload"
#photo = #artist.photos.build(params[:upload])
Is my create method.