Rails deployment made easy with Inploy

Inploy, Ruby on Rails, plugin, rails — Tags: , , , , — dc.rec1 @ 7:41 pm

After working in some systems made in Rails, Capistrano became one of the things that began to bother me more and more. I tried to find other alternatives, including Vlad, but none satisfied me, so I decided to create a solution and called it Inploy.

Before Capistrano fans crucify me, I wanted to let it clear that I don’t think Capistrano is a bad tool, just that it’s bad for my needs, which are much simpler than Capistrano can attend.

One of the things I don’t like about Capistrano is that it creates a lot of folders, one for each release. Some people argued with me that they are useful when you want to rollback a release, but that never happened to me, as never happened with most of the people I talked with. The rest of the people told me that in some circumstance they had to rollback a deploy, but the circumstance was that the deployed code broke the build.

Inploy uses Git, so in case we need to rollback our deploy to a version, we can use git reset. Of course this solution is more limited that the one that Capistrano uses, but it’s a solution to a problem that probably should never occur, a problem caused probably by bad practices in the development.

As a consequence of Capistrano strategies, they deploys are a little slow for my taste. I know there are some configurations that can speed up the process, but to configure is a thing I don’t want to do. I want to use a tool that works the best way by default and in most cases, the best way to a fast deploy is the simplest one: git clone in the setup and git pull in the update, the same that Inploy does.

Speaking about defaults, it’s very annoying to me having to define in Capistrano how to restart the server, how to clean the cache and what tasks it should rake, like more:parse and asset:packager:build_all. Inploy tries to solve this problems by executing common tasks by default, being smart enough to identify what tasks it should rake and in which order. The idea behind the plugin is that you shouldn’t worry about how to deploy that new tool you’re using, that things just work without the possibility of something going wrong.

Another advantage from Inploy over Capistrano for most cases is that it just have one way to deploy and its called update. This task updates the code, migrates the database, does some other tasks and restarts the server. It makes not sense to me to update the code without running migrations. In all teams I worked with, everyone could deploy the application and in most cases someone executed cap deploy instead of cap deploy:migrations. I know this is a human error but I prefer to use a tool that doesn’t let people make mistakes.

A need I had with deployment tools is that it could work both remotely and locally. I worked in a project that was delivered to a foreign client and the people responsible of updating the application in each release couldn’t do it otherwise that by connecting to a server and running a script. All of them used Windows and were used to work with Java systems that required them to access a machine, replace a war file and execute some commands. In that opportunity, the solution was to create a deploy.sh file in the root folder on the application. This file was executed by somebody from the client every time they needed to update the application.

The problem mentioned above doesn’t happen with Inploy, as it can be run both remotely or locally. When running remotely, the only only thing it does is to connect to a list of servers and run the tasks like being locally logged. It’s because of this that Inploy is delivered as a plugin, so it’s available in all environments.

As today, Inploy will only work for you if you’re working with Git and Passenger.

To install Inploy you can execute:

script/plugin install git://github.com/dcrec1/inploy.git

On installation, Inploy will write to a file in config/deploy.rb. This file is read by the plugin and it should be something like this:

deploy.application = "inploy"
deploy.repository = 'git://github.com/dcrec1/inploy.git'
deploy.user = 'dcrec1'
deploy.hosts = ['hooters', 'geni']
deploy.path = '/var/local/apps'

After that, we’re ready to execute the tasks that the plugin has:

rake inploy:local:setup
rake inploy:local:update
rake inploy:remote:setup
rake inploy:remote:update

