Rails deployment made easy with Inploy
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.


Looks really promising, thanks for writing it. I’ll give it a spin
~Marcello
[...] 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 [...]
[...] 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 [...]
Any plans to make this into a gem?
@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
Congratulations man,
This is a very nice work! Good job and tk’s to share it if the Ruby community.
Take care
Just watched the GitHub repo! Awesome work, looking forward to playing around with this.
[...] 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 [...]
[...] Rails deployment made easy with Inploy [...]
This seems to be exactly what I’ve been looking for. Nicely done. I’ll get the gem when it’s ready.
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
Thank you Diego, this is exactly what I have been looking for for a simple deployment system.
Thank you.
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?
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.
@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.
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?
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.
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
You’re welcome Brandon. On any problem please contact me.
Thanks for the support.
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.
@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
[...] Rails deployment made easy with Inploy | Diego Carrion (tags: rails deployment) [...]
[...] Rails deployment made easy with Inploy | Diego Carrion – October 30th ( tags: rails deployment inploy rubyonrails capistrano ruby deploy git ) [...]
[...] Rails deployment made easy with Inploy | Diego Carrion [...]
I think you’re right on track. Good job. I’m gonna shelve Capistrano for a while.
[...] Rails deployment made easy with Inploy (12) [...]
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?
@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.
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…
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.
@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’
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.
Thanks Erik, great feedback (:
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
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.
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
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.
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
so I cann’t use the plugin
advice me to try again
Dennis
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
Sorry Dennis, bug fixed. You should not specify ssh_opts, only the port.
Thanks for the feedback.
Excelent work now! thanks.
Dennis
Do you have plans to support other version control systems?
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.
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?
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.
ooh, that’s nice!! it works!
thanks!
Thank you for the fantastic piece of information. Gives a great insight. Thanks Gautam T Goudar, Irving, TX f
very good post, i certainly love this website, keep on it