Install and run RVM and Ruby 1.9.x on Red Hat OpenShift

UPDATE (03-08-12): This post is now largely obsolete as we now have a Ruby 1.9 cartridge available on OpenShift! While this is awesome, I’ll still be working on other little hacks including the Unicorn/Nginx cartridge, a specialised Ruby version manager for DIY cartridges and a little set of tools to quickly interact with your app above and beyond what rhc-tools let’s you do. You can still refer to this post however if you want to use the abilities of RVM on a DIY cartridge. Hope it helped!

When I first started investigating Red Hat’s new Platform-as-a-Service – OpenShift – for deploying my CRM app on, I discovered that they’ve only officially launched a Ruby 1.8.7 environment. I discovered I wasn’t the only person wishing for Ruby 1.9.x support on the forums, so I decided to see if I could install and use RVM on the system. Thankfully, Red Hat give you the ability to SSH into a restricted bash shell to manage your apps and this proved key to getting it to work.

After 3 long nights, I’ve managed to successfully install my own custom version of RVM designed for the OpenShift servers, and built and run Ruby 1.9.3-p125 and Rails 3.2.3, so here I explain how:

1. Create a DIY cartridge and configure SSH Access

Before you start, you need to create a “DIY” cartridge, or app. This is a blank slate where you configure the system yourself. This is just so we don’t get any version conflicts or config errors:

rhc-create-app -a [appname] -t diy-0.1 -l [email] -p [password]

You can also create the app through the new web console, but using the rhc tools will create your repository and perform some other setup (such as SSH public keys), which you’ll have to do manually otherwise.

To get your SSH details, run the following:

rhc-domain-info -l [email] -p [password] --apps

