Use Babushka to set up an Ubuntu 10.04 Server to run a Rails app

UPDATE: These instructions no longer work. Babushka went through a growth spurt and lots of breaking changes were made. I decided to wait for the project to settle down a bit before updating this post. I believe it is stabilizing so I’m going to update this soon. Be sure to check back here within the next week!

Basic setup

Most of this is copied from the Zero to Hero with Babushka screencast. Watching it is highly recommended
before you start fiddling with Babushka!

For this tutorial I assume that you’ve intalled a bare bones Ubuntu 10.04 Server and you’re logged into your user account.

First we’re going to set up babushka itself:

1
bash -c "`wget -O - babushka.me/up`"

This will bootstrap Babushka and proceed to install ruby, irb and various other useful packages.
When prompted for whose deps you’d like to install, enter ‘gpaul’.

Next we’re going to have Babushka do some base system config by installing ssh, curl, htop and some other apps that come in handy at times:

1
babushka system

Application setup

From here onwards it’s all up to you. You can install mysql, postgres, nginx, etc. You can also add more babushka-deps from github if you see
something you like or fork Ben Hoskings’ Babushka-Deps repo and add your own deps.

For this tutorial I’m going to use Ben’s Nginx and Postgres deps and get a sample rails app (Enki) going.

Ben uses an interesting approach: he sets up a user account for the app named after the domain. Sounds pretty cool so let’s go that route.
Remember: when asked for your username, enter ‘your-domain-name.tld’ (eg. enkiblog.com) Also, when asked for home dir base enter ‘/var/www’ or ‘/src/http’, whichever one you prefer to host your apps out of.

1
babushka 'user exists'

Set up a password for your new user:

1
sudo passwd your-domain.tld

Now become the new user:

1
su - your-domain.tld

Sweet! Now for some real action. We’re going to set up a git repo our app is going to reside in at. When asked, I put it in ~/current to keep with convention.

1
babushka 'passenger deploy repo'

The post-receive hook it adds is pretty cool: every time you push to this repo, the post-receive hook will refresh the code and restarts the passenger instance…have a look:

1
2
3
4
5
6
cat ~/current/.git/post-receive

cd ..
env -i git reset --hard
mkdir -p tmp
touch tmp/restart.txt

On your local machine, cd to your rails app’s root and add the repo on the server as a remote repository:

1
2
3
git remote add server your-domain.tld@your-ip-address:~/current
git push server master
... wait for it to finish pushing ...

Once its finished, your code will be on the server in the ~/current repo you created.

Now that we’ve set up the code on the server, we need to set up the rails app itself. Easy enough with Babushka, answer the prompts as you go:

1
babushka 'rails app'

Congrats, you can hit http://your-domain.tld and see your app hosted and running off postgres and nginx.

Sharing a session between subdomains

http://guestbook.co.za/ is also available at http://www.guestbook.co.za/. We wanted our users to remain logged in if they’re using GuestBook without the ‘www.’ subdomain and then enter it or visit the site from a link.

To do so we needed to share the session between www.guestbook.co.za and guestbook.co.za. This sounds really difficult but thankfully all it takes is prepending the domain name of your cookie with a period (.)

Here’s how to do it in Rails:

1
2
3
4
5
6
# In your production.rb file
config.action_controller.session = {
  :session_domain => ".your-domain.tld",
  :session_key    => "_yourapp",
  :secret         => "somehugesecretkeythathastobemorethanthirtycharacterslong"
}

Thanks for the original post I got this from!

Upgrade a show/hide toggle to use jQuery/Ajax

A friend of mine – Auke – is building a web application. The user has a secondary level of navigation that she
can show/hide at any time.

The app doesn’t include any javascript yet so clicking ‘Show Navigation’ currently reloads the page.
Auke rightly feels that this is a clunky solution and makes testing difficult. Here’s how to switch it around.

Before

1
2
3
4
5
6
7
8
9
<% if navigation_should_be_shown? %>
  <div id="navigation">
    <!-- Some links and stuff -->
  </div>

  <a href="/toggle-me-baby">Hide Navigation</a>
<% else %>
  <a href="/toggle-me-baby">Show Navigation</a>
<% end %>

After

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<head>
.....
  <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>

  <script type="text/javascript">
    function updateToggleText() {
      if ($("#navigation").is(":visible")) {
        $("#toggle").text("Hide Navigation");
      } else {
        $("#toggle").text("Show Navigation");
      }
    }
    
    $(document).ready(function() {
      $("#toggle").click(function() {
        $.post({url:  "/toggle-me-baby", function(response) {
          if (response == 'toggled!') {
            $("#navigation").toggle();
    
            updateToggleText();
          } else {
            alert("There was a problem toggling the navigation!");
          }
        });
      });
    });
  </script>
  
.......
</head>

<!-- Replacing the code from above -->
<% if navigation_should_be_shown? %>
  <div id="navigation">
    <!-- Some links and stuff -->
  </div>

  <a id="toggle" href="/toggle-me-baby">Hide Navigation</a>
<% else %>
  <div id="navigation" style="display:none">
    <!-- Some links and stuff -->
  </div>

  <a id="toggle" href="/toggle-me-baby">Show Navigation</a>
<% end %>

I haven’t tested this yet but it should do the trick. :)

Gustav