Faye setup in production - ruby-on-rails

I've set up Faye on localhost, and works fine.
I'm now trying to deploy it on DigitalOcean VPS, with Cloud66 deployment service.
To run the command I use an "after_rails" hook.
rackup $RAILS_STACK_PATH/faye.ru -s thin -E production
This gives me the error:
Error during deployment: Error during after_rails hook: Server: not_specified. Failed to run command: /usr/local/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in require': cannot load such file -- faye (LoadError) from /usr/local/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:inrequire' from /var/deploy/anabol/web_head/current/faye.ru:1:in block in <main>' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/builder.rb:55:ininstance_eval' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/builder.rb:55:in initialize' from /var/deploy/anabol/web_head/current/faye.ru:innew' from /var/deploy/anabol/web_head/current/faye.ru:in <main>' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/builder.rb:49:ineval' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/builder.rb:49:in new_from_string' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/builder.rb:40:inparse_file' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:277:in build_app_and_options_from_config' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:199:inapp' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:314:in wrapped_app' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:250:instart' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/lib/rack/server.rb:141:in start' from /usr/local/lib/ruby/gems/1.9.1/gems/rack-1.5.2/bin/rackup:4:in' from /usr/local/bin/rackup:23:in load' from /usr/local/bin/rackup:23:in'
github repo:
https://github.com/gwuix2/anabol
Any suggestions what could be the problem? Don't know where to start.

I've written up some documentation on how to solve this problem in case anyone else runs into it. You can find it here: http://community.cloud66.com/articles/faye-on-cloud-66
Disclaimer: I work for Cloud 66.

Cloud 66 Support solved my problem:
Hi there,
We run faye on our own stack. We actually run it behind thin - and monitor it as a process on the stack. The way we do this is with four files - see their details below:
1) RAILS_ROOT/.cloud66/deploy_hooks.yml
production:
before_rails:
- source: /.cloud66/files/add_thin_and_faye.sh
destination: ~/add_thin_and_faye.sh
target: rails
execute: true
sudo: true
apply_during: build_only
run_on: all_servers
2) RAILS_ROOT/.cloud66/files/add_thin_and_faye.sh
#!/bin/bash
sudo gem install thin --no-ri --no-rdoc
sudo gem install faye --no-ri --no-rdoc
3) RAILS_ROOT/Procfile
faye: thin -R $RAILS_STACK_PATH/faye/config.ru start
4) RAILS_ROOT/faye/config.ru
require 'faye'
faye_server = Faye::RackAdapter.new(:mount => '/your_faye_mount', :timeout => 45)
Faye::WebSocket.load_adapter('thin')
faye_server.listen(<<PUT-YOUR-PORT-HERE>>)
Note that for part 4) the settings will be different based on your requirements of course.
If you follow the setup above, you'll have faye running alongside your stack, and it will be available as a process on your stack.

Related

Executing capistrano from a different application

