Ubuntu Hardy - thin web server for Ruby

There are variety of options open to the sysadmin when serving Ruby applications.

One of them is thin. This is a 3rd party web server that is proxied to from the main web server (similar to mongrels in a general setup). Let's take a look at installing thin.


Prerequisites

I am assuming you have Ruby and Rubygems installed on your Slice. If you don't, please see the Ubuntu Hardy Ruby on Rails article).

Installation

Thin is a rubygem and so installation couldn't be easier:

sudo gem install thin

On the test Slice with a basic rubygems and Rails installation, the process installed the following gems:

rack-0.3.0
daemons-1.0.10
eventmachine-0.10.0
thin-0.8.1

Thin basics

There will be separate articles for proxying to thin from different web servers (Apache, Nginx, etc).

As such, we'll only look at the basics of thin, leaving Virtual Host configurations for later.

To determine the thin verions:

thin -v

As is often the case in the wacky world of the developer, each version has a unique name:

thin 0.8.1 codename Rebel Porpoise

Starting and stopping

Starting thin requires you to navigate to the rails directory and issuing this command:

thin start -d

The '-d' option runs it in the background. If you omitted the '-d' option, it would act in a similar manner to the webbrick server and requires an 'open' terminal. In that case, a standard 'Ctl -C' would kill the process.

To stop thin, you don't need to worry about finding the PID or searching for something to kill:

thin stop

Environment

The default environment for thin is development. To start it in a production environment is easy:

thin start -d -e production

Cluster

It would be relatively unusual for a Rails application to only need 1 ruby server, so to start a cluster of 3 would require this:

thin start --servers 3

The output shows 3 servers being started sequentially from port 3000 (the default port).

Stopping the cluster is just as easy:

thin stop --servers 3

Again, the output is very clear: a quit signal is sent to each PID.

Runlevels

You can add thin to a runlevel (/etc/init.d/) with ease.

To start with you need to create the script:

sudo thin install

Then add the script to the default runlevels:

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

The output confirms the process:

Adding system startup for /etc/init.d/thin ...
   /etc/rc0.d/K20thin -> ../init.d/thin
   /etc/rc1.d/K20thin -> ../init.d/thin
   /etc/rc6.d/K20thin -> ../init.d/thin
   /etc/rc2.d/S20thin -> ../init.d/thin
   /etc/rc3.d/S20thin -> ../init.d/thin
   /etc/rc4.d/S20thin -> ../init.d/thin
   /etc/rc5.d/S20thin -> ../init.d/thin

Excellent.

Now we need to define which (if any) of the rails applications to start on a reboot.

Just for example, assume I have a rails application located here:

/home/demo/public_html/testapp/

I want to start 3 thin servers and be in production mode when they are started:

sudo thin config -C /etc/thin/testapp.yml -c /home/demo/public_html/testapp/  --servers 3 -e production

Have a look at the file that was created:

cat /etc/thin/testapp.yml

The contents:

pid: tmp/pids/thin.pid
log: log/thin.log
timeout: 30
max_conns: 1024
port: 3000
max_persistent_conns: 512
chdir: /home/demo/public_html/testapp
environment: production
servers: 3
address: 0.0.0.0
daemonize: true

As you can see, there are several options that can be tweaked by hand if needed.

Note the server numbers and environment are exactly as we set them. You can, of course, add as many or as few options to the command as you require, such as port numbers and so on.

When the Slice is rebooted, the 3 thin servers will now start automatically.

More

As with most applications, there is more than I can go into here but please do check out all the options that are available to you:

thin --help

Summary

Thin is an established method of serving Ruby on Rails applications. I hope this introduction outlines how easy and sysadmin friendly thin actually is.

To see how to proxy to the thin web server from Apache or Nginx, please see the next few articles.

PickledOnion

Article Comments:

Craig commented Fri May 30 17:26:05 UTC 2008:

There is a typo in the first step.

"sudo gem instal thin"

Should be...

"sudo gem install thin"

