Create a Ubuntu Server with Rails, Nginx, and VirtualBox

server rack
panumas nikhomkhai at Pexels

Initial Setup

Download and Install VirtualBox

  1. The first thing you need is to download VirtualBox for your platform if you haven’t already. You can download it here.
  2. Install VirtualBox onto your fastest drive.

Download and Install Ubuntu

  1. It’s easiest to download and use Ubuntu Server 18.04 right now. But if you like, you can download Ubuntu 20.04 instead.
  2. Launch VirtualBox, and then create a new VM. On the first screen:
    1. Choose a memorable name.
    2. Put the Machine Folder on your fastest drive.
    3. Type: Choose Linux
    4. Version: Choose Ubuntu 64 Bit.
  3. On the second screen:
    1. Select as much memory as you can spare. 8 gigs would be good.
  4. On the third screen:
    1. You’ll want to create a new virtual disk.
    2. If you only use VirtualBox then you can leave it as VDI and click Create.
    3. Select Dynamically Sized and hit Next.
    4. Ensure that you have chosen to put the disk image on your fastest drive. Give the drive a nice size (about 100GB) and hit Create.
  5. Now that the disk image is created, choose the Machine and then click on Settings.
  6. Navigate to Storage, click on the empty CD Under Storage Devices.
  7. Under Attributes on the Right, Click on the disk next to Optical Drive.
  8. Find the Ubuntu disk image you downloaded and select it.
  9. Toggle the Live CD/DVD checkbox and then hit Ok.
  10. Now hit Launch/Start and get let the installation begin.
  11. You might get a prompt when you initially hit launch asking you to choose a media to boot from. It “should” have the Ubuntu Live CD/DVD already chosen, so just confirm it and keep ongoing.

Installing Ubuntu Part 2

  1. After some scrolling text, you’ll get to your first prompt: Choosing a language. Hit Enter and you’ll get the default English option.
  2. It’s almost guaranteed that you’ll get hit with an Installer Update. Just go ahead and update to the new installer.
  3. That should have went fast and you’ll see Keyboard Configuration. Unless you have something unique, hit Enter.
  4. Hit Enter on Network Connections without touching anything.
  5. Hit Enter on Configure Proxy.
  6. Hit Enter on configure Ubuntu Archive Mirror.
  7. On Guide Storage Configuration:
    1. Ensure that Use an entire Disk is checked.
    2. Ensure Set up this disk as an LVM group is UNCHECKED or you will have nothing but problems.
    3. Move on down to Done and hit enter.
  8. On Storage Configuration you should be able to just hit Enter.
  9. You’ll be prompted with a Confirm Destructive Action warning. If you’ve done everything right, select Continue and hit enter.
  10. On Profile Setup you’ll fill in the information requested. Make a note of it so you don’t lose it, or you’ll be doing all of this again.
  11. On SSH Setup, check the box for Install OpenSSH Server. Unless you have an SSH Identity to upload/import, leave it set to No.
  12. On Featured Server Snaps, skip everything and hit Done.
  13. While you’re making all those choices, it’s been installing in the background, so that’s good news! It’ll then start downloading and installing security updates. Let it do it’s thing before proceeding.
  14. Once updates are down, hit Reboot. You’ll probably see an error about unmounting the cdrom. Click on Devices in the menu, select Optical Drives, and then choose the unmount option.
  15. Click on the Machine menu option, then hit Reset, click through the warning and let it reboot.
  16. After it reboots, you may not see a login prompt, but you’ll notice that it has stopped scrolling text for a minute or two. Try hitting enter. If you get a login prompt, go ahead and log in! 🙂

Prep the Server

  1. Create a Deploy user
    1. sudo su
    2. adduser deploy
    3. adduser deploy sudo
    4. exit
  2. You’ll need to know your IP address for this next step. Since you don’t know it, we’ll need to install net tools and then do ifconfig to get the guest computers IP address. This will let us copy your personal SSH key to the guest machine.
    1. sudo apt install net-tools
    2. ifconfig and get your ip address.
    3. From your host computers command prompt, type: ssh-copy-id [email protected]<your-guest-ip-address>
    4. From your host computers command prompt, type: ssh-copy-id [email protected]<your-guest-ip-address>
  3. Now type ssh [email protected]<your-guest-ip-address>

Install Virtualbox Guest Additions

  1. In Virtualbox, select Devices and then select Insert Guest Additions CD.
  2. On the command prompt type: sudo mount /dev/cdrom /mnt
  3. Type cd /mnt
  4. Type sudo apt-get install -y dkms build-essential linux-headers-generic linux-headers-$(uname -r)
  5. Type sudo su
  6. Type ./
  7. Type shutdown -r now
  8. In Devices menu be sure to enable the shared clipboard (Host to Guest at a minimum). Drag and Drop isn’t necessary because you don’t have a GUI.

