The Dev Blog

Putting Family Management on Rails!

How Rails Change The Backend Coding Effort

Posted by Guy Naor Sat, 11 Mar 2006 18:08:00 GMT

One thing I lately noticed, is that Ruby on Rails completely changes the work distribuition between the backend and the rest of the system.

In my past projects (C++ on Windows - see my first post), the backend took a significant amount of work just for writing and reading the objects in the databse. When you also take into account all the code needed to set up the connections, handle the associations and other related stuff and DEBUGGING you end up spending 30-40% of the time on the backend.

With rails it goes down to about 5% of the time, leaving much more time for the business logic of the application and the UI.

I just wish we had something as beuatiful and useful as rails for the UI... But hey, a man is entitled to dreams :-)

Posted in  | 2 comments | no trackbacks

del.icio.us:How Rails Change The Backend Coding Effort digg:How Rails Change The Backend Coding Effort spurl:How Rails Change The Backend Coding Effort wists:How Rails Change The Backend Coding Effort simpy:How Rails Change The Backend Coding Effort newsvine:How Rails Change The Backend Coding Effort blinklist:How Rails Change The Backend Coding Effort furl:How Rails Change The Backend Coding Effort reddit:How Rails Change The Backend Coding Effort fark:How Rails Change The Backend Coding Effort blogmarks:How Rails Change The Backend Coding Effort Y!:How Rails Change The Backend Coding Effort smarking:How Rails Change The Backend Coding Effort magnolia:How Rails Change The Backend Coding Effort segnalo:How Rails Change The Backend Coding Effort

Capistrano (aka SwitchTower) and security

Posted by Guy Naor Mon, 06 Mar 2006 12:40:00 GMT