PickledOnion commented Fri May 30 17:28:40 UTC 2008:

Hi Craig,

Luckily, it can be either instal or install - it makes no difference to the installation of the thin gem.

Thanks for the note though, I will update it :)

PickledOnion

MJS commented Mon Jun 16 12:57:01 UTC 2008:

I think this tutorial should probably have the same warning as the updated rails tutorial. For small Slices use:

sudo gem install thin --no-rdoc --no-ri

It's been slowly trying to install the ri files for the last hour on my 256mb Slice.

Jesse commented Thu Jul 03 21:36:10 UTC 2008:

I followed the Ruby/Rails article and then tried installing thin but got an error: "checking form main() in -lpthread... no" on a brand new Hardy slice.

Brendan commented Fri Jul 18 20:24:40 UTC 2008:

I ran the command:

thin start -d

and then:

thin stop

and i get this output:

Can't stop process, no PID found in tmp/pids/thin.pid

erik commented Thu Aug 14 18:50:41 UTC 2008:

"sudo gem install thin" failed on my slice (Hardy).

I had to do "sudo apt-get install build-essential" in order to get "make" which is needed to install thin. Doing this is wise anyway since many installs rely on this.

Victor commented Fri Aug 15 22:16:43 UTC 2008:

I get the same error as Brendan.

After finishing all of your Thin instructions, In response to:

sudo /etc/init.d/thin start

I get:

[restart] /etc/thin/mysitename.yml ... Stopping server on 0.0.0.0:5000 ... Can't stop process, no PID found in tmp/pids/thin.5000.pid Stopping server on 0.0.0.0:5001 ... Can't stop process, no PID found in tmp/pids/thin.5001.pid Stopping server on 0.0.0.0:5002 ... Can't stop process, no PID found in tmp/pids/thin.5002.pid Starting server on 0.0.0.0:5000 ... Starting server on 0.0.0.0:5001 ... Starting server on 0.0.0.0:5002 ...

Can you please take a look?

Victor

morhekil commented Sat Aug 16 23:22:11 UTC 2008:

Victor, you've probably written "restart" instead of "start". That's not a problem as it just tried to stop servers first - and you've got your errors, of course, as no servers were running. As there were no errors after "Starting..." you should see your servers up and running in the process list.

Victor commented Tue Aug 19 03:52:26 UTC 2008:

Thanks for responding morhekil! I am sorry I was not clear - here is the complete sequence after a reboot - it appears that a fresh thin installation may be quietly crashing on start (?) let me know what you think (I completed all of the tutorials listed here xcept for nginx/mongrel - i was hoping to use thin):

SERVERNAME ~: thin start --servers 3 Starting server on 0.0.0.0:3000 ... Starting server on 0.0.0.0:3001 ... Starting server on 0.0.0.0:3002 ... SERVERNAME ~: ps ax PID TTY STAT TIME COMMAND /sbin/init [kthreadd] [migration/0] [ksoftirqd/0] [watchdog/0] [events/0] [khelper] [xenwatch] [xenbus] [migration/1] [ksoftirqd/1] [watchdog/1] [events/1] [migration/2] [ksoftirqd/2] [watchdog/2] [events/2] [migration/3] [ksoftirqd/3] [watchdog/3] [events/3] [kblockd/0] [kblockd/1] [kblockd/2] [kblockd/3] [kseriod] [pdflush] [pdflush] [kswapd0] [aio/0] [aio/1] [aio/2] [aio/3] [accel_watch/0] [accel_watch/1] [accel_watch/2] [accel_watch/3] [ksnapd] [kjournald] /sbin/udevd --daemon /sbin/syslogd -u syslog /bin/dd bs 1 if /proc/kmsg of /var/run/klogd/kmsg /sbin/klogd -P /var/run/klogd/kmsg /usr/sbin/sshd /bin/sh /usr/bin/mysqld_safe /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/my logger -p daemon.err -t mysqld_safe -i -t mysqld /usr/lib/postfix/master qmgr -l -t fifo -u /usr/sbin/cron /usr/sbin/apache2 -k start /sbin/getty 38400 tty1 /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start /usr/sbin/apache2 -k start pickup -l -t fifo -u -c sshd: USERNAME [priv] sshd: USERNAME@pts/0 -bash ps ax vbrodsky ~: thin stop --servers 3 Stopping server on 0.0.0.0:3000 ... Can't stop process, no PID found in tmp/pids/thin.3000.pid Stopping server on 0.0.0.0:3001 ... Can't stop process, no PID found in tmp/pids/thin.3001.pid Stopping server on 0.0.0.0:3002 ... Can't stop process, no PID found in tmp/pids/thin.3002.pid SERVERNAME ~:

