# Playbook example for capistrano-type deployment

**URL:** <https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215>\
**Category:** Ansible Project\
**Created:** [January 19, 2013, 7:44am UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215 "2013-01-19T07:44:41Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Meng\_Kuan](https://avatars.discourse-cdn.com/v4/letter/m/ee59a6/32.png) [@Meng\_Kuan](https://forum.ansible.com/u/Meng_Kuan)\
**Post date:** [January 19, 2013, 7:44am UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/1 "2013-01-19T07:44:41Z")

</div>

Hi,

I’ve been experimenting with using ansible to configure brand new virtual machines (timezone, ssh keys, ruby, nginx, postgresql, etc) and so far so good. Not having to run puppet daemons is liberating. =)

Next I’m looking at how to use ansible to perform a series of tasks similar to what is being done by capistrano to deploy new rails code to those VMs. I’ve searched the newsgroup but I have not seen any mention of someone doing this. Before I go any further, has this been done already? If yes, any sample playbook I can take a look at?

Thanks in advance!

cheers,  
mengkuan

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [January 19, 2013, 1:50pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/2 "2013-01-19T13:50:19Z")

</div>

I'm unclear what automagic Capistrano is specifically doing in your  
case, can you give some examples?

Definitely you'd want to use the git module, there really isn't a  
'gem' module yet but you can use command/shell.

(We'd like to have a gem module, but it will need to be written in  
Python and just rely on the CLI tools)

---

<div class="post-metadata">

**Author:** ![Lorin\_Hochstein1](https://avatars.discourse-cdn.com/v4/letter/l/ce73a5/32.png) [@Lorin\_Hochstein1](https://forum.ansible.com/u/Lorin_Hochstein1)\
**Post date:** [January 19, 2013, 6:31pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/3 "2013-01-19T18:31:59Z")

</div>

> Hi,
> 
> I've been experimenting with using ansible to configure brand new virtual  
> machines (timezone, ssh keys, ruby, nginx, postgresql, etc) and so far so  
> good. Not having to run puppet daemons is liberating. =)
> 
> Next I'm looking at how to use ansible to perform a series of tasks  
> similar to what is being done by capistrano to deploy new rails code to  
> those VMs. I've searched the newsgroup but I have not seen any mention of  
> someone doing this. Before I go any further, has this been done already? If  
> yes, any sample playbook I can take a look at?
> 
> Thanks in advance!

