Saturday, August 15, 2009

Moving Past Beta

‹prev | My Chain | next›

I got the beta site up and running yesterday. Since then, it has worked just fine, thank you very much. It is still running right now. Why am I a bit defensive? Well, because I started it in non-daemon mode. It is still running in one of my GNU screen windows.

That's fine for development mode, borderline OK for a limited beta, but is completely unacceptable for a production system. A good start would be to start the server as a daemon:
$ thin -d -R start
That might be OK for one time, but I would have to remember to do that each time I restart the system—not so OK.

The answer to that is, of course, an init.d script. Happily, I do not have to roll my own with thin:
sh-3.2$ sudo /var/lib/gems/1.8/bin/thin install
>> Installing thin service at /etc/init.d/thin ...
mkdir -p /etc/init.d
writing /etc/init.d/thin
chmod +x /etc/init.d/thin
mkdir -p /etc/thin

To configure thin to start at system boot:
on RedHat like systems:
sudo /sbin/chkconfig --level 345 thin on
on Debian-like systems (Ubuntu):
sudo /usr/sbin/update-rc.d -f thin defaults
on Gentoo:
sudo rc-update add thin default

Then put your config files in /etc/thin
Hmmm... Not only am I running on a Debian-like system, I am running on Debian itself, so:
sh-3.2$ sudo /usr/sbin/update-rc.d -f thin defaults
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
I will run the application out of /var/www rather than my home directory:
sh-3.2$ sudo mkdir /var/www
sh-3.2$ cd /var/www
sh-3.2$ sudo chown www-data:www-data .
sh-3.2$ cd /var/www/
sh-3.2$ sudo cp -r /home/cstrom/repos/eee-code .
sh-3.2$ sudo mkdir log
sh-3.2$ sudo chown -R www-data:www-data .
With the app in place, I can edit my /etc/thin/eee.yml file to contain:
user: www-data
group: www-data
pid: log/
log: log/thin.log
timeout: 60
port: 4567
chdir: /var/www/eee-code
environment: production
daemonize: true
I did try running directly from port 80 at first, but found this in the log:
/var/lib/gems/1.8/gems/eventmachine-0.12.8/lib/eventmachine.rb:565:in `start_tcp_server': no acceptor (RuntimeError)
from /var/lib/gems/1.8/gems/eventmachine-0.12.8/lib/eventmachine.rb:565:in `start_server'
from /var/lib/gems/1.8/gems/thin-1.2.2/lib/thin/backends/tcp_server.rb:16:in `connect'
from /var/lib/gems/1.8/gems/thin-1.2.2/lib/thin/backends/base.rb:49:in `start'
sh-3.2$ sudo apt-get install nginx
To get nginx to reverse proxy to my thin server running on port 4567, I need a sites-enabled file along the lines of:
# vi /etc/nginx/sites-enabled/ 
upstream beta_eeecooks_com {

server {
listen 80;
access_log /var/www/eee-code/log/logfile.log;

location / {
proxy_pass http://beta_eeecooks_com;

The upstream server is running on the localhost at port 4567. I nickname it as "beta_eeecooks_com". The server then proxy_passes everything to that server. Easy enough (after 10 minutes of wondering why it wasn't working only to discover I had created that configuration in the sites-available directory, not the sites-enabled directory!).

With that, I am assured that my server(s) will start whenever there is a reboot. I could use a way to check that it keeps running after start, but that will have to wait until tomorrow.

Before calling it a day, I note with some amount of sadness that someone tried to send email feedback today. The sadness is not because I do not desire feedback, quite the opposite. The sadness is due to the loss of the feedback. From my logs:
Errno::ECONNREFUSED - Connection refused - connect(2):
/usr/lib/ruby/1.8/net/smtp.rb:551:in `initialize'
/usr/lib/ruby/1.8/net/smtp.rb:551:in `open'
/usr/lib/ruby/1.8/net/smtp.rb:551:in `do_start'
/usr/lib/ruby/1.8/timeout.rb:62:in `timeout'
/usr/lib/ruby/1.8/timeout.rb:93:in `timeout'
/usr/lib/ruby/1.8/net/smtp.rb:551:in `do_start'
/usr/lib/ruby/1.8/net/smtp.rb:531:in `start'
eee.rb:188:in `POST /email'
eee.rb:178Errno::ECONNREFUSED: Connection refused - connect(2)
/usr/lib/ruby/1.8/net/smtp.rb:551:in `initialize'
/usr/lib/ruby/1.8/net/smtp.rb:551:in `open'
/usr/lib/ruby/1.8/net/smtp.rb:551:in `do_start'
/usr/lib/ruby/1.8/timeout.rb:62:in `timeout'
/usr/lib/ruby/1.8/timeout.rb:93:in `timeout'
/usr/lib/ruby/1.8/net/smtp.rb:551:in `do_start'
/usr/lib/ruby/1.8/net/smtp.rb:531:in `start'
/var/lib/gems/1.8/gems/pony-0.3/lib/pony.rb:67:in `transport_via_smtp'
/var/lib/gems/1.8/gems/pony-0.3/lib/pony.rb:42:in `transport'
/var/lib/gems/1.8/gems/pony-0.3/lib/pony.rb:15:in `mail'
eee.rb:188:in `POST /email'
Dang! No email server. It is late and I do not want the hassle of setting up a full-blown mail server, so I:
sudo apt-get install ssmtp
That installs a simple sendmail replacement. After setting the mailhub option in /etc/ssmtp/ssmtp.conf, I can now receive emails from the site and actually send them onto myself: - - [16/Aug/2009 02:47:00] "POST /email HTTP/1.0" 200 1076 6.1352 - - [16/Aug/2009 02:47:00] "GET /stylesheets/style.css HTTP/1.0" 304 - 0.0010 - - [16/Aug/2009 02:47:00] "GET /images/eee_corner.png HTTP/1.0" 304 - 0.0009
Apologies to anyone that tried to provide feedback today. Resending will work now!


  1. If you don't use haproxy or the nginx fair proxy balancing module/patch, won't you run the chance of getting requests hung up on a busy thin processes?

  2. Good point.

    The legacy rails app is a single mongrel instance, so I got stuck in that mentality. With an entire xen instance at my disposal, there is no need to be so limited...

  3. Great work!
    I'll read your entire journey on holidays =).

    Only one thing, why don't use nginx+passenger for production?


  4. I am ashamed to be the drowning newbie squalling for free handouts, but can you please elaborate on how you configured the mailhub option in /etc/ssmtp/ssmtp.conf?

    I am trying to make a simple contact form on a site made with Sinatra. I've installed pony and ssmtp, did no configuration, and am getting a Rack::Lint::LintError.

    Thank you!