AWS can be a very confusing system to work with, if you don't know much about it. I have researched many guides and manuals online, and never found one that had everything you needed, and didn't make you spend hours searching Google for commands and answers that none of these guides had. This is why I wanted to write a guide on this subject. I have put everything you will ever need to setup an AWS Rails Server here. In this guide, I will show you how to set up the following items:
First off, let's start with setting up our AWS server with the domain name we have already purchased. Go to Route53 in your AWS console, click on Hosted zones, then Create Hosted Zone at the top of the page. Enter your domain name in the field and set the type to Public Hosted Zone. Amazon will automatically give you NS records which you will need to update on the registrar you bought your domain name from. Once you have updated your NS records, it is now time to create our EC2 instance.
Head to the Amazon services page where all their services are listed. Then click on Launch Instance to start the process to create a new one. Select Ubuntu Server 16.04 LTS (HVM), SSD Volume Type, you won’t be charged for it if this is your first time using AWS, then select t2.micro which has Free tier eligible underneath it in green. Click Review and Launch, then click Launch. You will be asked to set a security .pem key file, create one and save it for later (make sure to put this in your home directory on your mac), you will need this to SSH in the server using the terminal later.
Congratulations! We have successfully created our Ubuntu Server Box! Now we need to set up an Elastic IP which will set a Static IP for our server. This will make it so our IP Address never changes and will advert any issues with future features. Now, head over on the left underneath Network and Security and select Elastic IP. Click on the blue Allocate new address button at the top and follow the steps to create a new Elastic IP. You will be asked to select your current EC2 instance you want to associate it with, select the box we just created.
Once you have successfully attached the new Elastic IP to your box, copy the IP Address and head back on over to your Route 53 Hosted Zone we created just a few minutes ago. Select Create Record Set and add two new A- IPv4 Address Records, one with your site as domain.com and another as www.domain.com. You will place the Elastic IP we created in the value box for both of these. This will redirect any requests to your domain to the IP we attached it to.
We also need to enable our http port 80, which is the default port your site will be directed to when someone visits it. Go to EC2, Network and Security, Security Groups, and find your instance you created. It will look somewhat like this "launch-wizard-2 created 2017-07-30T18:18:55.754-06:00". At the bottom of the screen click on Inbound then click edit. Once there, make sure that you have these rules:
| Type | Protocol | Port Range | Source | | --------------- | -------- | ---------- | -------| | HTTP | TCP | 80 | 0.0.0.0/0 | | HTTP | TCP | 80 | ::/0 | | PostgreSQL | TCP | 5432 | 0.0.0.0/0 | | SSH | TCP | 22 | 0.0.0.0/0 | | SMTP | TCP | 25 | 0.0.0.0/0 | | Custom TCP Rule | TCP | 3000 | 0.0.0.0/0 | | HTTPS | TCP | 443 | 0.0.0.0/0 | | HTTPS | TCP | 443 | ::/0 |
It’s now time to SSH into our Ubuntu Server. On Mac OSX, open up a terminal and head to the directory where you saved your .pem file. Give the file the right permissions to use it in your terminal and make it secure.
chmod 600 myrsafile.pem
Once done, run this command:
ssh -i yourkey.pem ubuntu@ec2-yourip.yourregion.compute.amazonaws.com
The last part of this command you will copy and paste by going to your EC2 page, then Instance category, click on Instance, and copy and paste the Public DNS (IPv4) found in the table displayed on that page. Once you have successfully entered your server, we will now get started on installing Ruby.
Let’s update the current packages.
sudo apt-get update
We will now download the dependencies needed to run Ruby, PostgresSQL, and Rails.
Let’s get some of the required packages to run our programs.
sudo apt-get install build-essential libssl-dev libyaml-dev libreadline-dev openssl curl git-core zlib1g-dev bison libxml2-dev libxslt1-dev libcurl4-openssl-dev libsqlite3-dev sqlite3
We will now make a new directory in which we will install the latest Ruby version. Run the following commands.
mkdir ~/ruby
cd ruby/
wget https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.1.tar.gz
tar -xzf ruby-2.4.1.tar.gz
cd ruby-2.4.1/
./configure
make
sudo make install
What we did above was create a Ruby directory, downloaded the latest version 2.4.1, unzipped the tar.gz, configured Ruby with our Ubuntu system—overriding the previous version of it on the system, then we configured and installed it on Ubuntu.
If you did it all right, type ruby -v in your terminal and you should get the output ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux].
Now let’s remove the directory we created because we no longer need it.
rm -rf ~/ruby
Now let’s install the Apache Web Server.
sudo apt-get install apache2
We will now get a program called Passenger which will help us run our Rails Server we are going to create later.
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
Open up the file that was just downloaded
sudo nano /etc/apt/sources.list.d/passenger.list
and place the following code within it .
deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main
Change the permissions of the files so that only root can access them.
sudo chown root: /etc/apt/sources.list.d/passenger.list
sudo chmod 600 /etc/apt/sources.list.d/passenger.list
We will now run another update that will get our Passenger server.
sudo apt-get update
We also need to install a mod that will integrate with Apache to run our Rails App.
sudo apt-get install libapache2-mod-passenger
Enable the new module using the code below, and then restart the Apache Server.
sudo a2enmod passenger
sudo service apache2 restart
We also need to install some developer dependencies for Apache which will help us verify if Passenger was installed correctly.
sudo apt-get install apache2-dev
Check to see now if Passenger was installed correctly, if it was you will see green checkmarks next to all the items. Select both Apache and Passenger when running the inspection test. If there are any issues with the installations, this validation will guide you through how to fix them.
sudo /usr/bin/passenger-config validate-install
We can now remove the old Ruby bin locations with these commands.
sudo rm /usr/bin/ruby
sudo ln -s /usr/local/bin/ruby /usr/bin/ruby
If you have a current github project, clone it now in your home directory and verify that Passenger is now running by running the following command. If you get output, you are all set. Please also not that if you have any .env files or hidden files, you will also need to import those over as well for your project to run.
sudo /usr/sbin/passenger-memory-stats
Install PostgreSQL.
sudo apt-get install postgresql postgresql-contrib
We now need to enter into the Postgres console to add a new user for creating our apps databases. Run the following commands.
sudo -i -u postgres
psql
create user "youruser" with password ‘yourpassword’;
create database "appname_production" owner "youruser";
Run the following command to set the root Postgres password.
\password
Exit out now by typing \q and then type exit to leave the PostgreSQL console. Next, install the following libraries.
sudo apt-get install python-psycopg2
sudo apt-get install libpq-dev
After installing those libraries, run sudo nano /etc/postgresql/9.5/main/pg_hba.conf and change all of the peer words to md5. This will allow our app access to create databases without needing to type in any passwords, this will also avoid future permission errors later on.
Now, let’s check out our current gem list. CD into your current app project and run the following command.
gem list
All good! Now install Rails using the following command to get the latest version.
sudo gem install rails
To verify that Rails is installed, run rails -v.
Edit your Gemfile and remove the comment in front of therubyracer so that our server can run in the background with Passenger.
sudo nano Gemfile
Then run a bundle install.
Re-update all the Ubuntu resources to prepare for the PostgreSQL installation.
sudo apt-get update
We need to create a new sites-available that will send traffic to our app and also run it with Apache Server.
sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/ yourappname.conf
Nano into the new file and delete everything that is already there, then add the following lines:
sudo nano /etc/apache2/sites-available/yourappname.conf
<VirtualHost *:80>
ServerName domain.com
ServerAlias www.domain.com
ServerAdmin domain@gmail.com
DocumentRoot /path/to/your/app/public
RailsEnv production
PassengerRuby /usr/local/bin/ruby
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory "/path/to/your/app/public">
Options FollowSymLinks
Require all granted
</Directory>
</VirtualHost>
We need to disable the default site and enable ours as the one available. Make sure you point your app to the public directory or it will not be able to find and load your app.
sudo a2dissite 000-default
sudo a2ensite yourappname
sudo service apache2 restart
You will then need to configure the test, development, and production username and passwords in your database.yml file.
nano config/database.yml
Let’s now create our databases (it may already exist from previous commands we have done, so ignore it if that’s the case) and migrate our current schemas.
rails db:create RAILS_ENV=production
rails db:migrate RAILS_ENV=production
rails db:seed RAILS_ENV=production
rails assets:precompile RAILS_ENV=production
Restart the Apache Server so that the changes will take effect.
sudo service apache2 restart
You did it! You have set up your Ubuntu 16.04 Passenger/Apache Rails Server!