As Michael noted, the git module is useful for doing deployments. At my  
organization, we use ssh agent forwarding so we don't need to keep private  
keys on the web server to checkout code from our git repository. We use  
native ssh connections with ansible to support agent forwarding \<  
[http://www.ansible.cc/docs/gettingstarted.html#choosing-between-paramiko-and-native-ssh](http://www.ansible.cc/docs/gettingstarted.html#choosing-between-paramiko-and-native-ssh)

> .

I don't think paramiko supports SSH agent forwarding yet, although I  
haven't tried it in a while. This bug suggests that this functionality is  
still under development: [https://bugs.launchpad.net/paramiko/+bug/483697](https://bugs.launchpad.net/paramiko/+bug/483697).

> 

Take care,

Lorin

---

<div class="post-metadata">

**Author:** ![Michel\_Blanc1](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@Michel\_Blanc1](https://forum.ansible.com/u/Michel_Blanc1)\
**Post date:** [January 21, 2013, 3:09pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/4 "2013-01-21T15:09:03Z")

</div>

Hello,

> (We'd like to have a gem module, but it will need to be written in  
> Python and just rely on the CLI tools)

Given how ruby applications are deployed (rvm, rbenv, bundler), I'm not  
sure that having a 'gem' module would be enough or really usefull.  
Almost nobody deploys system wide gems when they deploy a web application.

Most applications are vendorized with bundler, and gems are installe  
locally.  
The problem is more about getting the ruby interpreter you need. For  
this, people typically rely on rvm or rbenv.

Thus, a rbenv or rvm module would be more advised IMHO.

As of now, I'm deploying ruby via rbenv using git module and few  
templates. Meng, I'm curious to see what path you took for your ruby  
deployment.  
Could you elaborate on this ?

Thanks,

M

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [January 21, 2013, 3:33pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/5 "2013-01-21T15:33:59Z")

</div>

> Thus, a rbenv or rvm module would be more advised IMHO.

Make it so?

---

<div class="post-metadata">

**Author:** ![Michel\_Blanc1](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@Michel\_Blanc1](https://forum.ansible.com/u/Michel_Blanc1)\
**Post date:** [January 21, 2013, 3:53pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/6 "2013-01-21T15:53:37Z")

</div>

I'm considering it, despite my python incompetence. I just would like to  
see how Meng and may be others deploy their rubies for now, so I don't  
take a wrong turn straight away.

If you guys have ruby-related playbooks, I'd be glad to see them.

Here is my small ruby playbook : [https://gist.github.com/4586964](https://gist.github.com/4586964)

M

---

<div class="post-metadata">

**Author:** ![Meng\_Kuan](https://avatars.discourse-cdn.com/v4/letter/m/ee59a6/32.png) [@Meng\_Kuan](https://forum.ansible.com/u/Meng_Kuan)\
**Post date:** [January 21, 2013, 3:55pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/7 "2013-01-21T15:55:18Z")

</div>

> I'm unclear what automagic Capistrano is specifically doing in your  
> case, can you give some examples?

The most often used command for capistrano is the 'cap deploy' command.

&nbsp;&nbsp;[http://capitate.rubyforge.org/recipes/deploy.html#deploy](http://capitate.rubyforge.org/recipes/deploy.html#deploy)

This command performs the following steps:

1. Makes the latest revision of the code available on the target node. For a 'copy' strategy, it does a local checkout, zips it up, scp over to target node, unpack. For 'remote\_cache' strategy, it keeps a cache of the code on the target node for faster checkouts.

2. Switch symlink for the 'current' directory to point to the latest checkout. Does the same for the log, run, config directories, etc.

3. Runs 'bundle install' to ensure the app has the gems defined in Gemfile installed

4. Precompile the javascript and css assets

5. Optionally remove old releases

6. Optionally restart the webserver

At any point in time if a step fails, it will roll back to the previous release.

> Definitely you'd want to use the git module, there really isn't a  
> 'gem' module yet but you can use command/shell.

Yes, that's what I've been doing in my setup tasks.

---

<div class="post-metadata">

**Author:** ![Meng\_Kuan](https://avatars.discourse-cdn.com/v4/letter/m/ee59a6/32.png) [@Meng\_Kuan](https://forum.ansible.com/u/Meng_Kuan)\
**Post date:** [January 21, 2013, 4:03pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/8 "2013-01-21T16:03:53Z")

</div>

Hi Michel,

I chickened out on the ruby install. =)

I'm simply installing the ubuntu ruby1.9.3 package and then doing 'gem install bundler'. So far the apps work but I'm wondering how stable that ruby1.9.3 package is in production.

I use rvm in my dev environment and I tell myself that I'll eventually switch to rvm once I have some time. I'll definitely use your ruby playbook as a guide towards that end. Thanks!

cheers,  
mengkuan

---

<div class="post-metadata">

**Author:** ![Michel\_Blanc1](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@Michel\_Blanc1](https://forum.ansible.com/u/Michel_Blanc1)\
**Post date:** [January 21, 2013, 5:42pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/9 "2013-01-21T17:42:34Z")

</div>

> I use rvm in my dev environment and I tell myself that I'll eventually switch to rvm once I have some time.

So we have at least one rvm user and one rbenv user amongst Ansible  
people. That's 2 modules to write already 😛

> I'll definitely use your ruby playbook as a guide towards that end.

Be aware that this only works with the '-i in sudo' which has been  
removed recently because it caused lots of troubles. I don't know how to  
solve this for now (sudo\_exe ?).

M

---

<div class="post-metadata">

**Author:** ![Jeremiah\_Heller](https://avatars.discourse-cdn.com/v4/letter/j/5f8ce5/32.png) [@Jeremiah\_Heller](https://forum.ansible.com/u/Jeremiah_Heller)\
**Post date:** [January 21, 2013, 6:37pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/10 "2013-01-21T18:37:51Z")

</div>

Here is my playbook: [https://gist.github.com/4588017](https://gist.github.com/4588017) - it is fairly naive (e.g. path to installing passenger hardcodes some elements e.g. ‘1.9.1’) but works for my current projects (all running on ruby 1.9.2). It also hardcodes the full path to rbenv related scripts, so the ‘-i’ option isn’t required - not sure how robust this is long-term.

It uses rbenv. Note the use of the rbenv-installer - not sure how well this works outside Ubuntu but could ease implementation of an ansible module.

My experience with rvm (and many others I’ve read/heard of) is that it is difficult to use in provisioning scenarios like this. I use rvm in dev but rbenv in production because of this.

Michel, I’d be happy to help out with these modules, although I’m new to python myself and I’m not sure I can find much time for the next couple of weeks.

- Jeremiah

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [January 21, 2013, 7:11pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/11 "2013-01-21T19:11:58Z")

</div>

Modifying that should technically allow you to put "-i" stuff in the  
beginning, although I can't accept anything module-wise in core that  
requires that to be tweaked to non-stock, otherwise it will raise too  
many questions.

The pip module supports virtualenv without needing -i, so I would hope  
this would also be possible.

---

<div class="post-metadata">

**Author:** ![Michel\_Blanc1](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@Michel\_Blanc1](https://forum.ansible.com/u/Michel_Blanc1)\
**Post date:** [January 23, 2013, 2:25pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/12 "2013-01-23T14:25:40Z")

</div>

> Modifying that should technically allow you to put "-i" stuff in the  
> beginning, although I can't accept anything module-wise in core that  
> requires that to be tweaked to non-stock, otherwise it will raise too  
> many questions.

Sure.

> The pip module supports virtualenv without needing -i, so I would hope  
> this would also be possible.

In my case, the problems lies in the sudo config : in some default  
configuration (Ubuntu), sudo locks $HOME so this environment variable is  
preserved This means that f you're root, and sudo as "user", your home  
will be /root (or whatever root's home is) anyway.

This breaks a lot of things on behalf of the target user that assure  
$HOME is really the user's $HOME. rbenv init scripts are no exceptions.

The solution to this is to configure sudo on the remote node to allow  
HOME overriding with this in /etc/sudoers :

&nbsp;&nbsp;Defaults always\_set\_home

I don't know if this has security implications. Anyway I don't think  
preventing HOME being set to another location improves security in  
anyway (and it can easily be circumvented since the caller is root in  
this case...).

You can then wrap your calls in 'bash -lc' (e.g. 'bash -lc "rbenv  
version"' so the whole environment gets loaded properly.

This is quite hackish, but as of now this is the only way I found to  
circumvent the lack of "-i" in sudo calls.

M

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan](https://avatars.discourse-cdn.com/v4/letter/m/c4cdca/32.png) [@Michael\_DeHaan](https://forum.ansible.com/u/Michael_DeHaan)\
**Post date:** [January 23, 2013, 2:44pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/13 "2013-01-23T14:44:50Z")

</div>

> > Modifying that should technically allow you to put "-i" stuff in the  
> > beginning, although I can't accept anything module-wise in core that  
> > requires that to be tweaked to non-stock, otherwise it will raise too  
> > many questions.
> 
> Sure.
> 
> > The pip module supports virtualenv without needing -i, so I would hope  
> > this would also be possible.
> 
> In my case, the problems lies in the sudo config : in some default  
> configuration (Ubuntu), sudo locks $HOME so this environment variable is  
> preserved This means that f you're root, and sudo as "user", your home  
> will be /root (or whatever root's home is) anyway.
> 
> This breaks a lot of things on behalf of the target user that assure  
> $HOME is really the user's $HOME. rbenv init scripts are no exceptions.
> 
> The solution to this is to configure sudo on the remote node to allow  
> HOME overriding with this in /etc/sudoers :
> 
> &nbsp;&nbsp;Defaults always\_set\_home

Always seems bad, and requires extra configuration? We could  
possibly consider adding "-H" to the sudo arguments maybe?

---

<div class="post-metadata">

**Author:** ![Michel\_Blanc1](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@Michel\_Blanc1](https://forum.ansible.com/u/Michel_Blanc1)\
**Post date:** [January 23, 2013, 2:56pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/14 "2013-01-23T14:56:06Z")

</div>

Yes, having -H would be \*much\* better. It could be nice if people which  
experienced side effects with -i could try -H.

However, we'll still have to wrap things in 'bash -lc' calls.

Thanks,

M

---

<div class="post-metadata">

**Author:** ![Michel\_Blanc1](https://avatars.discourse-cdn.com/v4/letter/m/fbc32d/32.png) [@Michel\_Blanc1](https://forum.ansible.com/u/Michel_Blanc1)\
**Post date:** [January 23, 2013, 3:14pm UTC](https://forum.ansible.com/t/playbook-example-for-capistrano-type-deployment/12215/15 "2013-01-23T15:14:06Z")

</div>

> Here is my playbook: [https://gist.github.com/4588017](https://gist.github.com/4588017)

Thanks.

> My experience with rvm (and many others I've read/heard of) is that it  
> is difficult to use in provisioning scenarios like this. I use rvm in  
> dev but rbenv in production because of this.

Yeah, I tend to avoid rvm in production too and vendorize stuff with  
bundler.  
Ruby is great, but a real pain to deploy.

> Michel, I'd be happy to help out with these modules, although I'm new to  
> python myself and I'm not sure I can find much time for the next couple  
> of weeks.

Thanks Jeremiah.  
My Python experience is very limited too...

Besides this, I'm wondering if rbenv/rvm can really be handled in a  
module. Those installations involves quite a lot of fiddling : when you  
install ruby, you usually target a specific user. Then, you need to  
change it's environment and add some rbenv init scripts and alter  
PATH... All this depends on which distro you use, which shell you use,  
etc...

So after some thought, it looks more like a job for a playbook to me. A  
module would have really hard time to handle even classic use case  
scenarios, and would have to touch too many things to be reliable.

M
