Multi Subdomain Rails 5 App

I am involved building a SaaS application for Brevica, a US based firm, an app called Church Foyer. Last week I was implementing subdomain based multi-tenancy. For example, you can create a tenant with your own personalized subdomain. That is a cool feature, but I will talk about that later. I am going to pull an example from my personal website.

Here I am going to show you how you can create a single app that has multiple sub-domains. For example:

I recommend breaking down a large app to smaller, more manageable apps. But if that is not your interest, this is how you are going to do it. Here I will present you…

Step 1: Subdomain Session management

We don’t want our users to login to every single subdomain our app has, agreed? Then we need to configure Rails session store allow this. You can do some thing going in line with…

Rails.application.config.session_store :cookie_store,
                                       key: '_jdeencom_session',
                                       domain: {
                                         production: '.jdeen.com',
                                         development: '.jdeen.dev'
                                       }.fetch(Rails.env.to_sym, :all)

This will allow sessions created in, lets say www.jdeen.com, be available in, blog.jdeen.com, should the user need to comment on a blog post.

Step 2: Routes and Routing Constraints

Next you will need to define routes that have constraints constraints. This constraints should be in the subdomain level. For example we will need to redirect the request to / when the request is for example blog.example.com to blog#index action.

Rails.application.routes.draw do
  # ...
  constraints JDeen::Constraints::Blog do
    root 'blog#index'
  end
  # ...
end
# JDeen website main namespace
module JDeen 
  # Routing constraints
  module Constraints
    # Constraints for the blog subdomain
    class Blog
      # Checks if a request to the Rails app matches the blog
      def self.matches?(request)
        request.subdomain.present? && request.subdomain == 'blog'
      end
    end
  end
end

Step 3: Nginx config

The next is, we would need minor changes to a general Nginx config file. Just notice the * in front of the server name below.

cat /etc/nginx/sites-enabled/jdeen.dev
server {
  listen 80;
  server_name jdeen.dev;
  return 301 $scheme://www.jdeen.dev$request_uri;
}

upstream jdeendev {
    server localhost:3500 max_fails=3 fail_timeout=30;
}


server {
    listen 80;
    server_name *.jdeen.dev;

    root /home/ziyan/Work/JDeen/JDeen;

    try_files $uri/index.html $uri @jdeendev;

    location @jdeendev {
        proxy_pass http://jdeendev;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

Thats it and you should be good to go! Unless I missed some thing :relaxed: