Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example of a Foreman/Capistrano/upstart setup

Example of a Foreman/Capistrano/upstart setup

I need to jot down my Foreman-based web app setup real quick lest I forget.

When I build a Rails app (any web app, actually), it's not just the app itself anymore. There also are background jobs to be taken care of -- started, stopped, restarted. Usually these are required to run in production on a remote box, too, so I use Foreman to run those jobs. Foreman uses a Procfile to learn about said jobs, gives me a dead-simple way to start and stop them, and provides me with color-coded output when they run. It's a great timesaver.

Then, when I deploy my app to a remote machine, I use Foreman's ability to export upstart (or inittab) configurations. For that, I have custom tasks in my Capistrano-based config/deploy.rb file. Those halt the current jobs on the remote machine, trigger Foreman to write out new configurations for upstart and re-start the jobs. (Please note: Foreman needs to be installed on the remote box as well.)

Since it took me a while to get this setup working, I figured I'd share it real quick.

My examples come from a Rails-based environment, but I tried to make them app-agnostic as possible.

This here "article" is basically a bare-bone, stripped down version of Tim Riley's "Run Your Own Piece of Heroku with Foreman".

Assumptions

  • The Foreman gem is installed both on the local dev machine and the remote box
  • Deployment is done using Capistrano
  • The remote machine is running Ubuntu
  • The remote machine has upstart installed
### Foreman-related snippet of `config/deploy.rb` below.
### Rest of the file omitted!
namespace :foreman do
desc "Export the Procfile to Ubuntu's upstart scripts"
task :export, :roles => :app do
run "cd /var/my-ossum-app && sudo bundle exec foreman export upstart /etc/init -a my-ossum-app -u ossum-user -l /var/my-ossum-app/log"
end
desc "Start the application services"
task :start, :roles => :app do
sudo "start my-ossum-app"
end
desc "Stop the application services"
task :stop, :roles => :app do
sudo "stop my-ossum-app"
end
desc "Restart the application services"
task :restart, :roles => :app do
run "sudo start my-ossum-app || sudo restart my-ossum-app"
end
end
after "deploy:update", "foreman:export"
after "deploy:update", "foreman:restart"
worker: QUEUE=* bundle exec rake environment resque:work
scheduler: bundle exec rake environment resque:scheduler
@stationkeeping

This comment has been minimized.

Copy link

stationkeeping commented Feb 1, 2013

How are you able to use $ sudo bundle exec foreman? Did you install rbenv for the root user?

@heygambo

This comment has been minimized.

Copy link

heygambo commented Feb 20, 2013

You might want to try #{sudo} instead of sudo

@tinynumbers

This comment has been minimized.

Copy link

tinynumbers commented Aug 29, 2013

@thisisbrians

This comment has been minimized.

Copy link

thisisbrians commented Oct 10, 2013

rvmsudo worked for me: https://rvm.io/integration/sudo

@sjchristi

This comment has been minimized.

Copy link

sjchristi commented Mar 27, 2014

ran into a similar issue, using rbenv. Ended up using a solution I found on the web in a railscast comments.

in deploy.rb:

def rbenv(command)
  run "#{command}", :pty => true do |ch, stream, data|
    if data =~ /\[sudo\].password.for/
      ch.send_data(Capistrano::CLI.password_prompt("sudo password: ") + "\n")
    else
      Capistrano::Configuration.default_io_proc.call(ch, stream, data)
    end
  end
end

then a slight change to the task above:

  desc "Export the Procfile to Ubuntu's upstart scripts"
  task :export, :roles => :app do
    rbenv "cd #{current_path} && rbenv sudo bundle exec foreman export upstart /etc/init --procfile=Procfile.production -a #{application} -u #{user} -l #{current_path}/log"
  end

thank you for the recipe.

sam

@jameskerr

This comment has been minimized.

Copy link

jameskerr commented Jul 3, 2014

Very useful. I am digging it. I believe I will borrow this set-up for my app. Tried using God to monitor workers, but didn't like it very much. Foreman + Upstart + Capistrano looks like a great combo.

@jobwat

This comment has been minimized.

Copy link

jobwat commented Jul 9, 2014

I'm using this solution and I was getting an error message at each restart:

*** [err :: staging.my-ossum-app.com] start: Job is already running: my-ossum-app

Which makes sense but damage the feedback (it should just be a warning)
So I'm now striping out from the error output this 'Job is already running' message, but it's ugly:

run "{ sudo start my-ossum-app 2>&1 1>&3 | grep -v 'Job is already running' 1>&2; } 3>&1 || sudo restart my-ossum-app"

If anyone have a better restart mechanism non-error-verbose, I'm keen :)

@cbilgili

This comment has been minimized.

Copy link

cbilgili commented Mar 18, 2015

More revised version for Capistrano >= v3.0

namespace :foreman do
  desc "Export the Procfile to Ubuntu's upstart scripts"
  task :export do
    on roles(:app) do
      within current_path do
        execute :rbenv, :exec, "bundle exec foreman export upstart /etc/init --procfile=./Procfile -a #{fetch(:application)} -u #{fetch(:user)} -l #{current_path}/log"
      end
    end

  end

  desc "Start the application services"
  task :start do
    on roles(:app) do
      within current_path do
        execute :rbenv, :exec, "foreman start #{fetch(:application)}"
      end
    end

  end

  desc "Stop the application services"
  task :stop do
    on roles(:app) do
      within current_path do
        execute :rbenv, :exec, "foreman stop #{fetch(:application)}"
      end
    end
  end

  desc "Restart the application services"
  task :restart do
    on roles(:app) do
      within current_path do
        execute :rbenv, :exec, "foreman start #{fetch(:application)} || foreman restart #{fetch(:application)}"
      end
    end
  end
end

after "deploy:publishing", "foreman:export"
after "deploy:publishing", "foreman:restart"
@candidosales

This comment has been minimized.

Copy link

candidosales commented Jun 4, 2016

Thanks!! 👍

@mihaibb

This comment has been minimized.

Copy link

mihaibb commented Jun 30, 2016

I'm looking to update this script so I can export the foreman configuration different on specific machines.
For example I want the worker service to be only exported on servers with role worker.
The same for web and db.
Any ideas ?

@GraniteConsultingReviews

This comment has been minimized.

Copy link

GraniteConsultingReviews commented Sep 7, 2017

I update my script but it is not working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.