SkillAgentSearch skills...

Milia

Easy multi-tenanting for Rails5 (or Rails4) + Devise

Install / Use

/learn @jekuno/Milia
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Build Status Dependency Status

milia

Milia is a multi-tenanting gem for Ruby on Rails applications. Milia supports Devise.

You are viewing the documentation for using milia with Rails 5.x applications.
If you want to use Rails 4.2.x instead please switch to the Rails 4.x branch.

<!-- START doctoc generated TOC please keep comment here to allow auto update --> <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->

Intro

  • Milia is a solid choice for (SaaS) applications which are used by more than one tenant (i.e. companies or organizations) and is tailored for common use cases of multi-tenanted applications.
  • Milia allows to save the data of all tenants in the same database and enforces row based separation of the tenant data.
  • Milia uses the devise gem for user authentication and registration.

Milia highlights

  • Transparent to the main application code
  • Symbiotic with user authentication (supports devise out of the box)
  • Raises exceptions upon attempted illegal access
  • Enforces tenanting (not allow sloppy access to all tenant records)
  • Allows application flexibility upon new tenant sign-up, usage of eula information, etc
  • As non-invasive (as possible) to Rails code
  • Uses row-based tenanting (for good reasons)
  • Uses default_scope to enforce tenanting
  • See Milia in action in the Sample App

Basic concepts

Tenants == Organizations with Users / Members

A tenant is an organization with many members (users). Initially a user creates a new organization (tenant) and becomes its first member (and usually admin). Then he invites further members who can then login and join the tenant. Milia ensures that users can only access data of their own tenant (organization).

Tenanted models

Models which belong to a certain tenant (organization).
Add <i>acts_as_tenant</i> to the model body to activate tenanting for this model.
Most of your tables (except for pure join tables, users, and tenants) should be tenanted. Every record of a tenanted table needs to have a tenant_id set. Milia takes care of this.

Universal models

Models which aren't specific to a tenant (organization) but have system wide relevance. Add <i>acts_as_universal</i> to the model body to mark them as universal models.
Universal tables <i>never</i> contain critical user/company information. The devise user table <i>must</i> be universal and should only contain email, encrypted password, and devise-required data. All other user data (name, phone, address, etc) should be broken out into a tenanted table called members (Member belongs_to :user, User has_one :member). The same applies for organization (account or company) information. A record of a universal table must have tenant_id set to nil. Milia takes care of this.

Join tables

Pure join tables (has_and_belongs_to_many HABTM associations) are neither Universal nor Tenanted.

Tutorials + Documentation

  • Up to date starting point is the README you're currently viewing.
  • For more details on token authentication, exceptions, callbacks, devise setup etc. have a look at the additional README_DETAILS.
  • Tutorial: There's a good Milia tutorial at myrailscraft.
  • Check out the general three-part blog post about Multi-tenanting Ruby on Rails Applications on Heroku.

Sample app

You can get a sample app up and running yourself using an easy, interactive RailsApp generator and an according Milia generator. If desired the generator can also prepare everything for you to push your app to Heroku. The sample app uses devise with the invite_member capability (and optionally recaptcha for new account sign-ups). It creates skeleton user, tenant and member models.

Simply follow the following steps:

mkdir milia-sample-app
cd milia-sample-app
rvm use ruby-2.3.1@milia-sample-app --ruby-version --create
gem install rails
rails new . -m https://raw.github.com/RailsApps/rails-composer/master/composer.rb

An interactive setup starts which asks you some questions.

  • Choose "Build a RailsApps example application"
  • Choose "rails-devise" as the example template
  • Choose Template engine "HAML"
  • Choose "Devise with default modules"
  • Choose the other options depending on your needs

After the setup finished add to your Gemfile:
gem 'milia'

Install milia: bundle install

In app/controllers/application_controller.rb add the following line immediately after protect_from_forgery:
before_action :authenticate_tenant!

Run the following commands:

spring stop
rails g milia:install --org_email='mail@your-provider.de' --skip_devise_generators=true
  • Remove lower line "before_action :authenticate_tenant!" which has been added to app/controllers/application_controller.rb by the milia generator.
  • Remove the lines @extend .text-xs-center; (if any) from the file 1st_load_framework.css.scss.
  • Remove the file app/views/devise/registrations/new.html.erb

Setup the database: rake db:drop db:create db:migrate

Start the server: rails server

Open http://127.0.0.1:3000/users/sign_up in your browser. You're ready to go!

Previous sample app

For your reference: An outdated milia+devise sample app can be found at https://github.com/dsaronin/sample-milia-app and is live on Heroku: http://sample-milia.herokuapp.com
The according instructions on how to generate this sample app can be found at doc/sample.sh.

There are also outdated step-by-step instructions for setting this sample app up manually at doc/manual_sample.sh.

  • Step 1: Sample with simple devise only
  • Step 2: Add milia for complete tenanting
  • Step 3: Add invite_member capability

Installation

Adding milia to a new application

The quickest way: Follow the simple instructions of the chapter Sample App to generate a new app which uses devise+milia.

Add milia to an existing application

The recommended way to add multi-tenanting with milia to an existing app is to bring up the Sample App, get it working and then graft your app onto it. This ensures that the Rails+Devise setup works correctly.

Go step by Step

Don't try to change everything at once! Don't be a perfectionist and try to bring up a fully written app at once!

Just follow the instructions for creating the sample, exactly, step-by-step. Get the basics working. Then change, adapt, and spice to taste.

Bare minimal manual setup

(If you generated a [Sample App](Sample App) all of the following steps have been done already.)

Add to your Gemfile:

  gem 'milia', '~>1.3'

Then run the milia generator:

  $ bundle install
  $ rails g milia:install --org_email='<your smtp email for dev work>'

Note: The milia generator has an option to specify an email address to be used for sending emails for confirmation and account activation.

For an in depth explanation of what the generator does have a look at README_DETAILS.

Make any changes required to the generated migrations, then:

  $ rake db:create
  $ rake db:migrate

Application controller

<i>app/controllers/application_controller.rb</i> add the following line IMMEDIATELY AFTER line 4 protect_from_forgery

  before_action :authenticate_tenant!   # authenticate user and sets up tenant

  rescue_from ::Milia::Control::MaxTenantExceeded,   :with => :max_tenants
  rescue_from ::Milia::Control

Related Skills

View on GitHub
GitHub Stars339
CategoryDevelopment
Updated2mo ago
Forks65

Languages

Ruby

Security Score

100/100

Audited on Jan 23, 2026

No findings