I created a short video in which I demonstrate how to use the different tasks of the plugin. In the video I’m inside the Signal project, which already has Inploy installed and I remove it along with the configuration file to demonstrate how easily it is to install and configure it. After that I execute a remote setup and then a remote update. We can see in the video that the commands that Inploy runs are logged with the corresponding outputs and that config/*.sample files are renamed to config/*, another feature of Inploy. In the second part of the video a local update is ran and then deleted the repository, cloned and executed another setup, this time locally.

Deploy easily to Locaweb with Inploy from Diego Carrion on Vimeo.

More details about the plugin can be obtained in the official Inploy repository, where I’ll try to keep the README up-to-date. I hope it’s clear the way that Inploy works, but just in case, looking at the code is an option to eliminate doubts. The code is quite small (50 LoC moreless) and also self explanatory. Follows an snippet:

def local_setup
  copy_sample_files
  create_folders 'tmp/pids', 'db'
  run "./init.sh" if File.exists?("init.sh")
  after_update_code
end
 
def remote_update
  remote_run "cd #{application_path} && rake inploy:local:update"
end
 
def local_update
  run "git pull origin master"
  after_update_code
end
 
def after_update_code
  install_gems
  migrate_database
  run "rm -R -f public/cache"
  rake_if_included "more:parse"
  rake_if_included "asset:packager:build_all"
  run "touch tmp/restart.txt"
end

I wish this simple code motivates people to contribute with the project and make it smarter.

If this plugins helps you, please consider to recommend me at Working With Rails.

48 Comments »

  1. Looks really promising, thanks for writing it. I’ll give it a spin :-)

    ~Marcello

    Comment by Marcello Barnaba — October 20, 2009 @ 4:40 am
  2. [...] Rails deployment made easy with Inploy – A simple alternative to Capistrano if you’re using Passenger and Git and don’t need anything fancy at deployment time. Possibly related posts: (automatically generated)My Snow Leopard casualties: what’s not working in 10.6 A Fresh Cup is Mike Gunderloy’s software development weblog, covering Ruby on Rails and whatever else I find interesting in the universe of software. I’m a full-time Rails developer and contributor, available for long- or short-term consulting, with solid experience in working as part of a distributed team. If you’d like to hire me, drop me a line. I’m also the author of Rails Rescue Handbook and Rails Freelancing Handbook. Links [...]

    Pingback by Double Shot #565 « A Fresh Cup — October 20, 2009 @ 5:35 am
  3. [...] 2:37 pm on October 20, 2009 Reply Tags: deployments (3), rails (72), tutorials (8) http://www.diegocarrion.com/2009/10/19/rails-deployment-made-easy-with-inploy/ – Rails deployment made easy with Inploy [...]

  4. Any plans to make this into a gem?

    Comment by Bob — October 20, 2009 @ 11:59 am
  5. @bob

    I’ll make it a gem as soon as possible, maybe today. It didn’t happen yet because I didn’t know if somebody wanted this, but thanks for the feedback :)

    Comment by dc.rec1 — October 20, 2009 @ 12:25 pm
  6. Congratulations man,

    This is a very nice work! Good job and tk’s to share it if the Ruby community.

    Take care

    Comment by Marcio Trindade — October 20, 2009 @ 1:44 pm
  7. Just watched the GitHub repo! Awesome work, looking forward to playing around with this.

    Comment by Bob — October 20, 2009 @ 3:38 pm
  8. [...] Rails deployment made easy with Inploy | Diego Carrion (tags: ruby rails sysadmin) Possibly related posts: (automatically generated)links for 2006-11-23links for 2009-01-13links for 2008-04-11HowTo: RESTful Autocomplete Categories: Links Comments (0) Trackbacks (0) Leave a comment Trackback [...]

    Pingback by links for 2009-10-20 « Bloggitation — October 21, 2009 @ 1:07 am
  9. [...] Rails deployment made easy with Inploy [...]

  10. This seems to be exactly what I’ve been looking for. Nicely done. I’ll get the gem when it’s ready.

    Comment by Teddy — October 21, 2009 @ 1:39 am
  11. Hi Teddy, the gem is avaliable already in gemcutter:

    http://gemcutter.org/gems/inploy

    Used as a gem, as for now, you will need to load the tasks something like this:

    require ‘inploy’
    load ‘tasks/inploy.rake’

    And dont forget to create the config/deploy.rb file.

    Any feedback is welcome :)

    Comment by Diego Carrion — October 21, 2009 @ 9:24 am
  12. Thank you Diego, this is exactly what I have been looking for for a simple deployment system.

    Thank you.

    Comment by Bob — October 21, 2009 @ 11:01 pm
  13. This looks awesome! One question, though, as I’m still a bit of a Git/Rails newb. What’s the common way to handle a database.yml file and deployment?

    Comment by Brandon Weiss — October 22, 2009 @ 1:14 pm
  14. First of all, I love the tag line of your blog… we share common interests.

    Secondly, fine work. Just used this to deploy an app. Simple. Fast. Loverly.

    Thanks for sharing.

    Comment by Timmy — October 22, 2009 @ 1:25 pm
  15. @brandon

    I worked in some projects where everybody shared the same database.yml, so it was normally versioned as other files. In this cases, the development environment uses sqlite as a database, so the user and password was not a problem.

    In some other projects where the development database needed to be MySQL, like when working with Sphinx, the database.yml was ignored by Git an instead a database.yml.sample was versioned. The reason for this is that each people had a diferente combination of user/password for the MySQL database, so the database.yml could not be shared.

    Inploy copies config/database.yml.sample to config/database.yml if the second file do not exists, so if you decided to use a config/database.yml.sample file, I recommend you to configure it for the staging and production environment. This way, when Inploy copies the file, the configuration will be ok and migration will run without problems.

    Thanks everybody for the feedback.

    Comment by Diego Carrion — October 22, 2009 @ 1:48 pm
  16. Interesting. So, I guess that means if I’m using MySQL, the first time I deploy the app I need to manually upload the database.yml file? Because if it’s a public repository on GitHub, I obviously can’t track the db config file. So after I rake inploy:remote:setup, upload the database.yml file, I can just rake inploy:remote:update and everything should be cool?

    Comment by Brandon Weiss — October 22, 2009 @ 2:19 pm
  17. Yes, exactly that. As on setup the migrations will be executed, maybe it’s a good idea to configure database.yml.sample to use sqlite by default, so the process will not thrown an error and later will be easy to delete this database.

    Comment by Diego Carrion — October 22, 2009 @ 2:38 pm
  18. Ah, I see. Yes, that makes sense. Thanks! I really wasn’t looking forward to having to learn to use Capistrano for something that really shouldn’t be all that complicated, but looks like now I won’t have to :)

    Comment by Brandon Weiss — October 22, 2009 @ 3:48 pm
  19. You’re welcome Brandon. On any problem please contact me.

    Thanks for the support.

    Comment by Diego Carrion — October 22, 2009 @ 3:58 pm
  20. I took almost identical approach with my “git-deploy” strategy. Check it out, I’m already deploying several different-scale sites with it: http://github.com/mislav/git-deploy

    However I still use Capistrano for the setup task. I like its ability to execute tasks remotely via a nice DSL.

    Comment by Mislav — October 22, 2009 @ 7:50 pm
  21. @mislav

    I just checked it out, very cool. I think it’s another great option to deployment. Will take a time to analyze the code, maybe I can borrow something :)

    Comment by Diego Carrion — October 22, 2009 @ 8:05 pm
  22. [...] Rails deployment made easy with Inploy | Diego Carrion (tags: rails deployment) [...]

    Pingback by links for 2009-10-23 « Amy G. Dala — October 23, 2009 @ 9:05 am
  23. [...] Rails deployment made easy with Inploy | Diego Carrion – October 30th ( tags: rails deployment inploy rubyonrails capistrano ruby deploy git ) [...]

  24. [...] Rails deployment made easy with Inploy | Diego Carrion [...]

  25. I think you’re right on track. Good job. I’m gonna shelve Capistrano for a while.

    Comment by David Beckwith — November 2, 2009 @ 3:42 am
  26. [...] Rails deployment made easy with Inploy (12) [...]

    Pingback by git top links: 2009-11 « git blog — November 8, 2009 @ 7:40 am
  27. I would like to deploy my staging server first. If everything looks ok I want to proceed and deploy to the production server. Is that possible with Inploy?

    Comment by Erik — November 8, 2009 @ 4:15 pm
  28. @Erik

    If you’re using the production environment in your staging server this is actually possible, If not, there is somebody working on making the environment configurable, I think this will available tomorrow.

    Comment by Diego Carrion — November 8, 2009 @ 9:13 pm
  29. I can use the production environment on the staging server, no problem. But how do I specify which server to deploy to when running inploy:local:update ? I don’t want to deploy to production server until the application is tested ok on staging server…

    Comment by Erik — November 9, 2009 @ 2:08 am
  30. Is there a mailing list/forum for Inploy?

    For me the gem version isn’t working.

    rake inploy:remote:setup
    Don’t know how to build task ‘inploy:remote:setup’.

    I’m on REE 1.8.7 and Rails 2.3.4 on Snow Leopard.

    The plugin version works but when running inploy:remote:setup it stops after

    checkout -f -b master origin/master
    fatal: git checkout: branch master already exists

    So submodules are never initiated and updated and inploy:local:setup never runs.

    Comment by Erik — November 9, 2009 @ 2:53 am
  31. @Erik

    this is the group:

    http://groups.google.com/group/inploy_

    The problem when using Inploy as a gem is that it needs to be installed in both computers, as it runs the commands as being locally.

    About the environments, you can set your deploy.rb file like this:

    http://gist.github.com/229936

    and then call the Rake file like this:

    rake inploy:remote:update env=’staging’
    rake inploy:remote:update env=’production’

    Comment by Diego Carrion — November 9, 2009 @ 8:23 am
  32. Thanks for the tip about the environments. Exactly what I was looking for. About the gem problem I’ll create a topic on the google group.

    Comment by Erik — November 9, 2009 @ 8:35 am
  33. Thanks Erik, great feedback (:

    Comment by dc.rec1 — November 9, 2009 @ 8:51 am
  34. Hi, very good plugin but I have a problem when it works with ports

    my deploy.rb:

    deploy.template = :locaweb
    deploy.application = “demo”
    deploy.user = ‘demouser’
    deploy.hosts = ['servergeek.com']
    deploy.path = ‘/home/apps’
    deploy.ssh_opts = ‘-p 3987′

    I get

    Inploy => git push ssh://[demouser@servergeek.com]/home/apps/demo master

    So it is wrong!! it must be:
    Inploy => git push ssh://[demouser@servergeek.com:3987]/home/apps/demo master

    the parameter deploy.ssh_opts = ‘-p 3987′ works in Inploy => ssh -p 3987 demouser@servergeek.com ok

    it is a bug.

    so i set:
    deploy.hosts = ['servergeek.com:3987']
    i get
    Inploy => ssh -p 3987 railsapps@avizormedia.com:3987 wrong

    Solve?

    Dennis

    Comment by Dennis — February 10, 2010 @ 2:26 pm
  35. Hi Dennis, this doesn’t resolve? :

    deploy.template = :locaweb
    deploy.application = “demo”
    deploy.user = ‘demouser’
    deploy.hosts = ['servergeek.com:3987']
    deploy.path = ‘/home/apps’

    Im just set the port without setting the ssh option.

    Comment by dc.rec1 — February 10, 2010 @ 3:38 pm
  36. Hi dc.rec1
    How I said.
    deploy.hosts = ['servergeek.com:3987']
    i get
    Inploy => ssh railsapps@servergeek:3987 this line is wrong
    Inploy => git push ssh://[demouser@servergeek.com:3987]/home/apps/demo master this line is ok

    IF I set:
    deploy.hosts = ['servergeek.com']
    deploy.ssh_opts = ‘-p 3987′
    i get:
    Inploy => ssh -p 3987 railsapps@servergeek this line is ok
    Inploy => git push ssh://[demouser@servergeek.com]/home/apps/demo master this line is wrong

    AND If I set:
    deploy.hosts = ['servergeek.com:3987']
    deploy.ssh_opts = ‘-p 3987′
    i get:
    Inploy => ssh -p 3987 railsapps@servergeek:3987 this line is wrong
    Inploy => git push ssh://[demouser@servergeek.com:3987]/home/apps/demo master this line is ok

    my server is setup with port 3987

    Dennis

    Comment by Dennis — February 10, 2010 @ 4:01 pm
  37. Oh I get it, I thought this was ok:

    ssh railsapps@servergeek:3987

    I will try to implement this functionality. I can also accept a patch if you want :)

    Thanks for the feedback.

    Comment by dc.rec1 — February 10, 2010 @ 4:11 pm
  38. the correct syntax must be:

    Inploy => ssh -p 3987 railsapps@servergeek.com
    Inploy => git push ssh://[demouser@servergeek.com:3987]/home/apps/demo master

    Fix it please :D so I cann’t use the plugin :(

    advice me to try again :D

    Dennis

    Comment by Dennis — February 10, 2010 @ 4:15 pm
  39. Hi Dc.

    I try the plugin again. it’s works very good, very easy.

    but now I see this line:

    Inploy => ssh -p 3987 -p 3987 demouser@servergeek.com ‘cd /home/rails/example && git checkout -f && rake inploy:local:update environment=production’
    with this setup:
    deploy.template = :locaweb
    deploy.application = “example”
    deploy.user = ‘demouser’
    deploy.hosts = ['servergeek.com']
    deploy.path = ‘/home/rails’
    deploy.port = “3987″
    # optional advanced settings
    deploy.ssh_opts = ‘-p 3568′
    #deploy.branch = ‘master’

    and works. only i dont like -p 9999 twice in ssh line

    if I set deploy.ssh_opts = ‘-p 3568′ its write ssh -p -p 3987 demouser@servergeek.com………
    if I comment #deploy.ssh_opts = ‘-p 3568′ it’s write ssh demouser@servergeek.com……… and the port????

    Dennis

    Comment by Dennis — February 15, 2010 @ 6:19 pm
  40. Sorry Dennis, bug fixed. You should not specify ssh_opts, only the port.

    Thanks for the feedback.

    Comment by Diego Carrion — February 17, 2010 @ 5:49 am
  41. Excelent work now! thanks.

    Dennis

    Comment by Dennis — February 17, 2010 @ 11:27 am
  42. Do you have plans to support other version control systems?

    Comment by Jess — April 20, 2010 @ 8:35 pm
  43. Hi Jess, I can implement support for other version control system if you need it. Im trying to keep Inploy as simple as needed, adding functionalities only when there is a demand.

    Comment by Diego Carrion — April 21, 2010 @ 8:56 am
  44. This is really good, but one of the things I really hate about Capistrano is that it doesn’t let you specify different user/pwd for every environment, for instance, I don’t know why but in the company I’m working for right now there is 1 server for each environment, so development and production have different IP and different user/pwd pairs, as far as I understand Inploy doesn’t let you specify different user/pwd either, am I wrong?

    Comment by raf — November 9, 2010 @ 3:17 pm
  45. Hi Raf,

    Inploy’s config file is pure Ruby, so you can do things like this:

    if ENV['RAILS_ENV'] = ‘production’
    user = ‘batman’
    password = ‘robin’
    else
    user = ‘lorem’
    password = ‘ipsum’
    end

    Hope that helps.

    Comment by Diego Carrion — November 9, 2010 @ 4:22 pm
  46. ooh, that’s nice!! it works!

    thanks!

    Comment by raf — November 9, 2010 @ 7:00 pm
  47. Thank you for the fantastic piece of information. Gives a great insight. Thanks Gautam T Goudar, Irving, TX f

    Comment by nj pest control — August 6, 2011 @ 6:57 pm
  48. very good post, i certainly love this website, keep on it

    Comment by attorney lancaster pa — October 20, 2011 @ 12:08 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.
(c) 2013 Diego Carrion | powered by WordPress with Barecity