Software Development Stuff

Postings of a software developer

Ruby on Rails Server With Nginx, Phusion Passenger and PostgreSQL

Introduction

Instructions for setting up Ubuntu 12.04.4 LTS to host a Ruby on Rails Application with nginx as the web server, Phusion Passenger as the application server and PostgreSQL as the database. This has been tested on a clean installation of Ubuntu 12.04.4, but should work on existing installation and different versions with little changes as well. This is one of my first blog posts so take that into account when giving feedback.

Installation

Write the following inside a script file and run it (Or run the commands one by one). It will add the Phusion Passenger repositories to apt sources, install it, install rbenv, ruby and bundler, stuff required to compile Ruby, PostgreSQL and nginx. Feel free to customize the script to your needs. If you prefer RVM to rbenv just change the corresponding lines etc.:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env bash
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
echo "deb https://oss-binaries.phusionpassenger.com/apt/passenger precise main" | sudo tee -a /etc/apt/sources.list.d/passenger.list
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates
sudo apt-get install -y git build-essential nodejs postgresql postgresql-server-dev-9.1 libssl-dev nginx-extras passenger libcurl4-openssl-dev
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
source ~/.bash_profile
rbenv install -v 2.1.1 # replace with the ruby version that you want to use
rbenv global 2.1.1 # replace with the ruby version that you want to use
gem install -V bundler

Configuration

Change the following lines in /etc/nginx/nginx.conf:

1
2
3
4
5
6
7
8
9
10
11
# Phusion Passenger config
##
# Uncomment it if you installed passenger or passenger-enterprise
##

# passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
# passenger_ruby /usr/bin/ruby;

##
# Virtual Host Configs
##

to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Phusion Passenger config
##
# Uncomment it if you installed passenger or passenger-enterprise
##

passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
passenger_ruby /<path/to/where/you/installed/ruby>/bin/ruby;

#Add the following line if you don't want passenger to display friendly debug information when your application fails to start:
passenger_friendly_error_pages off;

##
# Virtual Host Configs
##

(Default ruby installation directory is /home/<username>/.rbenv/versions/<ruby-version>)

Generate a ssh keypair and add your public key to where you deploy from (If you need to and use git with ssh). Otherwise just do whatever you need to get your application to the server. Guide to ssh key generation can be found at https://help.github.com/articles/generating-ssh-keys

Clone your repo to a directory of your choosing (If you use git):

1
$ git clone <your-git-repo-address>

Add an user to postgresql with the name and password you specified in the production database config in your database.yml:

1
$ sudo -u postgres psql
1
create user <username>  with password '<password>';
1
alter role <username> createdb;

To exit psql prompt, type:

1
\q

Change the local authentication line in /etc/postgresql/9.1/main/pg_hba.conf:

1
2
3
4
5
6
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     peer
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5

to:

1
2
3
4
5
6
# TYPE  DATABASE        USER            ADDRESS                 METHOD

# "local" is for Unix domain socket connections only
local   all             all                                     md5
# IPv4 local connections:
host    all             all             127.0.0.1/32            md5

to allow password authentication to postgresql

And then restart postgresql:

1
$ sudo service postgresql restart

source ~/.bash_profile to get access to rbenv and new commands of the gems that were installed:

1
$ source ~/.bash_profile

Go to your rails application root and run bundle install:

1
$ bundle install --without development test

Make sure your secret token is specified in your application’s config/application.yml if you’re using the figaro gem. If not, you can generate a new one with the following command in your rails apps’s root:

1
$ rake secret

Then just add that to <your/rails/application/root>/config/application.yml:

1
SECRET_TOKEN: <generated-token-here>

If you are using ssl, now is the time to import your certificates or generate them. The following configurations assume they are stored in /etc/nginx/ssl/

Create a file to /etc/nginx/sites-enabled/ with the name of the name of your application and add the following contents Replace leading whitespaces with tabs if nginx complains about them:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server {
        listen 80;
        server_name <your-domain-here>;
        root <your/rails/application/root>/public;
        passenger_enabled on;
}

# Comment this out if you are using SSL
# server {
        # listen 443 ssl;
        # server_name <your-domain-here>;
        # passenger_enabled on;
        # root <your/rails/application/root>/public;
        # ssl_certificate /etc/nginx/ssl/server.crt; # Replace with the path to your certificate
        # ssl_certificate_key /etc/nginx/ssl/server.key; # Replace with the path to your key
# }

Then modify /etc/nginx/nginx.conf to only include that site configuration:

1
2
3
4
5
6
7
    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/<the-server-conf-file-you-created>;
}

Go to your rails application root and run the following commands:

1
$ RAILS_ENV=production rake db:setup assets:precompile

Then restart nginx:

1
$ sudo service nginx restart

Your application should now be served properly by nginx on port 80 :) If you run into problems, check the logs at /var/log/nginx to see whether they help identify the problem.

Vagrant for Ruby on Rails Development on Ubuntu 13.10

Installing

Vagrant can be installed on Ubuntu via apt-get, but the version is really old. I downloaded the .deb -file from http://www.vagrantup.com/downloads.html.

Configuring

First create a folder for your project and go to that folder. The following command will initialize a new vagrant virtual machine and use Ubuntu Precise as the base:

$ vagrant init precise32 http://files.vagrantup.com/precise32.box

Vagrant will also create a Vagrantfile in the working directory. Open the file for editing and the change the following line:

1
2
3
4
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # config.vm.network :forwarded_port, guest: 80, host: 8080

to

1
2
3
4
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  config.vm.network :forwarded_port, guest: 3000, host: 3000

to forward the default Rails development port to the virtual machine. Now create two script files to the same directory with Vagrantfile. We will include all software installation in those scripts. You can name the scripts as you like, the names that I use are just examples:

$ nano installation.sh

I have put the following commands into the first scripts that will be run as root. Feel free to customize these commands to your liking. Node.js is included because its needed for some javascript operations:

1
2
3
4
#!/usr/bin/env bash
echo -e "deb mirror://mirrors.ubuntu.com/mirrors.txt precise main restricted universe multiverse\ndeb mirror://mirrors.ubuntu.com/mirrors.txt precise-updates main restricted universe multiverse\ndeb mirror://mirrors.ubuntu.com/mirrors.txt precise-backports main restricted universe multiverse\ndeb mirror://mirrors.ubuntu.com/mirrors.txt precise-security main restricted universe multiverse\n$(cat /etc/apt/sources.list)" > /etc/sources.list
apt-get update
apt-get install -y git build-essential nodejs libsqlite3-dev

After this create another script file to be run as normal user. The script will first install rbenv for easy switching between different Ruby versions. Then it will install a version of Ruby, in my case 2.1.0. It will then set that version of Ruby to be the global default. Finally it will install Rails and Bundler:

$ nano installation_user.sh
1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env bash
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
source ~/.bash_profile
rbenv install -v 2.1.0 # replace with the ruby version that you want to use
rbenv global 2.1.0 # replace with the ruby version that you want to use
gem install rails
gem install bundler

After this add the following lines to Vagrantfile to include your new shell scripts:

1
2
  config.vm.provision :shell, path: "installation.sh"
  config.vm.provision :shell, path: "installation_user.sh", privileged: false

After this the configuration for your Ruby on Rails development environment should be configured and you can start the Vagrant box with the following command:

$ vagrant up

The startup will take some time the first time because it will install the whole system like you previously configured. After the process has finished you can ssh to your new virtual machine with the command:

$ vagrant ssh

The directory where you most likely will want to initialize your Rails project(s) inside the virtual machine is:

/vagrant/

Since it will be shared between your guest and host machine. You should now be set up to start developing your application.