Adding foreman on passenger - ruby-on-rails

So far I had a simple application that only required the classic rails server to boot.
I have recently added the react_on_rails gem and it requires to boot a nodejs server to handle webpack and javascript stuff.
So I understand I need this foreman gem that is capable of managing several processes. So far so good, but then I'm still having a few problems understanding and deploying this enhanced app to my production environment (Phusion Passenger on Apache/Nginx)
So several questions :
Does passenger handle the transition from rails s to foreman start -f Procfile.dev automatically ?
If no then where do I setup things so passenger works ?
Side question : almost all google results refer to puppet when looking for foreman on passenger. Anyone could explain what puppet does in 1 line and if I really need it in production ? So far everythings runs smoothly on localhost with the foreman start -f Procfile.dev command so I don't know where this is coming from...
I am deploying my application to the Amazon Cloud using Capistrano, and I was expecting to have the rails + nodejs setup on every autoscaled instance (and Passenger would graciously handle all that). Am I thinking wrong ?

In our production environment we use eye to manage other processes related to the rails app. (Passenger will run from mod_passenger while the workers are controlled by eye)
And here is an example of how to start 4 concurrent queue_classic workers:
APP_ROOT = File.expand_path(File.dirname(__FILE__))
APP_NAME = File.basename(APP_ROOT)
Eye.config do
logger File.join(APP_ROOT, "log/eye.log")
end
Eye.application APP_NAME do
working_dir File.expand_path(File.dirname(__FILE__))
stdall 'log/trash.log' # stdout,err logs for processes by default
env 'RAILS_ENV' => 'production' # global env for each processes
trigger :flapping, times: 10, within: 1.minute, retry_in: 10.minutes
group 'qc' do
1.upto(4) do |i|
process "worker-#{i}" do
stdall "log/worker-#{i}.log"
pid_file "tmp/pids/worker-#{i}.pid"
start_command 'bin/rake qc:work'
daemonize true
stop_on_delete true
end
end
end
end

Related

Rails - Passenger and Nginx preventing rufus-scheduler from scheduling in production mode

I am using Rufus Scheduler to call a function once every 2 minutes.
In development mode when running rufus scheduler with WEBrick the system works as expected and my function is called every 2 minutes.
When I deploy to our production server which runs passenger and NGINX the scheduler does not call the function anymore.
I am assuming this is to do with threads, with the scheduler running on a separate thread that might be getting destroyed on our production server.
I have seen answers for similar issues when using Passenger and Apache together, but I am unable to come up with a solution for running rufus scheduler with passenger and NGINX in production mode.
Any help would be appreciated.
Code below setting up rufus
# :nocov:
require 'rufus-scheduler'
include TwitterParser
unless ENV['NODAEMON'] || Rails.env != 'production'
scheduler = Rufus::Scheduler.new
TwitterParser.set_up
scheduler.every '2m' do
begin
TwitterParser.parse_tweets
rescue Twitter::Error::TooManyRequests => error
puts 'Too Many Twitter requests, resets in: ' + error.rate_limit.reset_in.to_s
end
end
end
# :nocov:
Please read the rufus-scheduler FAQ.
https://github.com/jmettraux/rufus-scheduler#faq
It contains links to (old) articles about Passenger + rufus-scheduler
Amog them, this SO answer by one of the authors of Passenger might help:
rufus cron job not working in Apache/Passenger
Have a good time.

Detect if application was started as HTTP server or not (rake task, rconsole etc)

I'm using EventMachine and Monetarily to start e TCP server along with my rails application. This is started from config/initializers/momentarily.rb.
My problem is that it starts also when I run rake tasks, like db:migrate. I only want it to start when when I start the HTTP server. Environments won't help, since both the server start and rake tasks are under Development environment. Is there a way of knowing that the application is running the HTTP server as opposed to anything else? Note that is not only rake tasks, the EM starts also if I run the rails console, which is again something not desirable for my case.
unless File.basename($0) == "rake" && ARGV.include?("db:migrate")
# you are not in rake db:migrate
end
There's not a great way of doing this that I know of. You could copy newrelic's approach (check discover_dispatcher in local_environment.rb) which basically has a list of heuristics used to detect if it is running inside passenger, thin, etc.
For passenger it checks
defined?(::PhusionPassenger)
for thin it checks
if defined?(::Thin) && defined?(::Thin::Server)
Set an environment variable in config.ru file, and use it anywhere in the code to detect if it's executed using a rails server command only.
For e.g.
File: config.ru
ENV['server_mode'] = '1'
And using it somewhere as:
File: config/environment.rb
Thread.new { infinite_loop! }.join if ENV['server_mode'] = '1'
Reference: Answer
Maybe you can implement a switch in the initializer based on ARGV?
Something like:
if ARGV.join(' ').match /something/
# your initializer code here
end
Don't start that other server from an initializer. Create a daemon in script/momentarily and start it from within your app.
After your application launches, you could have it shell out to check ps. If ps shows that the HTTP server is running and the running HTTP server has the same pid as your application (check the pid by inspecting $$), then you could launch the TCP server.
In addition to a great answer by Frederick Cheung above, there can be some other "footprints" in actual process environment. Eg. Phusion Passenger adds certain variables to ENV such as:
PASSENGER_APP_ENV
IN_PASSENGER
PASSENGER_SPAWN_WORK_DIR
PASSENGER_USE_FEEDBACK_FD
Web servers typically can also set SERVER_SOFTWARE variable eg.:
SERVER_SOFTWARE=nginx/1.15.8 Phusion_Passenger/6.0.2

