Root-Server Tutorial

ROOT-SERVER TUTORIAL

Installing Ruby on Rails on Production Systems

Learn how to install Ruby on Rails on Ubuntu 20.04 in a production environment.

Author:

Vincent Thelang

Last updated:

05/11/2021

Introduction

In this tutorial, we will install Ruby on Rails from scratch on a production system. The software versions used were Ruby version 3, Rails 7 and Ubuntu 20.04 base image. I used this environment by myself on a VPS 1000 G9 and can recommend it for its performance. After ordering the server and installing the Ubuntu 20.04 image, we can connect to it via SSH.

Requirements

  • vServer or root server with Ubuntu 20.04 installed
  • Domain

Step 1 - Installing Ruby

Creating a user

First we create a separate user on our system:

adduser rails_user
adduser rails_user sudo
su rails_user

Installing necessary packages

Once we have connected to the server, we can start installing some necessary packages. To guarantee the operation of Webpacker in Ruby on Rails, we need to install Node.js and Yarn. Webpacker makes it easy to use the JavaScript pre-processor to manage application-like JavaScript in Rails.

For the installation, we first need to add some repositories to our system:

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo add-apt-repository ppa:chris-lea/redis-server

Then we refresh our package list with the new repositories:

sudo apt-get update

Now we can install the necessary packages:

sudo apt-get install git-core curl zlib1g-dev build-essential libsqlite3-dev sqlite3 libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev dirmngr gnupg apt-transport-https ca-certificates nodejs yarn

Installing rbenv and Ruby

Once all the packages are installed, we can proceed with the actual installation of Ruby. Here we use "rbenv", which is a Ruby version manager that makes it easier to handle different Ruby versions and to deal with gems and environment variables.

The easiest way is to clone rbenv from GitHub, so we have the latest version. To do this, we proceed as follows:

git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
git clone https://github.com/rbenv/rbenv-vars.git ~/.rbenv/plugins/rbenv-vars
exec $SHELL

Once rbenv is installed, we can continue with the installation of the Ruby version. In our example we install the current version 3.0.2, but this can be changed to any other version.

rbenv install 3.0.2
rbenv global 3.0.2
ruby -v

If version 3.0.2 appears after executing ruby -v, the installation was successful.

Installing Bundler

To be able to install gems from the project in the future, we also need to install the bundler.

gem install bundler
bundle -v

If Bundler version 2 is displayed now, the installation was successful and the installation of Ruby is complete.

Step 2 - Configuring the web server

For our production environment, we use nginx to receive HTTP requests. The HTTP requests are then forwarded to Passenger, which ensures that they are executed in our Rails application.

Installing nginx & Passenger

For the installation, we once more have to add repositories to the system:

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7
sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger focal main > /etc/apt/sources.list.d/passenger.list'

Then we update the list:

sudo apt-get update

Now we can install nginx and Passenger:

sudo apt-get install -y nginx-extras libnginx-mod-http-passenger

To activate Passenger in nginx we have to execute the following two commands:

if [ ! -f /etc/nginx/modules-enabled/50-mod-http-passenger.conf ]; then sudo ln -s /usr/share/nginx/modules-available/mod-http-passenger.load /etc/nginx/modules-enabled/50-mod-http-passenger.conf ; fi
sudo ls /etc/nginx/conf.d/mod-http-passenger.conf

Configuring nginx & Passenger

Passenger comes with its own compiled Ruby version by default. I don't recommend using this version as it may be outdated and we installed rbenv in advance, which solves a lot of problems for us.

To adjust Passenger, we need to edit the following file:

sudo nano /etc/nginx/conf.d/mod-http-passenger.conf

There we change the line as follows:

- passenger_ruby /usr/bin/passenger_free_ruby;
+ passenger_ruby /home/rails_user/.rbenv/shims/ruby;

After saving the file, we execute the following command to start nginx:

sudo service nginx start

If we now access the IP or server address via web browser and receive the message "Welcome to nginx", we have configured nginx correctly.

We can now create a new configuration file by creating the following file with the nano editor:

sudo nano /etc/nginx/sites-enabled/rails_app

We copy the following content into the file:

server {
  listen 80;
  listen [::]:80;

  server_name YOUR_DOMAIN;
  root /var/www/rails_app/public;

  passenger_enabled on;
  passenger_app_env production;

  location /cable {
    passenger_app_group_name myapp_websocket;
    passenger_force_max_concurrent_requests_per_process 0;
  }

  client_max_body_size 10m;

  location ~ ^/(assets|packs) {
    expires max;
    gzip_static on;
  }
}

You can modify the following details according to your needs:

  • server_name
    • Instead of the YOUR_DOMAIN, you can specify here your domain on which your Rails app should run.
  • root
    • /var/www/rails_app is the location of our Rails app. You can customize this, the important thing is that the path always ends with /public.
  • passenger_app_env
    • If you prefer to run your Rails in a development environment, you can specify development here instead of production.
  • location /cable
    • If you are sure that your app will not use an Action Cable for WebSockets, you can remove this block from the file.
  • client_max_body_size
    • If you want to allow your users to upload files to your Rails app, you can set a maximum upload file size here. In the default setting, this is 10 MB.
  • location ~ ^/(assets|packs)
    • The assets and packs directories contain JavaScript and CSS files from your Rails app. To make these files more performant, they are cached and zipped with the block. You can extend this with more directories.

Step 3 - Setup Rails

Once you have saved the file, we change to the directory /var/www/. Now you can copy your existing Rails app into the rails_app folder. Alternatively, you can use tools like Capistrano for deployment.

To install Rails, use the gem install command provided by RubyGems:

gem install rails

If you want to start from scratch, you can create a new Rails app here with the name rails_app and execute the following command:

rails new rails_app

After creating the project folder, Rails now runs Bundle install to install the necessary gems, and then Yarn to install the necessary JS dependencies. We can then switch to the project folder using cd rails_app and start development. Happy Coding! ;)

Sqlite3 was selected as the default database, which is sufficient for small applications in most cases. If you want to do more, install PostgreSQL or another database on the server and configure it in your Rails app.

To finally compile the JavaScript files execute the following command:

RAILS_ENV=production rails assets:precompile

Now we are almost done, we just need to reload nginx and then we can view our Rails app in the web browser.

For this purpose, we execute the comnand:

sudo service nginx reload

Conclusion

If we now access our IP or server address or routed domain and our Rails app is displayed, we are done. However, keep in mind that this is an unencrypted HTTP connection. If you want to make your application accessible to other users, please install at least LetsEncrypt in your nginx.

License

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicence, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Contributor's Certificate of Origin

By making a contribution to this project, I certify that:

  1. The contribution was created in whole or in part by me and I have the right to submit it under the license indicated in the file; or

  2. The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same license (unless I am permitted to submit under a different license), as indicated in the file; or

  3. The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.

  4. I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the license(s) involved.

Published 05/11/2021 by Vincent Thelang

Submit your tutorial

Get 60€ netcup vouchers for every published tutorial.