Victor commented Tue Aug 19 05:43:06 UTC 2008:

I should have mentioned this right away - but this may be the key:

I am storing the sites in /var/www/sitename.com and in that site's folder is the 'rails' folder containing the ruby on rails app folder with all the files...

Here is the error log of one of the thin servers:

/var/www/SITENAME.com/rails/insoshi/config/../vendor/rails/railties/lib/initializer.rb:701:in read': No such file or directory - /var/www/SITENAME.com/rails/insoshi/config/database.yml (Errno::ENOENT) from /var/www/SITENAME.com/rails/insoshi/config/../vendor/rails/railties/lib/initializer.rb:701:indatabase_configuration' from /var/www/SITENAME.com/rails/insoshi/config/../vendor/rails/railties/lib/initializer.rb:331:in initialize_database' from /var/www/SITENAME.com/rails/insoshi/config/../vendor/rails/railties/lib/initializer.rb:120:inprocess' from /var/www/SITENAME.com/rails/insoshi/config/../vendor/rails/railties/lib/initializer.rb:93:in send' from /var/www/SITENAME.com/rails/insoshi/config/../vendor/rails/railties/lib/initializer.rb:93:inrun' from /var/www/SITENAME.com/rails/insoshi/config/environment.rb:13 from /usr/local/lib/siteruby/1.8/rubygems/customrequire.rb:27:in gem_original_require' from /usr/local/lib/site_ruby/1.8/rubygems/custom_require.rb:27:inrequire' ... 8 levels... from /usr/lib/ruby/gems/1.8/gems/thin-0.8.2/lib/thin/runner.rb:136:in run!' from /usr/lib/ruby/gems/1.8/gems/thin-0.8.2/bin/thin:6 from /usr/bin/thin:19:inload' from /usr/bin/thin:19

Writing PID to tmp/pids/thin.5000.pid Using rails adapter Exiting!

and the Apache error.log has:

[Fri Aug 15 21:53:42 2008] [error] proxy: apgetscoreboard_lb(0) failed in child 4534 for worker http://127.0.0.1:5000

Is it an issue of a missing required gem of the insoshi app? or a configuration error? because even if I simply try to start the thin server (as I mentioned in my previous post) it looks like it quietly fails...

Thanks for any comments!

Victor

Victor commented Tue Aug 19 15:18:56 UTC 2008:

So wanted to send an update -

I now made sure that the ruby on rails application has all the gems and packages that it needs and all of its assertions give zero errors.

Now when 3 Thin servers load after a soft VM reboot - they actually stay running (on the ps ax process list). The thin logs have no errors either, but when I visit the domain name, instead of a home page I get the ruby-on-rails application's 500.html error file from its public folder. Now that the thin servers are running - I do not know what I should do to find the problem.

If the site is stored in /var/www/SITENAME.com/rails/rails-app - should I change some permissions via chmod? What is the best place to seek the error now that it looks like Thin is serving the error 500? What would you do?

Thanks so much for any comments!

Marty McGee commented Tue Aug 19 22:31:53 UTC 2008:

