Search code examples
rubysudobundlerrvmthin

RVM and thin, root vs. local user


So I'm trying to get thin to run as a service with RVM. After a thin install I manually updated /etc/init.d/thin to use an su - user when running the config command so that thin was running as a local user, rather than root. So far so good.

Now, when I try to sudo service thin start it looks like it's trying to use the non-RVM version of Ruby (1.8.7 which was installed on the box to start with) to actually execute the command. I did a gem install thin on the non-RVM version, which then gets me a uninitialized constant Bundler message—Bundler is only installed in the RVM gems, not the system gems. It looks like I can't get the RVM environment set up (even though my RVM startup script is in ~/.bashrc which is then included in ~/.bash_profile).

All I want to do is run thin as a service using the RVM environment, not the system environment. Is this even possible? Should I just give up and commit the ultimate sin of running everything as root? It's very tempting at this point.

Thanks for any help!


Solution

  • RVM comes with a handy wrapper generator that creates an intermediary loader for an init.d script. This allows you to load a service using a particular Ruby version and gemset. I use it like this (after installing the thin gem):

    1 - create init.d entry for thin

    sudo thin install 
    

    2 - set up some defaults

    sudo /usr/sbin/update-rc.d -f thin defaults 
    

    3 - generate boot config for your rails app

    sudo thin config -C /etc/thin/<appname>.yml -c /var/rails/<appdir> --servers 4 -e production
    

    4 - generate rvm wrapper script

    rvm wrapper <rubyversion>@<gemset> bootup thin
    

    5 - If you're using a global gemset, you can just use

    rvm wrapper ruby-1.9.2-p125 bootup thin
    

    6 - edit thin init

    sudo nano /etc/init.d/thin
    

    7 - change the original loader

    DAEMON=/usr/local/rvm/gems/ruby-<rubyversion>-<rubyrevision>@<gemset>/bin/thin
    

    8 - to point to the rvm wrapper instead

    DAEMON=/usr/local/bin/bootup_thin
    

    9 - start it up

    sudo service thin start
    

    If you're running more than one app, just generate a boot config yml file for each one; when booting thin all yml files in /etc/thin/ are parsed. More info here:

    http://wiki.rubyonrails.org/deployment/nginx-thin?rev=1233246014 nb: This is linking to a revision, the most current version has been edited to be empty. Consider looking at the link without the ?rev=... in the url, the current version may be back and potentially more up to date.

    HTH

    2013 BONUS EDIT

    While I no longer use RVM in production, thin is still my production server of choice, and I still use steps 1-3 above to get started. But the default configuration it generates can do with a few tweaks, here are some of mine:

    Set the user & group that thin runs as:

    user: www-data
    group: www-data
    

    Remove the port config and switch to using sockets instead (a little faster):

    # port: 3000
    socket: tmp/sockets/<appname>.sock
    

    Tell thin to restart instances one by one, instead of shutting them all down before starting up again (rolling restart):

    onebyone: true
    

    Give the server processes a "tag" to help identify them (in ps aux etc):

    tag: <appname>