Installation Continued…

RubyWorks comes with ready-made configuration for all packages included in the stack. We don’t change configuration of anything else on your system during the installation process (there is one exception: we add a line for runit to /etc/inittab). You probably don’t want us to automatically punch holes in your firewall, anyway. So, we don’t.

Besides, our ready-made configuration is not a One Size Fits All affair. It’s just a starting point. The idea is to begin with something that works, change it in small steps, make sure that it still works after each step, and keep going until you have a setup that suites your needs, personal taste and data center conventions.

Even if you don’t need to change anything, you are encouraged to read through this page at least once, when getting started with the stack. You’ll learn something useful.

Open up to incoming HTTP traffic

Once you install RubyWorks, a skeleton Rails app should be accessible as http://localhost:3001. Of course, your production servers probably have something to block external traffic on random ports, so if you try to access it from another computer, it will not work. Fixing this is the first thing to do.

Opening port 3001 to network

The program serving those HTTP requests on port 3001 is called HAProxy. It is a general-purpose proxy that plays the role of software load balancer in the RubyWorks stack. If you want it to be accessible from outside, simply allow external TCP connections to port 3001. This usually involves system-config-securitylevel-tui (Redhat and CentOS) or iptables (Debian/Ubuntu).

HAProxy on port 80

The simplest way to respond on the standard HTTP port 80, instead of a non-standard 3001, is to make HAProxy do it. First of all, make sure that nothing is bound to that port already:

> telnet localhost 80
Trying 127.0.0.1...
telnet: Unable to connect to remote host: Connection refused

If something does accept a connection, you have to find and uninstall that something. More likely than not, it will be an httpd process, otherwise known as Apache Web Server.

Configuration of HAProxy is in a file called /etc/rails/haproxy.conf. Find a line there that says

listen rails :3001

and replace it with

listen rails :80

then restart HAProxy:

sudo /usr/sbin/sv restart haproxy

Note that on some systems (e.g., Ubuntu) port 80 is blocked by default. You’ll have to reconfigure whatever blocks it (typically, iptables or SELinux).

HAProxy behind a web server

HAProxy can serve requests from browsers directly, however it doesn’t have features, flexibility or security controls of a real web server (Apache and Nginx are two popular options in the Rails world). Besides, if your Rails app has to serve a lot of static content, you can do it much better with a web server (typical difference on commodity hardware is 700 static hits/sec with HAProxy->Mongrel vs 4000 static hits/sec with Apache).

There are many ways to tweak this configuration, but the simplest is a virtual host like this (Apache):

  <VirtualHost *:80>
    ServerName myapp.com
    ServerAlias www.myapp.com

    ProxyPass / http://127.0.0.1:3001/
    ProxyPassReverse / http://127.0.0.1:3001
    ProxyPreserveHost on
  </VirtualHost>

If Apache is running on a different computer, replace 127.0.0.1 with the network name or IP address of your Rails application server, and open port 3001 to external traffic, as described above.

There is a lot more about configuring Apache to serve Rails apps in Mongrel documentation. Remember that we alredy have a load-balancer in RubyWorks stack (HAProxy), so you should not use mod_proxy_balancer, just simple mod_proxy. As a bonus, since you don’t need mod_proxy_balancer, you don’t need Apache 2.1+. Whatever version comes with your Linux distro is good enough.

HAProxy logs

HAProxy logs to a syslog facility local0, via a socket connection. By default, your syslog configuration probably doesn’t accept socket connections, and doesn’t have a local0 facility, so you have no HAProxy log. If you want it, configure syslog to accept TCP connections by adding -r to syslogd parameters.

Then set up syslog facility local0 and direct it to file /var/log/haproxy.log by adding this line to /etc/syslog.conf:

local0.* /var/log/haproxy.log

Restart syslog service:

service syslog restart

Now, hit http://localhost:3001 with a browser, and tail /var/log/haproxy.log. You should see a number of entries like this:

  Jun 14 23:16:26 localhost haproxy[17469]: 127.0.0.1:38781 [14/Jun/2007:23:16:26] rails rails-1 2/0/1/12/18 200 7749 - - ---- 0/0/0 0/0 "GET / HTTP/1.1"

Changing log destination

If your system configuration has multiple RubyWorks instances, it’s a good idea to direct all HAProxy logging to a central syslog server. To send HAProxy logs to haproxylog facility on logjam server, find this line in /etc/rails/haproxy.conf:

log 127.0.0.1 local0

and replace it with

log logjam haproxylog

Securing Monit console

Monit is a lightweight monitoring tool. RubyWorks stack uses it to make sure that all processes in the stack are healthy. If a process starts using too much CPU, or leaks memory, it is Monit’s job to detect it, alert the sysadmin, and restart the process if necessary.

Monit has a web console on port 2812. Since that console can be used to start and stop services, you probably want to have access to it from another computer, but you definitely don’t want too many people to have the same ability. Default configuration of monit only accepts connections from localhost, with user/password admin/MonitPa$$w0rd (basic HTTP authentication).

Bind monit’s web frontend to all network interfaces, and change user/password by editing /etc/rails/monit.conf according to the comments in that file. Look for these lines:
use address 127.0.0.1
allow admin, MonitPa$$w0rd

and replace them with something like this:

use address 0.0.0.0
allow admin, [your own password]
Now, if you think “hmm, basic HTTP auth is not terribly secure”, that is correct. The password is sent across the network in plain text. Consider tightening it up further by turning on HTTPS. Create (or obtain a trusted) SSL certificate, and put it into /etc/rails/monit.pem. Then, find the line in /etc/rails/monit.conf that says

set httpd port 2812 and

and add the following after it:

ssl enable
pemfile /etc/rails/monit.pem

If you do that, you must use https://localhost:2812 to connect to Monit. Note: it’s https://, not http://, if you just see an empty page, it means you forgot about it.

(Also refer to this documentation: How to use monit with ssl .)

Email alerts

As we mentioned before, Monit makes sure that all processes in the stack are healthy. You may want to get an alert via email if there’s something wrong. Monit can do that for you.

We left a piece of configuration commented out in /etc/rails/monit.conf. It could be a good start point to setup your mail notification:

    # set mailserver mail.bar.com                # your SMTP server
    # set alert admin@bar.com                    # who's supposed to be notified
    # mail-format {                            # content of alert mail
    #    from: rubyworks@rubyforge.org
    #    subject: $SERVICE $EVENT at $DATE
    #    message: Monit $ACTION $SERVICE at $DATE on $HOST,
    #
    #    Yours sincerely,
    #    RubyWorks.
    # }

There are some macros you can use in mail-format section. Refer to Monit’s manual for more details.