Just some friendly notes to fellow users about 502 Bad Gateway errors and 500 Internal Server errors...

  1. For people having a 502 Bad Gateway error, make sure you set your "workerprocesses" variable in the Nginx configuration file (2nd line down) to a value greater than or equal to the number of thin server instances ("cluster") you are requesting. The Nginx default is only 1, so if you request 2+ mongrels for your app to run on, you'll get a 502 error. To be safe, set "workerprocesses" to 4 and request 4 or less thin server instances, then reboot your server.

  2. For people getting a 500 Internal Error message, make sure you create your production database first by running "rake db:migrate RAILS_ENV=production" before you try to run your Rails app on your server - otherwise Rails won't be able to access your database and errors galore. (Duh, right? Well, I forgot :-)

  3. Make sure your thin cluster is running! You can check this by entering "ps -ef | grep thin". If it's not running, you either didn't initially run "sudo gem install thin && sudo thin install", or You should see more than 1 line, like this:

root 4004 1 2 22:08 ? 00:00:07 thin server (0.0.0.0:3000)
root 4009 1 2 22:08 ? 00:00:07 thin server (0.0.0.0:3001)
demo 4149 4138 0 22:13 pts/0 00:00:00 grep thin

  1. If none of these work, keep trying things. Your persistence will pay off! It took me a few hours and a few mistakes to get it right.

Good Luck

Marty McGee commented Tue Aug 19 22:37:10 UTC 2008:

Sorry about the Markdown issues on the previous comment. Just wanted to mention that the Nginx config file I'm speaking of is located at /etc/nginx/nginx.conf if you installed via aptitude, and /usr/local/nginx/conf/nginx.conf if you installed from source.

MJS commented Wed Aug 20 11:58:35 UTC 2008:

Victor...

I'm not sure what you're doing. Rails should be installed as a gem, are you saying you have a copy at /var/www/SITENAME.com/rails/ ?

If you've frozen the version of Rails you are using it should be in yourapp/vendor/rails folder.

Unless I misunderstand what you've done...

Rafael commented Tue Sep 02 18:18:05 UTC 2008:

Victor,

I was having the same Errno::ENOENT error. You said: "made sure that the ruby on rails application has all the gems and packages that it needs". What gems did you update?

Jivko commented Thu Oct 09 11:19:45 UTC 2008:

Great !!! Work fine with 2 clusters with 3 thin servers and apache for proxy.

Dave commented Tue Oct 05 20:15:15 UTC 2010:

Can someone please help me with monitoring this thin cluster with monit? This is what I have so far: thin.monitrc: check process thin0 with pidfile tmp/pid/thin.3000.pid start program = "/etc/init.d/thin start" stop program = "/etc/init.d/thin stop" if totalmem > 50.0 MB for 5 cycles then restart if failed port 3000 then restart if cpu usage > 95% for 3 cycles then restart if 5 restarts within 5 cycles then timeout group thin But it doesn't seem to work.

John commented Mon Dec 12 19:35:02 UTC 2011:

Great article! Thanks for taking the time to put this together. However, i'm stuck. In the runlevels section do you mean to put this "sudo thin install" into a script inside /etc/init.d/thin?

I did exactly that, then followed the rest of the steps, but when i restarted my server thin never booted up. Could i be possibly missing something?

Thanks, John

Jered commented Fri Dec 16 03:09:07 UTC 2011:

Actually, it means to run "sudo thin install" from the command line. That should add an init script for thin to /etc/init.d. After that the update-rc.d command will tell the system to enable the thin init script.

Swasher commented Sat Mar 23 11:02:24 UTC 2013:

Hello, is it possible to make thin server password protected? I'm run Visage (collectd web interface) on thin.

senluo commented Wed Jul 10 05:30:33 UTC 2013:

I had do with the tutorial,when" thin start -C /etc/thin/redmine.ym" it occured a waring is Insecure world writable dir /usr/local in PATH , mode 040777; and in the logs like this

Writing PID to tmp/pids/thin.3000.pid No adapter found for /opt/bitnami/apps/redmine Exiting!

can you give me a help Thanks!

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)