Glenn Gillen

Letting nginx automatically detect new rails apps

Following on from my post yesterday explaining how to let god automatically detect any new rails apps is few capistrano and config tweaks. This time the changes will let nginx use the same config file we created to so that setting up a new upstream and rails config is as simple as a call to deploy:setup in capistrano.

Make sure you've setup app.god

These changes have a dependency on the changes from my previous post, so be sure to follow the steps on creating app.god to dynamically configure god for rails

Create a new nginx task for capistrano

Within your deploy.rb you want to insert this snippet:

namespace :deploy do

  after "deploy:setup", "deploy:nginx:setup" 

  namespace :nginx do
    desc 'Setup nginx upstream config'
    task :setup, :roles=>:app do
      @apps = []
      eval(open("./config/app.god").read)
      nginx_upstream_config = []
      @apps.each do |app|
        upstream_name = app.class.to_s.downcase.gsub(/.*::/,"")
        nginx_upstream_config 

I'll run through what is happening here. Within deploy:nginx:setup we first instantiate the @apps variable, so that the app.god we created previously has an instance to insert itself into. We then read in and execute app.god, which means @apps will be populated with our application now.

Now for each application (why would we have more than one? I'll explain at the end) we loop over and create an nginx upstream definition, with each of the ports specified within app.god. Next is to create the standard nginx/rails config (feel free to change to suit your own needs), push it up to the server, and then link it into /etc/nginx/application_name.conf.

Required changes in nginx

The only thing you need to do within your nginx.conf file is add the following line at the end of your http service definition:

include /etc/nginx/*.conf;

And now, when you run:

cap deploy:setup

Capistrano will not just setup the rails directory structures, but will also update the nginx config to make it aware of your new application. It also means that your application specific nginx config now resides in your rails directory structure. Should you decide to take the application off the server, the nginx config disappears when the app does.

So why do you use @apps to specify the application?

Well with the god config from the previous post, god is dealing with every rails application on the server and stores the list of them within @apps. However, with this in most cases we are only dealing with one (the app we are deploying) so it's somewhat redundant. I say in most cases because there have been times when we've deployed the same application twice on the same server, running on different ports and accessible from different URLs. This meant we could do the following in app.god:

class Rubypond

  def initialize
    @ports = [8061, 8062, 8063]
  end
end

@apps 

Next up, how to extend what we've done so far to manage backgroundrb for us too.

Glenn Gillen

I'm an advisor to, and investor in, early-stage tech startups. Beyond that I'm an incredibly fortunate husband and father. Working on a developer-facing tool or service? Thinking about starting one? Email me and let me know or come to one of our days to help make it a reality.