This will print out all the apps in your namespace and their corresponding information. The ‘UUID’ is your SSH username and the ‘Public URL’ (minus the “http://”) is the SSH server. You should then be able to connect like so:

ssh 9a4c7dbdc3@rvm-pyramidthoughts.rhcloud.com

2. Download and Install RVM for OpenShift

Once connected to your app instance, use the following command to download and run the automated installation script I’ve written.

UPDATE (03-05-12): If you were getting an error from curl like in the comments below, its because GitHub altered the  path!  – The curl command should now work properly.

cd $OPENSHIFT_DATA_DIR
curl -L https://raw.github.com/xiy/rvm-openshift/master/binscripts/install-rvm-openshift.sh | bash -s

In short, it will download a working copy of the libyaml-0.1.4 source and compile it, and then dowload and install my version of RVM, as well as installing the latest stable version of Ruby (1.9.3-p125). During my testing, the copy of libyaml that RVM fetched was configured wrongly and failed to build on the servers, hence the custom build.

NOTE: You may also want to build readline if you require it (for irb etc.) and configure with ‘–prefix=$OPENSHIFT_DATA_DIR/.rvm/usr’ to ensure that it’s linked with Ruby when it compiles. This has to be done BEFORE Ruby is compiled.

3. Install and configure a Rails app

Once Ruby and RVM are completely installed, test that it works:

$ source $OPENSHIFT_DATA_DIR/.rvm/scripts/rvm
$ rvm use 1.9.3-p125@global
$ ruby -e 'puts "Hello OpenShift!"'
=> Hello OpenShift!

All going well it should say hello. You should now be able to create your Rails app and code away locally. Make sure you have a ‘.rvmrc’ file in the root of your Rails app that lets RVM know what version of Ruby to use and the name of the gem set.

Update (23-05-2012): You can create AND initialise your project .rvmrc with one command, thanks to @wayneseguin

# NOTE: These commands should be performed INSIDE your Rails app dir.
$ rvm --create --rvmrc 1.9.3-p125@[appname]
$ rvm use --create 1.9.3-p125@[appname];
$ touch .rvmrc && echo 'rvm 1.9.3-p125@[appname]' >> .rvmrc

Also make sure that you edit the action_hook scripts to perform the necessary housekeeping. At this point, I would also suggest using a server such as Thin in place of the clunky WEBrick. You can run it via the rails builtin script or like I’ve done here:

.openshift/action_hooks/post_deploy:

# this will spawn a sub-shell, so make sure we can use rvm
source $OPENSHIFT_DATA_DIR/.rvm/scripts/rvm

# make sure our bundle is up to date
cd $OPENSHIFT_REPO_DIR/[appname]
bundle

.openshift/action_hooks/start:

# this will spawn a sub-shell, so make sure we can use rvm
source $OPENSHIFT_DATA_DIR/.rvm/scripts/rvm

# make sure we're in the app-dir so we use the right gemset
cd $OPENSHIFT_REPO_DIR/[appname]

# start the thin server on the internal ip and port
bundle exec thin start -d -a $OPENSHIFT_INTERNAL_IP -p $OPENSHIFT_INTERNAL_PORT -l $OPENSHIFT_LOG_DIR/thin.log

NOTE: You may also want to symlink the environment logs in the rails app logs directory to the $OPENSHIFT_LOG_DIR to make sure you capture everything from your app, as in testing I’ve found that the Thin process doesn’t seem to log everything.

.openshift/action_hooks/stop:

# kill the server through the pidfile
kill `cat -- $OPENSHIFT_REPO_DIR/[appname]/tmp/pids/thin.pid`

Unicorn is another great alternative thanks to it’s performance and worker threads, which is ideal for a restricted resource environment like OpenShift. I would also pair it with Foreman and dump the stdout of Foreman into ~/app/logs so that it can be tailed locally with the ‘rhc-tail-files’ command. You can also hook into a service like Travis-CI in your ‘.openshift/action_hooks/pre_build’ script to run your integration tests. I may have to write a blog post about action_hooks soon that can show all this in action.

At this point you should be good to go and code away and push your Rails 3.2+ app up to the OpenShift servers on MRI Ruby 1.9.x. If you want to see a Rails 3.2.3 app running on Ruby 1.9.3-p125 to prove it works, go here.

Enjoy!

p.s If you’d like to improve my hacky edits to RVM or if there are any bugs, you can browse the repo on my GitHub: http://github.com/xiy/rvm-openshift.

28 thoughts on “Install and run RVM and Ruby 1.9.x on Red Hat OpenShift

      • Hehe no worries!

        As a rule, the two directories you should be working in are…

        ~/appdir/data
        ~/appdir/repo

        …as these have full write access. Also remember that information in your repo dir gets overwritten whenever you push using Git, so store any information you want to keep that’s outside of your repository inside the data dir. Once you have your app set up and your action hooks working, you shouldn’t need to touch the repo directory anyway.

        Good luck!

    • Make sure you run the curl commands within the ~/yourappdir/data directory (also available as the $OPENSHIFT_DATA_DIR environment variable) in SSH.

      If you are, please add -v to the command and let me know what it says!

      Thanks.

      • Hello, thank you for this “magick”.
        But I have same problem, with “-v” it say:

        { [data not shown]
        bash: riadok 1: chyba syntaxe neďaleko neočakávaného tokenu „newline“
        bash: riadok 1: `’
        * Failed writing body (1235 != 5619)
        100 16672 100 16672 0 0 525k 0 –:–:– –:–:– –:–:– 525k* Closing connection #0

        curl: (23) Failed writing body (1235 != 5619)

  1. Thank you.
    Maybe next bug:
    source $OPENSHIFT_DATA_DIR .rvm/scripts/rvm;
    between $CONSTANT and child directory must be space ” “, not slash “/”
    its working for me.

    Next problem for me:

    remote: An error occured while installing rake (0.9.2.2), and Bundler cannot continue.
    remote: Make sure that `gem install rake -v ‘0.9.2.2’` succeeds before bundling.

    I have default Gem file.

  2. Hmm, I’m not sure I understand. The command:

    source $OPENSHIFT_DATA_DIR/.rvm/scripts/rvm

    should work fine with the “/” (it just does what RVM would normally do in a standard environment on shell login).

    The only reason I can think of for it not installing rake properly is permissions (i.e. wrong directory) or RVM hasn’t been activated properly. Make sure you run the ‘source’ command above before you use RVM and test it by just typing ‘rvm’ in the shell.

    If you’re running the `bundle` command through a hook (I’m guessing by the ‘remote:’ part) then make sure that at the top of the hook script you have the ‘source’ command, otherwise it’ll try to install using the system Ruby (1.8.7).

    • with “/” do this:

      remote: /var/lib/stickshift/96f164c3f3344f8bac434e88a6544488/store/data//.rvm/scripts/cd: line 45: cd: /var/lib/stickshift/96f164c3f3344f8bac434e88a6544488/store/repo//[appname]: Dir or file not exist

      rake is maybe problem with my RoR apps, I’m going to test it tomorrow. Thank you for fast answer. You are doing good job with this script.

      • Well my app shows the 503 error page and I follow step by step, but I don’t know if there are some diferences between Rails and Sinatra, but the point is that I just wanna use ruby 1.9.3, it doesn’t matter what framework I will use.

        Can I do this following your post? Or Are there any steps that this post doesn’t show me?

        By the way sorry for my terrible english, I am brazilian guy who has a lot of apps on openshift!

      • You can definitely use Sinatra following this tutorial, its more fore 1.9.3 and RVM than Rails specifically. It sounds like you may not have the server correctly set up to receive requests from outside. How are you serving the Sinatra app?

      • Well I don’t understand your question, but I install rvm, ruby 1.9.3 fine from ssh.

        One question, on DIY mode, Do I need to put all app code on the folder diy or on root folder?

      • All your app code should be within ~/appname/repo, which you can also reference with the $OPENSHIFT_REPO_DIR environment variable.

        Remember though that your OpenShift app is designed to be updated/modified using Git, so it’s best if you only do the initial setup through SSH.

        You should start the rack server through the action hook scripts (explained at the bottom of the blog).

    • Depending on your use case, rbenv can actually be better. Neither are that well programmed when it comes to restricted environments however!

  3. After this step

    # NOTE: These commands should be performed inside your Rails app dir.
    $ rvm use –create 1.9.3-p125@;
    $ touch .rvmrc && echo ‘rvm use 1.9.3-p125@;’ >;>; .rvmrc

    (I issued these commands line twice : in app_name/repo and app_name/data

    I have this error when issuing source $OPENSHIFT_DATA_DIR/.rvm/scripts/rvm :

    source $OPENSHIFT_DATA_DIR/.rvm/scripts/rvm

    Error:
    /var/lib/stickshift/641b3f457f8742f8bab9dbe820a90f53/rexoweb/data/.rvmrc is for rvm settings only.
    rvm CLI may NOT be called from within /var/lib/stickshift/641b3f457f8742f8bab9dbe820a90f53/rexoweb/data/.rvmrc.
    Skipping the loading of /var/lib/stickshift/641b3f457f8742f8bab9dbe820a9

    any help please

    thanks

    • Try running this command instead, inside your app directory:

      rvm --create --rvmrc 1.9.3-p125@[appname]

      This should work. If not then edit your .rvmrc file to just say:

      rvm use 1.9.3-p125@[appname]

      • thanks, can I know what do you mean by app directory? my ruby app called “rexoweb” and I have only writing rights in rexoweb/repo and rexoweb/data
        Which directory I should take.

        you said that you used this hack for you ruby CRM. can I know the name?

        Thanks

  4. I have this error after pushing my app :

    /var/lib/stickshift/abde5a0d18fd4f9dbd911ead6bfcb357/rexoweb/data//.rvm/scripts/cd: line 45: cd: /var/lib/stickshift/abde5a0d18fd4f9dbd911ead6bfcb357/rexoweb/repo//rexoweb: No such file or directory
    remote: Could not locate Gemfile

  5. Hi. In first, thanks for your well done work. At the moment I have running (test) app on Openshift with ruby 1.9.3 and rails, thanks to you, I can edit, coding and etc.
    But I have some, maybe stupid question. How I can use git for this? I mean, for now, I connect to my openshift app via ssh, edit and coding what I want or what I need, but I can’t undestand how to use git. So, if you have some advise and some time maybe you can explain this?

    Thanks again.

    • Actually that’s not a bad question at all. Red Hat haven’t really (in my opinion) documented the workflow you’re supposed to use when developing on OpenShift, but if you’re familiar with Heroku then it’s pretty much the same. The basic workflow, considering you follow this tutorial, should be:

        1. Using this tutorial, set up RVM and Ruby, as well as your web server.
        2. Clone the repository to your local system from the OpenShift server using Git: git clone ssh://[uuid]@[app]-[namespace].rhcloud.com
        3. Create your Rails/Sinatra app in the local repo, edit, and then push back up to the OpenShift server: git push origin master
        4. When you push, it will trigger your action_hook scripts inside the .openshift directory of your repo, so remember to edit these too as in the tutorial.

      You can find the url to clone from by using the web console on the OpenShift website or using the rhc-domain-info script at the command line (part of rhc-tools).

      • Hi. Thanks again for so fast answer. I just trying get this work, but without success. I’m not sure that I understand correct this:

        “3. Create your Rails/Sinatra app in the local repo, edit, and then push back up to the OpenShift server: git push origin master”

        I mean, after clone I have on my mashine folowing dir: my app, and in this dir I have two dir: diy and misc, and Readme file. So, where I should create my Rails app?
        There is also hidden directories, as .git. It would be so that I should create my Rails app in this .git?
        Sorry for my English 🙂

      • Hi. Sorry about this spam. I just want say, I finally got this work. Everithing works ok, thank to you again 🙂
        Good lack.

  6. Pingback: Unicorn+Nginx on Red Hat OpenShift | Pyramid Thoughts

Leave a reply to xiy Cancel reply