Ruby on Rails is a popular web framework for Ruby that was developed to increase a programmer's productivity. However, getting various gems and dependencies to work together can get tricky sometimes. This guide will help you set up a full production-ready Rails environment including commonly used gems and dependencies.
Requirements
RCS instance with at least 512 MB of RAM (1024 MB prefered).
RCS instance running Ubuntu 17.04.
Stack Used in This Guide
Nginx: a fast and powerful web server. (ver 1.10.3)
Passenger: an app server that will help Nginx serve your Ruby app. (ver 1.5.1.8)
Rbenv: a Ruby version manager. (ver 1.1.1-2)
Ruby: (ver 2.4.1)
MariaDB: an open source branch of MySQL server (ver 10.2)
SSL certificate from Let's Encrypt
Installation
Add Sudo User
Note: It is highly recommended to not install any of these services as root, as you might expose yourself to an attack. Setting up a deploy
or app
user is a common convention:
sudo adduser deploy
sudo adduser deploy sudo
su deploy
Update and Upgrade System
Make sure you are running all the latest packages on your Ubuntu VM:
sudo apt-get update && sudo apt-get upgrade -y
Install Build System
In order to be able to compile Ruby using rbenv and other gems, various packages need to be installed. Depending on the version of Ruby you will need, some of the packages may not be needed.
Compiling
sudo apt-get install -y curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev
sudo apt-get install -y libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev
sudo apt-get install -y python-software-properties libffi-dev
sudo apt-get install -y build-essential openssl libreadline6 libreadline6-dev libreadline-dev
sudo apt-get install -y automake libtool bison pkg-config bison autoconf libc6-dev ncurses-dev
sudo apt-get install -y libapr1-dev libaprutil1-dev libx11-dev libffi-dev tcl-dev tk-dev
Packages for SSL support
These are necessary to compile several gems, such as Passenger:
sudo apt-get install -y zlib1g zlib1g-dev libssl-dev libyaml-dev libcurl4-openssl-dev libruby
Versioning
The Ruby community is using Git as a SCM of choice; but additional ones, like Mercurial or Subversion, can be installed as well:
sudo apt-get install -y git git-core
Database Drivers for MySQL / MariaDB
sudo apt-get install -y libmysqld-dev mysql-client libmysqlclient-dev
Nokogiri
Required for several popular gems that need native XML libs:
sudo apt-get install -y libxml2-dev libxslt-dev
Node.js
Add official repositories from Node with the latest version as default Ubuntu repositories tend to lag behind a few major versions:
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
Optional Packages
These packages are not required for the system to run, but are good to have if you need to use certain gems.
Graphs and Images
These libraries are not necessary and can be skipped unless you plan on using image manipulation gems; such as Rmagick:
sudo apt-get install -y imagemagick libmagickwand-dev libvips-dev
Database Drivers for SQLite and PostgreSQL
Install drivers for SQLite or PostgreSQL if you need to connect to other databases or prefer a simple, local DB:
sudo apt-get install -y libsqlite3-dev sqlite3 libpq-dev postgresql postgresql-contrib
Tools
Utilities that don't normally come pre-installed on a fresh Ubuntu install. Feel free to install your text-editor of choice:
sudo apt-get install -y iotop htop nano vim
Install the MariaDB Server
MariaDB is a powerful relational SQL server, that is fully compatible with MySQL. The easiest way to install the latest version of MariaDB is using official repositories:
sudo apt-get install software-properties-common
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,i386] http://ftp.utexas.edu/mariadb/repo/10.2/ubuntu zesty main'
sudo apt update
sudo apt install -y mariadb-server
Follow the prompts and set up a root password. After, verify that you can access your fresh installation:
mysql -V
It will display a line similar to this:
mysql Ver 15.1 Distrib 10.2.8-MariaDB, for debian-linux-gnu (x86_64) using readline 5
Login into the MySQL shell:
mysql -h localhost -u root -p
Note: use \q
to exit.
Install Rbenv and Ruby
Rbenv
Install Rbenv using git. This is the simplest install method, and it allows for easy updates later. Also install ruby-build
, it is responsible for actually compiling different versions of Ruby:
cd
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
Note: When you need to update simply cd ~/.rbenv
and git pull
.
Make Rbenv and Ruby-build available in the shell. To ensure that the export lines get inserted at the beginning of the .bashrc
file, which is important for non-interactive bash commands, use these lines:
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.temp_bashrc
echo 'eval "$(rbenv init -)"' >> ~/.temp_bashrc
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.temp_bashrc
cat ~/.temp_bashrc ~/.bashrc > ~/.combined_bashrc && mv ~/.combined_bashrc ~/.bashrc && rm ~/.temp_bashrc
exec $SHELL
Check if Rbenv and Ruby-build installed and are available in shell:
rbenv install --list
If rbenv
is not recognized, log out and log back into the shell.
Create a ~/.bash_profile
file and point it to source your ~/.bashrc
file. If you need to run any non-interactive shell commands from your Rails app, such as cron jobs setup by the whenever
gem, it will use the same version of Ruby as your interactive shell. This can help prevent strange errors. Add this line to the ~/.bash_profile
file:
if [ -f $HOME/.bashrc ]; then
source $HOME/.bashrc
fi
Ruby
Install Ruby 2.4.1:
rbenv install 2.4.1
Note: This process may take 5-15 minutes depending on the resources on your VM, and there is no progress bar.
Make Rbenv available everywhere.
rbenv global 2.4.1
Passenger and Nginx
Add the PGP key and HTTPS support for apt:
sudo apt-get install -y dirmngr gnupg
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo apt-get install -y apt-transport-https ca-certificates
Add the Passenger repository:
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger zesty main > /etc/apt/sources.list.d/passenger.list'
sudo apt-get update
Install the Passenger + Nginx modules:
sudo apt-get install -y nginx
sudo apt-get install -y libnginx-mod-http-passenger
Visit your RCS instance using it's domain name or IP to test these at this point. If they're working, your page will show the default Nginx welcome page.
Setup Rails, the App, and Configure Passenger
Install Bundler and Rails:
gem install bundler rails --no-ri --no-rdoc
Ubuntu/Debian convention is to setup your app in /var/www
. By default it is only writable by root. For the setup to work, give ownership to the sudo user deploy
:
sudo chown deploy:deploy /var/www -R
Generate the rails app in /var/www/
. If you already have an app you want to deploy, git clone
it here and then run bundle
:
cd /var/www
rails new example --database=mysql
Configure Passenger to point to the app.
Prep Nginx.
sudo nano /etc/nginx/nginx.conf
Change user to
deploy
.user deploy;
In the
http
section of the config, there should be a line that tells Nginx to load modules including passenger. If it's missing, you can add it right afterVirtual Host Configs
title, but beforesites-enabled
.include /etc/nginx/conf.d/*.conf;
Edit/create the
passenger.conf
file.sudo nano /etc/nginx/conf.d/mod-http-passenger.conf
Tell Passenger to use our Rbenv setup. It may contain a line pointing to the Ruby version included with Passenger, just delete or comment it out.
passenger_ruby /home/deploy/.rbenv/shims/ruby; passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;
Setup virtual host to point to the app in
/var/www/example/
.sudo nano /etc/nginx/sites-enabled/example.conf server { listen 80; server_name example.com www.example.com; root /var/www/example/public; passenger_enabled on; # When you are ready to switch to production mode - change this to `production` passenger_app_env development; # <-- !important }
Restart Nginx.
sudo service nginx restart
At this point your application is ready to be used in development mode. To switch to production mode you need go back to your Nginx configuration and change the rails_env
setting to production
.
Before you switch to production mode, you still will need to setup your production database example_production
, database.yml
, and secret key. Check out a tool like Capistrano or Mina to speed up your application deployment process. It is a good practice to use ENV variables with a gem like dotenv
, and do not commit your passwords, secret keys and such to your git repository.
Setup SSL
There are multiple services out there offering SSL certificates for your domain, many are paid and a couple are free. Setup SSL no matter what service you use. Let's Encrypt is very easy, and free, to use. Let's Encrypt is a non-profit organization backed by many tech giants.
Installation
Run the following commands, and follow the prompts.
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
sudo certbot --nginx
sudo certbot renew --dry-run
If you go to your RCS instance now using HTTPS
, you will see a secure website.
Renewal
Your newly issued certificate will expire, and will need to be renewed periodically. The easiest way to do this is to set up a cron job.
sudo crontab -e
30 2 * * 1 /usr/bin/certbot renew
As a final, but optional step, reboot your VM and make sure all services restart as expected.