Wednesday, October 16, 2013

How to set up production mode in Rails 4 with Thin and Apache

I just completed a few days of research on the problem: how can Apache serve static assets while Thin runs Rails 4 application on the given port. Apache should create far-future expires headers on assets also. So, to do this, you need some

Apache modules:

a2enmod proxy_balancer
a2enmod proxy_http
a2enmod rewrite
a2enmod headers
a2enmod expires


My Apache virtualhost config:

<virtualhost>
    ServerName my_site.com
    ServerAlias *.my_site.com
    DocumentRoot /home/my_path/my_app/public

    RewriteEngine On

    <proxy balancer:="" thinservers="">
     BalancerMember http://127.0.0.1:5000
     </proxy>
   
    <location assets="">
        Header unset ETag
        FileETag None
        ExpiresActive On
        ExpiresDefault "access plus 1 year"
    </location>

    RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
    RewriteRule ^/(.*)$ balancer://thinservers%{REQUEST_URI} [P,QSA,L]

    # Custom log file locations
    ErrorLog  /home/my_path/my_app/log/error.log
    CustomLog /home/my_path/my_app/log/access.log combined

</virtualhost>


After then, restart your Apache service:

service apache2 restart

That was Apache configuration thanks to this post:
http://bibwild.wordpress.com/2012/11/20/apache-conf-for-rails-asset-pipeline



Setting up Thin


There is my thin configuration file in /etc/thin directory. Set environment to production my_site_name.yml:

chdir: /home/my_path/my_app
environment: production
address: 0.0.0.0
port: 5000
timeout: 30
log: log/thin.log
pid: tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
servers: 1
daemonize: true
onebyone: true
user: my_user_name
group: my_user_name
tag: my_site_name-publ


I made a script in application's bin/ directory, my_site_name:

#!/bin/sh
#

# Start the service
start() {
    thin start -C /etc/thin/my_site_name.yml
}

# Stop the service
stop() {
    thin stop -C /etc/thin/my_site_name.yml    
}

# Start the service
restart() {
    thin restart -C /etc/thin/my_site_name.yml
}

### main logic ###
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

exit 0


This is important for start / stop / restart your Rails 4 application easily. Set this file executable. Then just restart Thin like this, in you app's directory:

bin/my_site_name restart


Configuration for production mode

First install yui-compressor gem to minify CSS also.
After then, insert gem 'therubyracer' to production section into gemfile.
 


source 'https://rubygems.org'

gem 'rails', '4.0.0'
gem 'mysql2'
gem 'sass-rails', '~> 4.0.0'

gem 'uglifier', '>= 1.3.0'
gem 'yui-compressor','~> 0.12.0'
gem 'coffee-rails', '~> 4.0.0'
gem 'coffee-script-source', '1.5.0'
gem 'therubyracer', platforms: :ruby

gem 'jquery-rails'
gem 'turbolinks'
gem 'jquery-turbolinks'

gem 'jbuilder', '~> 1.2'

group :doc do
  # bundle exec rake doc:rails generates the API under doc/api.
  gem 'sdoc', require: false
end

gem 'execjs'
gem 'savon'
gem 'faye'
gem 'thin'

group :production do
  gem 'therubyracer'
end



And run 'sudo bundle install'

See config/environments/production file:

MySiteName::Application.configure do

  # Code is not reloaded between requests.
  config.cache_classes = true

  # Eager load code on boot. This eager loads most of Rails and
  # your application in memory, allowing both thread web servers
  # and those relying on copy on write to perform better.
  # Rake tasks automatically ignore this option for performance.
  config.eager_load = 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 = false
 
  # Compress JavaScripts and CSS.
  config.assets.js_compressor = :uglifier
  config.assets.css_compressor = :yui

  # Do not fallback to assets pipeline if a precompiled asset is missed.
  config.assets.compile = false

  # Generate digests for assets URLs.
  config.assets.digest = true

  # Version of your assets, change this if you want to expire all your assets.
  config.assets.version = '1.0'

  # Specifies the header that your server uses for sending files.
  config.action_dispatch.x_sendfile_header = nil  #"X-Sendfile" # for apache

   # Set to :debug to see everything in the log.
  config.log_level = :info

   # Precompile additional assets.
  # application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
  config.assets.precompile = ['*.js', '*.js.erb', '*.css', '*.css.erb', '*.js.coffee.erb']
  config.assets.precompile << %w(*.png *.jpg *.jpeg *.gif *.ico)
  config.assets.precompile += [ "images/icons/*" ]


  # Ignore bad email addresses and do not raise email delivery errors.
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
   config.action_mailer.raise_delivery_errors = false

  # 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

  # Disable automatic flushing of the log to improve performance.
   config.autoflush_log = false

  # Use default logging formatter so that PID and timestamp are not suppressed.
  config.log_formatter = ::Logger::Formatter.new
end


Don't forget to set config.action_dispatch.x_sendfile_header to nil and pay attention to precompile section. Add image subfolders and image extensions also.

 Now you have to compile assets to public/assets directory, but first empty cache and assets files:


rm -rf tmp/*
rm -rf public/assets/*
RAILS_ENV=production bundle exec rake assets:precompile

Don't forget to restart your Rails 4 application, but probably needs to kill thin process because assets files has been changed.

See this post also, it helped me a lot:
http://blog.55minutes.com/2012/02/untangling-the-rails-asset-pipeline-part-1-caches-and-compass/



And the result is a simple live mathematical practice site.

That's all, good luck!

2 comments:

  1. Hi would you mind sharing which blog platform you're working with?

    I'm planning to start my own blog in the near future but I'm having a tough time making a
    decision between BlogEngine/Wordpress/B2evolution and Drupal.
    The reason I ask is because your design seems different then most blogs and I'm looking for something completely unique.
    P.S Apologies for being off-topic but I had to ask!

    Feel free to visit my site :: Gadget News

    ReplyDelete
    Replies
    1. Hi,

      I use simple blogger.com for blogging, it has not an unique design, but you can modify it if you want. For Rails, you can find lots of blog engine gems here: https://www.ruby-toolbox.com/categories/Blog_Engines

      Attila

      Delete

Note: Only a member of this blog may post a comment.