organized flames

Fun With Apache and Virtual Hosts

Posted on October 31, 2007 by Michael

Specifically, name based virtual hosts.

I recently tried to add IPv6 support to my web server. I used to have it, I remember having it, so this should not be all that hard.

After an hour of hacking, I ended up finding two gotchas:

  • Make certain, I mean certain, that all virtual hosts for name-based servers have a unique ServerName line.
  • Make certain, and I mean certain, to save your original configuration files.

Yea, I know, I should have known better. But this is a simple thing to change, right?

A very useful tool is apachectl -S, which lists all virtual hosts. Even better is to run that output through sort

Simple Rails Caching

Posted on October 28, 2007 by Michael

In my apache configuration I have Apache serving static pages from the public directory. After playing around with Mephisto a bit, I’ve learned a few tricks on caching.

The common belief is to use memcache for caching on sites that are large enough to need it. However, I think with a few tricks, I can do better. I think in some cases, letting Apache serve the content is a far wiser move.

For example, I will begin writing out the images for avatars on guildcorner.org to files, and let Apache serve them. I will do this when they are created, updated, or rendered to a browser. This will let Apache serve the next request for it. I also plan on deleting the cache file if the avatar is deleted.

Since I use Capistrano to push out releases now, and the cached files are not in subversion, upgrading to a new application version won’t require anything special.

Mongrel, Apache, and Rails

Posted on October 28, 2007 by Michael

When I first started running Rails applications on my web server, I chose to use FastCGI. Specifically, the mod_fcgid module, which had some features I wanted. It also has the unfortunate by-product of corrupting Apache’s memory. Bad news.

I’ve since removed FastCGI entirely and moved to a proxy to mongrel_cluster setup. And I’ve started deploying with Capistrano.

Capistrano

I have a certain amount of concern with moving to a deployment system I knew very little about. Just like a new backup system, I feel like I’m handing the keys to my data over to something not written by me. And, while it is fairly simple to set up, Capistrano is somewhat complicated internally.

I already push out my operating system upgrades in an automated way. I compile NetBSD on one machine here at home, and push the binaries out to all the machines I have which run NetBSD. This means about 7 machines rsync from the build box with one command. This can be scary, but I’ve been doing it for 5 years now, and it just works. How can a web site be scary compared to kernels and system binaries?

The answer is, it’s not. If something breaks it is fairly easy to manually reconfigure if I need to. So, I’ve relaxed a bit. My concerns are still there, and I’m keeping a careful watch on how Capistrano runs each time I deploy. I have yet to do a real deployment after all! So far, I’ve not done a single migration, and have not had to roll back. And I’m pushing to a single machine, which runs the database as well as the site.

I suspect that, as I become comfortable with this new method to update my web sites, I’ll start thinking of it as rsync++. It really is that simple.

mongrel_cluster

Mongrel is a vary amazing little widget. Sure, it’s slower than Apache, but that’s ok. Mongrel is still far, far faster than restarting Rails for each web hit, and far more reliable than mod_fcgid.

In my configuration, I run each site on ports 10000, 10010, 10020, etc. with up to 3 servers per. This means application #1 is on 10000 through 10002, with room to grow should I need to run more. If I find myself running more than 10 servers for a site it needs a new machine anyway, or more machines. And if that happens, I hope I’ll have a budget.

Apache load balancing

This is a new feature in Apache 2.1, and apparently is very reliable with Apache 2.2. This is currently my favorite way to run a web site.

My configuration, which happens to be for this site:

  1. <proxy balancer://blog>
  2. BalancerMember http://localhost:10010
  3. BalancerMember http://localhost:10011
  4. BalancerMember http://localhost:10012
  5. </proxy>
  6. <VirtualHost blog.flame.org:80>
  7. DocumentRoot /www/blog/flame-blog/current/public
  8. <directory "/www/blog/flame-blog/current/public">
  9. Options FollowSymLinks
  10. AllowOverride None
  11. Order allow,deny
  12. Allow from all
  13. </directory>
  14. ProxyRequests off
  15. <proxy *>
  16. order deny,allow
  17. allow from all
  18. </proxy>
  19. RewriteEngine on
  20. # Check for maintenance file. Let apache load it if it exists
  21. RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f
  22. RewriteRule . /system/maintenance.html [L]
  23. # Rewrite index to check for static
  24. RewriteRule ^/$ balancer://blog%{REQUEST_URI} [L,P,QSA]
  25. # Let apache serve static files (send everything via mod_proxy that
  26. # is *no* static file (!-f)
  27. RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
  28. RewriteRule .* balancer://blog%{REQUEST_URI} [L,P,QSA]
  29. </VirtualHost>

It is important, at least on my host, to use localhost in the balancer destinations. This is due to mongrel suddenly running on IPv6 loopback (::1) rather than the usual IPv4 loopback (127.0.0.1). I don’t know why this happened, but the localhost trick makes Apache try both addresses, and whichever works it will use.

This configuration makes Apache serve static content, and sends all other requests off to one of the Mongrel processes.

Ursae-Lyons

Posted on October 27, 2007 by Michael

Last weekend my wife and I attended a lovely little event in the Barony of Bjornsborg in the Kingdom of Ansteorra. We had a wonderful time. There was music, a bardic circle, and lots of singing (most of it good!) coming from Cynric’s tavern.

The best things to happen there, in my opinion, was that Baron Cynric of Bedwyn was awarded with the Kingdom’s highest persona award, Lions of Ansteorra, Devenders of the Dream, and his lady wife Baroness Seraphina Maslowska was awarded with a Pelican! Congratulations to both of you!

RailsMode (not ENV['production'])

Posted on October 27, 2007 by Michael

RailsMode

I’ve been spreading things like this all around my code, where I wanted to do something differently in production vs. development mode. Previously, I’d write something like this:

  1. if ENV[RAILS_ENV] == production
  2. … perform magic …
  3. end

While this is pretty simple, it just didn’t feel very DRY. So, I decided to use this as a reason to learn about modules and mixins.

I have a generic plug-in in vendor/plugins that I put small bits of code like this. You might as well, but if you don’t, you can drop this in a helper.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

module RailsMode
  def railsmode(*list)
    list.map! do |item|
      item.to_s
    end

    if block_given?
      if list.include?(ENV['RAILS_ENV'])
        yield
      end
    else
      return list.include?(ENV['RAILS_ENV'])
    end
  end
end

I also put this line in my environment.rb file:

1
2

include RailsMode

This mixes the module into the current class. Doing this in environment.rb makes it available everywhere in rails. Putting that line in a specific file would also work, such as a controller, or a helper.

With this, I can now write:

1
2
3
4

if railsmode(:production)
  ... perform magic ...
end

I can also check for multiple modes at once:

1
2
3
4

if railsmode(:production, :development)
  ... perform magic ...
end

And of course, who needs an if when I can pass in a block:

1
2
3
4

railsmode(:production) do
  ... perform magic ...
end

Well, I've done it...

Posted on October 26, 2007 by Michael

Michael, meet blog. Blog, meet Michael

I’ve gone and joined the blogging world. Sure, I could have done this years ago, back when 5 year olds didn’t post to blogs every day… but then I’d be a trend-setter.