public

A guide for setting up an Ubuntu server for Rails deployment

  • Download Gist
Ubuntu Setup Guide for Rails Deployment.md
Markdown

Rails Deployment with Ubuntu 12.10, RVM, Postgresql, Nginx, and Unicorn.

This setup was used successfully on a DigitalOcean VPS. After much trial and error, and following a number of disparate guides and tutorials, I was able to distil the process to the information found in this gist.

Before getting started, you should create a new server droplet. Login to verify that everything is working correctly.

ssh root@xxx.xxx.xx.xx

You might see the following error when logging in.

RSA host key for xxx.xxx.xx.xx has changed and you have requested strict checking.
Host key verification failed.

You can resolve this error using the following command. See How to remove strict RSA key checking in ssh for more information.

ssh-keygen -R xxx.xxx.xx.xx

After running the command will see the following prompt.

The authenticity of host 'xxx.xxx.xx.xx (xxx.xxx.xx.xx)' can't be established.
RSA key fingerprint is xxx
Are you sure you want to continue connecting (yes/no)? yes

Type yes and hit enter to continue. You will be prompted to enter your root password. Do so and you should be connected to your VPS.

Exit back to your local machine and use ssh-copy-id (OS X only) to add your rsa key. This avoids the need to enter your password each time you ssh into the server. If ssh-copy-id is not available on your local machine use brew to install it.

brew install ssh-copy-id # If it's not installed already; OS X only.
ssh-copy-id root@xxx.xxx.xx.xx

Log into the remote server and verify everything is working correctly.

Add a new user called deployer. We will use this user with Capistrano to deploy the app. You may want repeat the process and add your rsa key to deployer again to avoid typing your password each time you login.

ssh root@xxx.xxx.xx.xx
adduser deployer --ingroup sudo # Follow the prompt; no further information required.

If you you want to copy your rsa key for deployer, exit and run the following command.

ssh-copy-id deployer@xxx.xxx.xx.xx

Login to the server as deployer to verify everything is working correctly.

ssh deployer@xxx.xxx.xx.xx

Remote Server Setup

Update packages, then install git-core to deploy from github. Add python-software-properties and software-properties-common and to be able to add repositories to apt-get. Update packages after installation.

sudo apt-get -y update
sudo apt-get -y install git-core python-software-properties software-properties-common
sudo apt-get -y update

Add github key:

ssh git@github.com

You will see the following message.

The authenticity of host 'github.com (204.232.175.90)' can't be established.
RSA key fingerprint is xxx
Are you sure you want to continue connecting (yes/no)? yes

Type yes and hit enter to continue. Then exit the remote terminal and return to your local machine, and run the following command.

ssh-add -K # OS X only; still not sure why this is needed? ...

Install Postgresql

After logging back into your server using deployer, add the Posgresql repository.

sudo add-apt-repository ppa:pitti/postgresql
sudo apt-get -y update
sudo apt-get -y install postgresql libpq-dev

Switch to postgres user created by the install and setup its credentials.

sudo -u postgres psql
\password

Create the user and database for your Rails application.

create user awesome_app with password 'awesome_password';
create database awesome_app_production owner awesome_app;

Install Nodejs

Add the repository, update, then isntall it.

sudo add-apt-repository ppa:chris-lea/node.js
sudo apt-get -y update
sudo apt-get -y install nodejs

Install Nginx

Add the repo to apt-get, update, then install it.

sudo add-apt-repository ppa:nginx/stable
sudo apt-get -y update
sudo apt-get -y install nginx

Finally, start Nginx up.

sudo service nginx start

After starting it you should be able to navigate to the servers ip address to view the Nginx splash page.

At this point all that's left is setting up Ruby. You may want to create a snapshot of the VPS. This will allow you to start new droplets using the snapshot, and therefore avoid repeating this setup.

Note that Digital Oceans requires you shutdown the server in order to create a snapshot.

Install Ruby

You may install Ruby using RVM, rbenv, or compile it from source. I'm only familiar with RVM so this is what I'll be using. Grab RVM using Curl. If Curl is not installed on your VPS, use apt-get to install it.

\curl -L https://get.rvm.io | bash -s stable

Load RVM, and install its dependencies.

source ~/.rvm/scripts/rvm
rvm requirements

I found that if you are using RVM its paths get added to ~/.bash_profile. This will cause bundler to fail during Capistrano deployment, and a slew of other issues. See Bundler/Capistrano errors for more information. RVM should warn you about this during setup, and might ask you to run source ~/.profile.

You can also tell if this happened when running source ~/.rvm/scripts/rvm; the command produces an error.

Open up .bash_profile and copy the RVM path, then paste it at the top of your .bashrc file. Then reload .bashrc and RVM.

vi ~/.bash_profile # Copy path: [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
vi ~/.bashrc       # Then paste path at top of this file
source ~/.bashrc
source ~/.rvm/scripts/rvm

Now you have two choices: either delete .bash_profile, since its empty, or copy and paste the contents of ~/.profile into it. Forget to do this and every time you ssh into the VPS you'll have to source .bashrc in order to access any Ruby commands. This will cause problems for Capistrano deployments as well. See -bash ruby command not found for more information.

When bash is invoked as an interactive login shell, or as a non-interactive shell with the --login option, it first reads and executes commands from the file /etc/profile, if that file exists. After reading that file, it looks for ~/.bash_profile, ~/.bash_login, and ~/.profile, in that order, and reads and executes commands from the first one that exists and is readable.

sudo rm ~/.bash_profile

You now aught to be able to install your desired version of Ruby. Once installed, set it to the default version. Installing Ruby should take a few minutes, so grab a coffee while your at it.

rvm install 1.9.3
rvm use 1.9.3 --default

Install Rubygems.

rvm rubygems current

If your application uses any gems that have external dependencies, you should install them now. This Rails app requires Image Magic and rmagick to use with CarrierWave.

sudo apt-get -y install libmagickwand-dev imagemagick

For more information, see How to install rmagick on Ubuntu 10.04.

Finishing Up

At this stage you'll still need to write your Capistrano deployment recipes to setup your site on Nginx and Unicorn.

After Deployment (Work in Progress)

After deployment you will want to remove the Nginx default site. This requires you restart Nginx. You will also want to make sure that Unicorn starts up after the server is restarted.

sudo rm /etc/nginx/sites-enabled/default
sudo service nginx restart
sudo update-rc.d -f unicorn_awesome_app defaults

Gotchas

When deploying with a dynamic dabatase.yml file, there seems to be some issues with the yaml parser. See ERB templates with leading YAML reserved characters fail to serialize for more details.

You may need to gem install bundler as deployer@xxx in Capistrano fails with bundle gem not found during deployment. Although this may be related to the path being set incorrectly.

References

  1. Initial Server Setup with Ubuntu
  2. How to Install Ruby with RVM
  3. Resolving bundler errors during deployment
  4. How to install rmagick on Ubuntu 10.04
  5. Rails Cast Deploying to VPS and its comments
  6. -bash ruby command not found

The following references were not used, but they could be useful:

  1. Setting up nginx on Ubuntu 12.10
  2. Example unicorn init.sh
  3. How do RVM and rbenv work
  4. Vim commands cheat sheet
  5. rvm-capistrano Gem
  6. Setting up Unicorn with Nginx
  7. Example scripts for Nginx and Unicorn

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.