Unicorn doesn't play nice with Capistrano deployment?

I am having issues when using unicorn with a Capistrano deployment. From what I have been able to understand Capistrano uses a scheme in wich every release is deployed inside the releases directory under a unique name and if the transaction was successful, creates a symlink named current that will point to that release.
So I end up with a deployment directory such as:
/home/deployer/apps/sample_app/current
Then when I try to start unicorn from the binstubs directory all the unicorn methods look for things in the following path, particularly in the configurator.rb module:
/home/deployer/apps/sample_app
I haven't been able to fully understand how unicorn sets the working_directory from here:
https://github.com/defunkt/unicorn/raw/master/lib/unicorn/configurator.rb
But I wanted to check with the community if I am missing something evident due to the noob nature in me.
BTW I am starting unicorn as follows
APP_ROOT=/home/deployer/apps/sample_app/current
PID=$APP_ROOT/tmp/pids/unicorn.pid
CMD="$APP_ROOT/bin/unicorn -D -E production -c $APP_ROOT/config/unicorn.rb"
TIA
this was setup via unicorn.rb config working_directory param

Can I automatically start a daemon in a Rails 2.3.11 application?

In the development environment i use the following command to start a daemon after starting the server:
RAILS_ENV=development lib/daemons/mailer_ctl start
In the production environment, from the application directory, i would use:
lib/daemons/mailer_ctl start
Can i change the development.rb and production.rb files so the daemon would automatically be started? If not, is there another way to do this?
I recommend on your production server you use god (or something similar) to watch for the existing of a process, and start it if it does not exist
http://god.rubyforge.org/
Monit is an alternative -- here's a good SO question on monit vs god

How can I keep a Passenger Standalone up even after a restart?

I have a few apps running rails 3 on ruby 1.9.2 and deployed on a Ubuntu 10.04 LTS machine using nginx + passenger. Now, I need to add a new app that runs on ruby 1.8.7 (REE) and Rails 2. I accomplished to do that with RVM, Passenger Standalone and a reverse proxy.
The problem is that, every time I have to restart the server (to install security updates for example), I have to start Passenger Standalone manually.
Is there a way to start it automatically? I was told to use Monit or God, but I couldn't be able to write a proper recipe that works with Passenger Standalone. I also had a few problems with God and RVM, so if you have a solution that doesn't use God, or if you know how to configure God/Rvm properly, it's even better.
Here is what I got working. Using Upstart (Ubuntu 10.04) to start the passenger daemon
My environment uses rvm with ruby 1.9.2 and apache and my rails app is deployed via capistrano
# Upstart: /etc/init/service_name.conf
description "start passenger stand-alone"
author "Me <me#myself.am>"
# Stanzas
#
# Stanzas control when and how a process is started and stopped
# See a list of stanzas here: http://upstart.ubuntu.com/wiki/Stanzas#respawn
# When to start the service
start on started mysql
# When to stop the service
stop on runlevel [016]
# Automatically restart process if crashed
respawn
# Essentially lets upstart know the process will detach itself to the background
expect fork
# Run before process
pre-start script
end script
# Start the process
script
cd /var/path/to/app/staging/current
sh HOME=/home/deploy /usr/local/rvm/gems/ruby-1.9.2-p136#appname/gems/passenger-3.0.7/bin/passenger start --user 'deploy' -p '5000' -a '127.0.0.1' -e 'production'
end script
and the apache config:
<VirtualHost *:80>
ServerName myapp.com
PassengerEnabled off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
</VirtualHost>
Upstart doesn't set ENV['HOME'] which passenger relies on, so we have to pass that when executing the passenger command. Other than that its pretty straight forward.
A note for debugging: https://serverfault.com/questions/114052/logging-a-daemons-output-with-upstart (append something like >> /tmp/upstart.log 2>&1 to the second line in the script block)
Hope this helps.
I would suggest writing a shell script that can start this successfully, then use that in either a Monit or God recipe, if you're still willing to use them, or an init script if not.
You don't mention what OS your server runs, but if it's a recent Ubuntu, you can write an Upstart script pretty easily. It's built-in, and has the important feature of Monit/God - keeping your daemon running, even through restarts.
I use gem eye - https://github.com/kostya/eye
BUNDLE = 'bundle'
RAILS_ENV = 'production'
ROOT = File.expand_path(File.dirname(__FILE__))
Eye.config do
logger "#{ROOT}/log/eye.log"
end
Eye.application :app do
env 'RAILS_ENV' => RAILS_ENV
working_dir ROOT
trigger :flapping, :times => 10, :within => 1.minute
process :passenger do
daemonize true
pid_file "tmp/pids/passenger.pid"
start_command "#{BUNDLE} exec passenger start --port 3000 --environment #{RAILS_ENV}"
stop_signals [:TERM, 5.seconds, :KILL]
restart_command "kill -USR2 {PID}"
restart_grace 10.seconds
check :cpu, :every => 30, :below => 80, :times => 3
check :memory, :every => 30, :below => 70.megabytes, :times => [3,5]
end
process :delayed_job do
pid_file "tmp/pids/delayed_job.pid"
stdall "log/delayed_job.log"
daemonize true
stop_signals [:INT, 30.seconds, :TERM, 10.seconds, :KILL]
restart_grace 10.seconds
start_command "#{BUNDLE} exec rake jobs:work"
end
end
Depending on your platform, you will almost certainly have some variant of init available. On debian, this is init.d. On ubuntu, init.d or upstart. on a RHEL-like, service. These will allow you to manage services on startup. I suggest reading the appropriate man page for your platform.

Resources