I need to trigger a capistrano deployment from within an existing ruby scrpit.
For example, assume I want to start service that will listen to some messages, and on some messages I want to trigger a capistrano deployment of another app using cap staging deploy (which does work if I run this command directly from a shell).
~/app-to-deploy
- Gemfile #including many dependencies
- config/deploy # capistrano files
~/my-service
- Gemfile # including different dependencies than `app-to-deploy`
- my_script.rb # that wishes to call `cap app-to-deploy deploy`
I was thinking I could run the capistrano bash script from my service using something like
# my_service.rb
Dir.chdir(ENV['HOME'] + '/app-to-deploy') do
result = system('bash', '-c', "cap staging deploy")
end
If I run it with or without bundle exec this gives something like
cap aborted!
LoadError: cannot load such file -- active_support/all
/deploy/hermes/Capfile:2:in `require'
/deploy/hermes/Capfile:2:in `<top (required)>'
(See full trace by running task with --trace)
(I have ActiveSupport as a gem in my app-to-deploy but I don't have it in the Gemfile of my-service)
Seems like I have a lib dependency problem, but I'm not sure how to solve it...
Anyone has ideas or ways to go around the problem ? (or even better a way to call capistrano without using bash, assuming I may still have different dependencies ?)
(Note that app-to-deploy is an actual Rails app with many capistrano scripts that I don't want to touch if possible...)
The problem is that in unix systems environment is inherited. So when you call Capistrano from your rails app you don't have access to other gems. bash -c doesn't seem to clean env. You can with su -l probably.
One solution is to use
Bundler.with_clean_env do
Dir.chdir(ENV['HOME'] + '/app-to-deploy') do
result = system('bundle', 'exec', "cap", "staging", "deploy")
end
end
Just for reference: http://bundler.io/man/bundle-exec.1.html#Shelling-out

ActiveRecord::PendingMigrationError - migrating from one server to another

I'm new to Rails so please bear with me.
Currently there is an existing project (Rails 4.1.6, Ruby 2.1.3) running on digital ocean VM (Ubuntu 14.04) and its connecting to Postgresdb 9.6 without any issues. I have to migrate this to new VM.
I have setup a new vm with Ubuntu 16.04, installed Rails and Ruby with exact same versions. I tried creating a test rails app and its working fine. However, when I tried to deployed the project from old server to this new one its giving me errors.
Details:
There was an error while trying to load the gem 'uglifier'.
Gem Load Error is: Could not find a JavaScript runtime. See https://github.com/rails/execjs for a list of available runtimes.
Backtrace for gem load error is:
/usr/local/lib/ruby/gems/2.1.0/gems/execjs-2.7.0/lib/execjs /runtimes.rb:58:in `autodetect'
/usr/local/lib/ruby/gems/2.1.0/gems/execjs-2.7.0/lib/execjs.rb:5:in `<module:ExecJS>'
/usr/local/lib/ruby/gems/2.1.0/gems/execjs-2.7.0/lib/execjs.rb:4:in `<top (required)>'
/usr/local/lib/ruby/gems/2.1.0/gems/activesupport-4.1.6/lib /active_support/dependencies.rb:247:in `require'
/usr/local/lib/ruby/gems/2.1.0/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:247:in `block in require'
/usr/local/lib/ruby/gems/2.1.0/gems/activesupport-4.1.6/lib/active_support/dependencies.rb:232:in `load_dependency'
After searching on internet, most of them suggested to uncomment this line in the Gemfile.
# gem 'therubyracer', platforms: :ruby
This was commented in the old server, however, I tried uncommenting it and it came back with different error.
Migrations are pending. To resolve this issue, run: bin/rake db:migrate RAILS_ENV=development
Website was connecting to the same database and old webportal was running fine but it gave me this error. So I setup a new test db and ran the following commands -
RAILS_ENV=production bundle exec rake db:create
RAILS_ENV=production bundle exec rake db:setup
RAILS_ENV=production bundle exec rake db:migrate
All those commands were executed successfully but for some reason I'm still receiving "Migrations are pending....." error.
Please advise.
The migration-error seems to think you should be on the development environment... but the migrations you ran are for production... so either your environment-setting is not correct, or you need to run the migrations for development instead

Phusion Passenger not starting - flock': No locks available # rb_file_flock - /vagrant/tmp/pids/passenger.3000.pid.lock (Errno::ENOLCK)

This is a Rails app that runs on Phusion Passenger.
In development environment(passenger standalone mode) I run it in a Vagrant Ubuntu 14.04 based box in a MBP(at work) and a Linux Mint PC(home).
In gemfile: gem 'passenger'
Right now it is at passenger (5.0.25) according to my Gemfile.lock.
The command I normally use to start the rails server is passenger start which is in a Procfile.
rails: passenger start
sidekiq: bundle exec sidekiq
In my home PC, when I issue the command foreman start or passenger start I get:
/home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb:67:in `flock': No locks available # rb_file_flock - /vagrant/tmp/pids/passenger.3000.pid.lock (Errno::ENOLCK)
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb:67:in `block in exclusive_lock'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb:63:in `open'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller/lock_file.rb:63:in `exclusive_lock'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/vendor/daemon_controller.rb:219:in `start'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb:49:in `start_engine_real'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb:322:in `start_engine'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb:63:in `run'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/src/ruby_supportlib/phusion_passenger/standalone/main.rb:51:in `run!'
from /home/vagrant/ruby/lib/ruby/gems/2.1.0/gems/passenger-5.0.25/bin/passenger:45:in `<top (required)>'
from /home/vagrant/ruby/bin/passenger:23:in `load'
from /home/vagrant/ruby/bin/passenger:23:in `<main>'
When I use the command passenger-config restart-app I get:
*** ERROR: Phusion Passenger doesn't seem to be running. If you are sure that it
is running, then the causes of this problem could be one of:
1. You customized the instance registry directory using Apache's
PassengerInstanceRegistryDir option, Nginx's
passenger_instance_registry_dir option, or Phusion Passenger Standalone's
--instance-registry-dir command line argument. If so, please set the
environment variable PASSENGER_INSTANCE_REGISTRY_DIR to that directory
and run this command again.
2. The instance directory has been removed by an operating system background
service. Please set a different instance registry directory using Apache's
PassengerInstanceRegistryDir option, Nginx's passenger_instance_registry_dir
option, or Phusion Passenger Standalone's --instance-registry-dir command
line argument.
Env var PASSENGER_INSTANCE_REGISTRY_DIR is not set, so following passenger's documentation I try to set it doing:
export PASSENGER_INSTANCE_REGISTRY_DIR=/vagrant/tmp or export PASSENGER_INSTANCE_REGISTRY_DIR=tmp
And then
sudo -E passenger-status but with this one I get sudo: passenger-status: command not found
As per Hongli's answer in another thread with a similar situation, the command sudo env PASSENGER_INSTANCE_REGISTRY_DIR=/tmp passenger-status returns:
env: passenger-status: No such file or directory
Finally, in my rails app tmp folder there are the passenger pid files:
passenger.3000.pid
passenger.3000.pid.lock
I'm really clueless. There's no log and everything I've searched and found didn't solve this.
Thanks for helping!
Could you please try starting passenger in another port and check if the issue still exist.
passenger start -p 3001

Making rbenv's ruby as system ruby (Using rbenv's ruby when start up) on Ubuntu

I'm trying to start the rails app when Ubuntu starts up.
For this, I added these lines in /etc/rc.local.
cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
bundle exec passenger start --port 8000 --user ubuntu --daemonize
However, the rc.local exits with error
+ cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
+ bundle exec passenger start --port 8000 --user ubuntu --daemonize
/usr/lib/ruby/vendor_ruby/bundler/spec_set.rb:92:in `block in materialize': Could not find rake-10.4.2 in any of the sources (Bundler::GemNotFound)
from /usr/lib/ruby/vendor_ruby/bundler/spec_set.rb:85:in `map!'
from /usr/lib/ruby/vendor_ruby/bundler/spec_set.rb:85:in `materialize'
from /usr/lib/ruby/vendor_ruby/bundler/definition.rb:114:in `specs'
from /usr/lib/ruby/vendor_ruby/bundler/definition.rb:159:in `specs_for'
from /usr/lib/ruby/vendor_ruby/bundler/definition.rb:148:in `requested_specs'
from /usr/lib/ruby/vendor_ruby/bundler/environment.rb:18:in `requested_specs'
from /usr/lib/ruby/vendor_ruby/bundler/runtime.rb:13:in `setup'
from /usr/lib/ruby/vendor_ruby/bundler.rb:120:in `setup'
from /usr/lib/ruby/vendor_ruby/bundler/setup.rb:17:in `<top (required)>'
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
The error is caused from using the ruby installed from rbenv; the ruby is in /home/ubuntu/.rbenv/bin/ directory. I guess when ubuntu starts up, the system ruby is executed, but it does not know anything about installed packges with rbenv's ruby and gem.
How can I solve this issue? Is there any way to make the ruby from rbenv as system's ruby?
For getting the error, I used the hints from this post: Run script with rc.local: script works, but not at boot.
EDIT
mwp's answer works fine, but I think I'd better make things clearer.
development bundle
Run bundle --deployment --binstubs to create ./vendor and copy files in bundle directory.
The setup.sh
#!/bin/bash
export APP_ROOT="/home/ubuntu/webapp/rails/passenger-ruby-rails-demo"
export APP_USER="ubuntu"
export APP_PORT="8000"
export RBENV_ROOT="/home/ubuntu/.rbenv"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
# Assuming you installed bundle with --binstubs...
$APP_ROOT/bin/passenger start --port $APP_PORT --user $APP_USER --daemonize
The rc.local file
cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
sh ./setup.sh
exit 0
Run these commands one time:
cd /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
rbenv local <the version you want>
This will create a .ruby-version file in your application directory that tells rbenv which version to use.
I would also recommend that when you deploy the application to its "production" location, you install bundler with the --deployment --binstubs flags. This will install the Gems inside a vendor subdirectory (to insulate them from an errant Gem update) and create handy shortcuts inside a bin subdirectory to run e.g. passenger, rackup, etc. without needing to do bundle exec.
However, you have another problem, and that is that rbenv (the shell function) [probably] isn't available while rc.local is running. I would recommend creating a new shell script and stashing it somewhere, possibly within your application's directory structure, with (something like) the following contents:
#!/bin/bash
export APP_ROOT="/home/ubuntu/webapp/rails/passenger-ruby-rails-demo"
export APP_USER="ubuntu"
export APP_PORT="8000"
export RBENV_ROOT="/path/to/rbenv"
export PATH="$RBENV_ROOT/bin:$PATH"
eval "$(rbenv init -)"
# Assuming you installed bundle with --binstubs...
"$APP_ROOT"/bin/passenger start --port $APP_PORT --user $APP_USER --daemonize
Then mark this script executable and you can call it from rc.local to start the service. As far as what you set RBENV_ROOT to, you can either use an existing user's .rbenv directory (e.g. ~ubuntu/.rbenv, assuming you installed a copy there), or you can set up a system-wide rbenv at /opt/rbenv or elsewhere. There are some good notes here.
I can think of a million different ways to improve the above script, and indeed this is only one of a million different ways to tackle this problem. Starting and stopping services is quite a hot topic in the DevOps and SysAdmin communities right now. I've had great success running Ruby applications in production using rbenv and Bundler, and if you decide to go this route, I hope you will too!
Upstart (http://upstart.ubuntu.com) can be a better way to replace rc.local.
# simple script
# http://uwsgi-docs.readthedocs.org/en/latest/Upstart.html
description "passenger "
start on runlevel [2345]
stop on runlevel [06]
respawn
# http://stackoverflow.com/questions/14823972/upstart-node-js-working-directory
script
chdir /home/ubuntu/webapp/rails/passenger-ruby-rails-demo
exec sh runme.sh
end script

How can I use unicorn as "rails s"?

A new Rails project's Gemfile shows:
# Use unicorn as the app server
gem 'unicorn'
rails s --help shows:
Usage: rails server [mongrel, thin, etc] [options]
Yet, doing:
rails s unicorn
I get:
/Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/rack-1.4.5/lib/rack/handler.rb:63:in `require': cannot load such file -- rack/handler/unicorn (LoadError)
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/rack-1.4.5/lib/rack/handler.rb:63:in `try_require'
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/rack-1.4.5/lib/rack/handler.rb:16:in `get'
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/rack-1.4.5/lib/rack/server.rb:272:in `server'
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/railties-3.2.13/lib/rails/commands/server.rb:59:in `start'
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/railties-3.2.13/lib/rails/commands.rb:55:in `block in <top (required)>'
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/railties-3.2.13/lib/rails/commands.rb:50:in `tap'
from /Users/patrick/.rvm/gems/ruby-1.9.3-head#keynote/gems/railties-3.2.13/lib/rails/commands.rb:50:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
I've used unicorn in the past on other projects, but always had to run the unicorn command and specify a config file which is a bit of a pain. I am wondering how I can just simply make it work by using rails s...
Is this possible?
It looks like the unicorn-rails gem that #Dogbert mentioned can actually be used to make Unicorn the rails server handler.
Simply include gem "unicorn-rails" (and for Rails 4.2.4, gem "rack-handlers") in your Gemfile, run bundle install to install the gem, then you can run:
$ rails server unicorn
Although once unicorn-rails is installed, Unicorn should be the default app server so you could also just run rails server and it should use Unicorn (assuming you don't also have Thin or Mongrel in your Gemfile, in which case they may conflict and you might want to remove the ones you're not using).
A better option might just be to run the unicorn server directly.
bundle exec unicorn -p 3000 # default port is 8080
gem 'rack-handlers'
rails server unicorn
However the answer by Steven is the simplest way to do.
I run unicorn on development environment via a rake task:
lib/tasks/dev_unicorn.rake:
task :server do
# optional port parameter
port = ENV['PORT'] ? ENV['PORT'] : '3000'
puts 'start unicorn development'
# execute unicorn command specifically in development
# port at 3000 if unspecified
sh "cd #{Rails.root} && RAILS_ENV=development unicorn -p #{port}"
end
# an alias task
task :s => :server
run:
rake s
Reference http://jing.io
I don't think it is possible to use unicorn as 'rails s'. Use this -
Add gem 'unicorn' to gem file and run bundle install.
and then run any of the following commands -
$ unicorn -p 3000
or
$ unicorn_rails -p 3000

Resources