You already know I ABSOLUTELY love Capistrano (well, I do prefer SwitchTower as a name...). I also count security as a critical component in any production system (and no, having a firewall doesn't count as security). So to make sure I can comfortably use it in production, I had to make some security adjustment on the machines I deploy to.

Some important requirments:

  1. The web server should only have read access to the absolute minimum it really needs. In my case, as I'm using FastCGI processes launched from outside the server, only the public directory needs to be readable by it.
  2. The deployment user (set :user "deployer" in deploy.rb) should be a distinct user and should be the only one with write privileges to the rails application directory.
  3. The rails application runner will be itself a distinct user with only read access to the rails application.
  4. All other users can't even read the deployment directories.
  5. The deployment user can run as root using sudo only the minimum number of things like restarting the web server, or changing configuration.

To satisfy those requirement I created 2 users - one to deploy and one to run the rails application. I then set the privileges on the files (using chmod) so that the runner can read everything in the rails app directories and write just to the log directory. And the web server can read only the public directory. Then I edited the sudoers file (use visudo and direct editing to catch syntax errors) and allowed the deployment user rights to launch/stop/reload the web server, and to copy some configuration files. Note that it can't write to the files. It can just copy them from one specific location to another. It's risky letting someone to sudo run shell scripts, as then they can do anything like root. Here's a piece of my sudoers file:

Cmnd_Alias      CP_LIGHTY_CONF = \
    /bin/cp  /etc/lighthttpd/maintenance.conf /etc/lighttpd/lighttpd.conf, \
    /bin/cp /etc/lighttpd/application.conf /etc/lighttpd/lighttpd.conf, \
    /etc/init.d/lighttpd

deployer    localhost = CP_LIGHTY_CONF

This gives the deployer user the rights to copy the config files around, but not to ever write to them. So that the admin on the box set them as needed, but the deployer can change them as needed.

Please note that this is only one layer of the security. Just like the firewall is just a single layer. When planning a deployment, think of security as a layered mechanism, adding more and more layers (firewalls, host firewalls, privileges, monitoring, IDS, SELinux, etc...).

Posted in ,  | no comments | no trackbacks

del.icio.us:Capistrano (aka SwitchTower) and security digg:Capistrano (aka SwitchTower) and security spurl:Capistrano (aka SwitchTower) and security wists:Capistrano (aka SwitchTower) and security simpy:Capistrano (aka SwitchTower) and security newsvine:Capistrano (aka SwitchTower) and security blinklist:Capistrano (aka SwitchTower) and security furl:Capistrano (aka SwitchTower) and security reddit:Capistrano (aka SwitchTower) and security fark:Capistrano (aka SwitchTower) and security blogmarks:Capistrano (aka SwitchTower) and security Y!:Capistrano (aka SwitchTower) and security smarking:Capistrano (aka SwitchTower) and security magnolia:Capistrano (aka SwitchTower) and security segnalo:Capistrano (aka SwitchTower) and security

Improving the rails spawner script

Posted by Guy Naor Sun, 05 Mar 2006 06:51:00 GMT

The spawner script in rails is pretty cool in that it will keep looking out for the FastCGI processes and make sure they are all working.

What I don't like about it, is that it launches the dispatcher again and again, letting it fail when the socket is already open. This is doing the unnecessary and puts more load on the system. But most of all it's just ugly!

As we're in a ruby script anyway, why not use it to see if the socket is in use before we launch the dispatcher? The only thing that needs to be changed is the spawn method (and you need to add a require 'socket' at the top of the script). We try to open a listening socket on the port we're being passed. If it opens, it means no process is listening on it and we can launch the dispatcher. If it is in use, an exception will be raised, and we just catch it, print a YES, and we're done.

def spawn(port)
  print "Checking if something is already running on port #{port}..."
  begin
    srv = TCPServer.new('0.0.0.0', port)
    srv.close
    srv = nil
    print "NO\n "
    print "Starting FCGI on port: #{port}\n  "
    system("#{OPTIONS[:spawner]} -f #{OPTIONS[:dispatcher]} -p #{port}")
  rescue
    print "YES\n"
  end
end

Now it will not even get to the dispatcher if the socket is already in use.

Posted in ,  | 2 comments | no trackbacks

del.icio.us:Improving the rails spawner script digg:Improving the rails spawner script spurl:Improving the rails spawner script wists:Improving the rails spawner script simpy:Improving the rails spawner script newsvine:Improving the rails spawner script blinklist:Improving the rails spawner script furl:Improving the rails spawner script reddit:Improving the rails spawner script fark:Improving the rails spawner script blogmarks:Improving the rails spawner script Y!:Improving the rails spawner script smarking:Improving the rails spawner script magnolia:Improving the rails spawner script segnalo:Improving the rails spawner script

Using SwitchTower with an ssh forwarding firewall

Posted by Guy Naor Sat, 04 Mar 2006 00:59:00 GMT

I really like switchtower and the ease it brings to rails deployment. Suddenly deployment is just as easy as rails development. This is especially true for the multi-server deployment I'm working on.

But there was one small problem. My firewall doesn't give ANY direct access to the internal machines. All connections are NATed into the internal machines. This includes even ssh connections, which are NATed from different ports into different machines. So to the outside they all look like the same server (for example deploy.famundo.com), but a collection of ports redirect ssh connections to specific internal machines. For example: deploy.famundo.com:22222 => app1:22, deploy.famundo.com:22223 => web1:22. This clashes with the way switchtower works, as it expects ssh to be running on one specific port. Even using the ssh_options[:port] in deploy.rb will use the same port for all servers.

To solve this, I added support in switchtower for assigning an optional specific port to each server. If non is given, the default will be used. Assigning different ports is very easy:

role :db, "app1" # Will use port 22
role :app, "deploy.famundo.com:2224"
role :web, "deploy.famundo.com:2223"

The change is a simple addition to switchtower/lib/switchtower/ssh.rb (in svn diff format):

--- ssh.rb      (revision 3755)
+++ ssh.rb      (working copy)
@@ -23,6 +23,11 @@
       methods = [ %w(publickey hostbased), %w(password keyboard-interactive) ]
       password_value = nil

+      # If the server has a port assigned to it (www.sample.com:2222), use it, and clean the server name
+      if server =~ /(.+):(\d{1,5})/
+        server, port  = $1, $2
+      end
+
       begin
         ssh_options = { :username => config.user,
                         :password => password_value,

Now I can use switchtower, and still keep my firewall setup! Sweet!

I'll post a ticket with this patch to the rail trac.

Posted in  | no comments | no trackbacks

del.icio.us:Using SwitchTower with an ssh forwarding firewall digg:Using SwitchTower with an ssh forwarding firewall spurl:Using SwitchTower with an ssh forwarding firewall wists:Using SwitchTower with an ssh forwarding firewall simpy:Using SwitchTower with an ssh forwarding firewall newsvine:Using SwitchTower with an ssh forwarding firewall blinklist:Using SwitchTower with an ssh forwarding firewall furl:Using SwitchTower with an ssh forwarding firewall reddit:Using SwitchTower with an ssh forwarding firewall fark:Using SwitchTower with an ssh forwarding firewall blogmarks:Using SwitchTower with an ssh forwarding firewall Y!:Using SwitchTower with an ssh forwarding firewall smarking:Using SwitchTower with an ssh forwarding firewall magnolia:Using SwitchTower with an ssh forwarding firewall segnalo:Using SwitchTower with an ssh forwarding firewall

Modules and Routes

Posted by Guy Naor Wed, 01 Feb 2006 00:19:00 GMT

Here's a little something for rails novices. Might save you some time and pain.

I wanted nice URLs for my application, and one of the important parts was really short URLs for the main parts of the application. So you can do: http://www.famundo.com/library and get to the library module. Or http://www.famundo.com/photos to get to the library/photos area of the application. That's easy with routes. In routes.rb I just had to add entries like:

map.connect 'library'  , :controller => 'library_center', :action => 'show'
map.connect 'photos'   , :controller => 'my_pictures', :action => 'show'
map.connect 'blog'     , :controller => 'personal_blogs', :action => 'show'

But my system has a further complication. I use modules to separate the different parts of the application, so that everything is nicely organized in development. So for my maps I used:

map.connect 'library'  , :controller => 'library/library_center', :action => 'show'
map.connect 'photos'   , :controller => 'library/my_pictures', :action => 'show'
map.connect 'blog'     , :controller => 'library/personal_blogs', :action => 'show'

At first it seemed to work fine, but when I got deeper in to the controllers actions, the resulting URLs where all messed up. After some work and some help on the list, the solution was VERY simple. I was missing an initial slash in my routes! When referencing the controller inside the module, I needed to add a leading slash. So that the routes are now working with:

map.connect 'library'  , :controller => '/library/library_center', :action => 'show'
map.connect 'photos'   , :controller => '/library/my_pictures', :action => 'show'
map.connect 'blog'     , :controller => '/library/personal_blogs', :action => 'show'

Ah, what a small {color:red}/ can do!

Posted in  | no comments | no trackbacks

del.icio.us:Modules and Routes digg:Modules and Routes spurl:Modules and Routes wists:Modules and Routes simpy:Modules and Routes newsvine:Modules and Routes blinklist:Modules and Routes furl:Modules and Routes reddit:Modules and Routes fark:Modules and Routes blogmarks:Modules and Routes Y!:Modules and Routes smarking:Modules and Routes magnolia:Modules and Routes segnalo:Modules and Routes

And So It Starts

Posted by Guy Naor Sat, 28 Jan 2006 20:44:00 GMT

It wasn't too long ago that my main development language was C++ on Windows. But when I decided I want to do web development, this just plain didn't make sense. Enter Ruby and Rails!

I was on a search for a good web development environment, and looked at many of the options available, but none seemed to meet my requirements. Java was too heavy (I did do Java development in the past, but that was long ago), I didn't like the then available Python stacks and I really dislike all the .NET stuff. Call it too many years on Windows, or a dislike to proprietary systems, but I just won't touch it.

While searching, I stumbled upon RubyOnRails. I was weary of all the promises I read about it, but playing with it a bit proved me wrong. What a refreshing surprise!!!

Then came the need to do a 180 degree turn in my head. From the strict mindset of C++ to the "crazy" way Ruby and the other dynamic languages do things. I had no prior Ruby experience, so it required lots of learning. Luckily I had lots of experience with Linux and all related technologies, so this part was taken care of.

A few weeks after starting learning, I switched my dev environment from Visual Studio on Windows to Eclipse on Fedora Core 4 (past experience with RedHat made it my choice), and I can't be happier :-).

Some dev choices I have made so far:

  • OS - Linux FC4
  • IDE - Eclipse with RadRails
  • Source control - Subversion
  • Database - PostgreSQL

Come visit this blog for some development ideas and solutions related to my new development journey. And for details as I take an amazing new application online.

Posted in , , ,  | no comments | no trackbacks

del.icio.us:And So It Starts digg:And So It Starts spurl:And So It Starts wists:And So It Starts simpy:And So It Starts newsvine:And So It Starts blinklist:And So It Starts furl:And So It Starts reddit:And So It Starts fark:And So It Starts blogmarks:And So It Starts Y!:And So It Starts smarking:And So It Starts magnolia:And So It Starts segnalo:And So It Starts

Older posts: 1 ... 4 5 6

Subscribe to The Dev Blog