Installing Ruby

  1. Adding Node.js repository
    1. curl -sL | sudo -E bash -
  2. Adding Yarn repository
    1. curl -sS | sudo apt-key add -
    2. echo "deb stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
    3. sudo add-apt-repository ppa:chris-lea/redis-server
  3. Refresh our packages list with the new repositories
    1. sudo apt-get update
  4. Install our dependencies for compiiling Ruby along with Node.js and Yarn
    1. sudo apt-get install git-core curl zlib1g-dev build-essential 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 redis-server redis-tools nodejs yarn
  5. Installing RBENV:
    1. git clone ~/.rbenv
    2. echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
    3. echo 'eval "$(rbenv init -)"' >> ~/.bashrc
    4. git clone ~/.rbenv/plugins/ruby-build
    5. echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc
    6. git clone ~/.rbenv/plugins/rbenv-vars
    7. exec $SHELL
    8. rbenv install 2.7.1
    9. rbenv global 2.7.1
    10. ruby v
    11. ruby 2.7.1
  6. Installing Bundler:
    1. This installs the latest Bundler, currently 2.x.
      1. gem install bundler
    2. For older apps that require Bundler 1.x, you can install it as well.
      1. gem install bundler -v 1.17.3
    3. Test and make sure bundler is installed correctly, you should see a version number.
      1. bundle -v
      2. Bundler version 2.0

Installing NGINX and Passenger

For production, we’ll be using NGINX as our webserver to receive HTTP requests. Those requests will then be handed over to Passenger which will run our Ruby app.

Installing Passenger is pretty straightforward. We’ll add their repository and then install and configure their packages.

  1. sudo apt-key adv --keyserver hkp:// --recv-keys 561F9B9CAC40B2F7
  2. sudo sh -c 'echo deb bionic main > /etc/apt/sources.list.d/passenger.list'
  3. sudo apt-get update
  4. sudo apt-get install -y nginx-extras libnginx-mod-http-passenger
  5. 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
  6. sudo ls /etc/nginx/conf.d/mod-http-passenger.conf

Now that we have NGINX and Passenger installed, we need to point Passenger to the correct version of Ruby.

We’ll start by opening up the Passenger config file in your favorite editor, nano or vim.

If you want to use the Nano for editing: sudo nano /etc/nginx/conf.d/mod-http-passenger.conf

If you want to use the Vim for editing: sudo vim /etc/nginx/conf.d/mod-http-passenger.conf

We simply want to change the passenger_ruby line to match the following: passenger_ruby /home/deploy/.rbenv/shims/ruby;

Save this file and we’ll start NGINX. sudo service nginx start

You can check and make sure NGINX is running by visiting your server’s public IP address in your browser and you should be greeted with the “Welcome to NGINX” message.

Next we’re going to remove this default NGINX server and add one for our application instead.

  1. sudo rm /etc/nginx/sites-enabled/default
  2. If you want to use the Nano for editing
    1. sudo nano /etc/nginx/sites-enabled/myapp
  3. If you want to use the Vim for editing
    1. sudo vim /etc/nginx/sites-enabled/myapp

We want the contents of our NGINX site to look like the following.

Change “myapp` to the name of your app. We’ll use this same folder later on when we define our Capistrano deploy_to folder.

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

  server_name _;
  root /home/deploy/myapp/current/public;

  passenger_enabled on;
  passenger_app_env production;

  location /cable {
    passenger_app_group_name myapp_websocket;
    passenger_force_max_concurrent_requests_per_process 0;

  # Allow uploads up to 100MB in size
  client_max_body_size 100m;

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

Save the file and then we’ll reload NGINX to load the new server files. sudo service nginx reload

Setting up PostgreSQL

  1. sudo apt-get install postgresql postgresql-contrib libpq-dev
  2. sudo su - postgres
  3. createuser --pwprompt deploy
  4. createdb -O deploy myapp
  5. exit

Creating a MYSQL Database

  1. sudo apt-get install mysql-server mysql-client libmysqlclient-dev
  2. sudo mysql_secure_installation
  3. Open the MySQL CLI to create the user and database
    1. mysql -u root -p

In the following example, make sure you replace the following names:

  • myapp with the name of your database, typically the name of your app
  • $omeFancyPassword123 with your own password
  • deploy with the name of your database user if you’d like something different
  2. CREATE USER IF NOT EXISTS 'deploy'@'localhost' IDENTIFIED BY '$omeFancyPassword123';
  3. CREATE USER IF NOT EXISTS 'deploy'@'%' IDENTIFIED BY '$omeFancyPassword123';
  4. GRANT ALL PRIVILEGES ON myapp.* TO 'deploy'@'localhost';
  5. GRANT ALL PRIVILEGES ON myapp.* TO 'deploy'@'%';
  7. \q