Ruby on Rails

Please begin with the PostgreSQL installation

Quick start for a production system

apt-get install ruby rubygems build-essential ruby-dev rake
gem install bundler

More information on Bundler

apt-get install git
git clone
useradd -s /bin/bash -m webapp
rsync -av --exclude '.git/*' OSTel /home/webapp/
chown -R webapp:webapp /home/webapp/OSTel/
su - webapp
cd OSTel
bundle install --path vendor/bundle --without development
su - postgres
createuser -d -E -P -e ruby_on_rails_username (after hitting enter, pick a random long password, you never have to type this by hand, it goes in your config/database.yml )

You will be asked two questions, 'Shall the new role be a superuser?' and 'Shall the new role be allowed to create more new roles?' .. the answer to both is no

As the user you picked above , edit OSTel/config/database.yml with your connection information, this will vary on your configuration
The relevant part of your config file will typically yours will end up looking something like this:

  adapter: postgresql
  encoding: unicode
  database: production
  username: username_you_chose
  password: password_you_chose
  pool: 5
  timeout: 5000

More information about Rails

su - webapp
echo "PATH=$PATH:$HOME/OSTel/vendor/bundle/ruby/1.9.1/bin" >> ~/.profile
echo "export RAILS_ENV=production" >> ~/.profile
source .profile
cd OSTel
export RAILS_ENV=production
rake db:create
rake db:migrate
bundle exec rails server --env production

You should now have an application server running on your IP address at port 3000. For a high performance web server on a production system, refer to the Unicorn and nginx pages.


Ruby on Rails does not make it simple to edit the default logging configuration. To disable IP address logging differs by Rails version. I took the hacker way out after days of debugging. Issue #1164

Here are links to stories about later versions of Rails. As of Rails 4.0, logging is a proper configuration option and does not require patching source code.

SIP domain and outgoing email

The front end application depends on email to send user registration notifications. This is configured in /home/webapp/OSTel/config/initializers/smtp_settings.rb
The quick start for email is to use gmail , though this does not scale and will break your application when you reach the gmail SMTP quota . Sendgrid and Mailgun are two commercial providers as of the time of this writing that I've used and recommend.

You also must set the desired domain name for email notifications in /home/webapp/OSTel/config/environments/production.rb. Replace with your domain

  config.domain = "" 
  config.action_mailer.default_url_options = { :host => config.domain }

The next step is to install Kamailio

Data model and customization info

If you would like to generate users manually or forego the entire front end application for user provisioning, you must know both the Rails data model and the schema that Kamailio requires for a valid registered user.

Manual user creation

# su - webapp
$ cd OSTel
$ bundle exec rails console production
> u = User.create(:email => "", :sip_username => "foo", :password => "changeme") 

Data model and schema

The User model is a Rails ActiveRecord model

The schema looks like this after the Rails database is set up. There are validations which do not exist in the database but are enforced by the ActiveRecord model, they are described below.

    id integer NOT NULL,
    email character varying(255) DEFAULT ''::character varying NOT
    encrypted_password character varying(128) DEFAULT ''::characte
r varying NOT NULL,
    confirmation_token character varying(255),
    confirmed_at timestamp without time zone,
    confirmation_sent_at timestamp without time zone,
    reset_password_token character varying(255),
    reset_password_sent_at timestamp without time zone,
    remember_created_at timestamp without time zone,
    sign_in_count integer DEFAULT 0,
    current_sign_in_at timestamp without time zone,
    last_sign_in_at timestamp without time zone,
    current_sign_in_ip character varying(255),
    last_sign_in_ip character varying(255),
    failed_attempts integer DEFAULT 0,
    unlock_token character varying(255),
    locked_at timestamp without time zone,
    created_at timestamp without time zone,
    updated_at timestamp without time zone,
    authentication_token character varying(255),
    freeswitch_id integer,
    freeswitch_password character varying(255),
    ha1 character varying(255),
    ha1b character varying(255),
    domain character varying(255),
    sip_username character varying(255)

CREATE SEQUENCE users_id_seq
    CACHE 1;

ALTER TABLE ONLY users ALTER COLUMN id SET DEFAULT nextval('users_id_seq'::regclass);

    ADD CONSTRAINT users_pkey PRIMARY KEY (id);

CREATE UNIQUE INDEX index_users_on_sip_username ON users USING btree (sip_username);


The user authentication framework is called Devise. It manages user passwords and validates required records. The validated records are :email and :password. Email must be unique for the web application, as it is used as the user identifier. The password is encrypted pre-save via a hook in Devise.

Kamailio requires both the :ha1 and :ha1b fields to be encoded using Digest Authentication

This is implemented via the User ActiveRecord model with a pre-save and pre-update hook. Inspect the User model for the encoding method, named generate_sip_hash. It requires a plaintext password, which means it cannot pull data directly from the model since :password is a meta-field that is encrypted and saved into :encrypted_password. The table should not be populated manually unless you want to bypass the Rails application and create Kamailio users with a custom application.

For example, to provision a new Kamailio user you need username, domain and password. In the application, :domain is retrieved from the configuration and available through the global variable Devise::Application.config.domain. username is set with :sip_username and :password is set through the pre-encrypted value provided by Devise. The following commented definition of generate_sip_hash demonstrates how to properly encode the :ha1 and :ha1b fields.

  def generate_sip_hash
    # validate the presence of a password

    if (self.password) 
      # get the domain from the global configuration
      domain = Devise::Application.config.domain 

      # encode string as "username:domain:password" 
      self.ha1 = Digest::MD5.hexdigest("#{self.sip_username}:#{domain}:#{self.password}") 

      # encode string as "username@domain1:domain2:password" 
      self.ha1b = Digest::MD5.hexdigest("#{self.sip_username}@#{domain}:#{domain}:#{self.password}")

      # set domain for SIP realm.
      self.domain = domain 

The :ha1b field format is used if your application would like to use an email-like identifier for the username. For example, if I would like to provision users with an email address () as the username, you can manually set domain1 to "" and domain2 to that of your SIP server. If both :ha1 and :ha1b are set, users can log in with either identifier. See the AUTH_DB module documentation for details.

Next up! Kamailio

Also available in: PDF HTML TXT