This documentation takes you through the process of configuration required to host a Rails application on a EC2 instance. The tutorial uses Nginx + Passenger on the server. The sample application used in this guide can be found here
-
Open AWS Console
-
After you signin into your developer account, you should see a list of AWS services. From the the services find Compute and select EC2 from there.
-
Choose
Ubuntu Server 16.04 LTS
from the list of AMI (Amazon Machine Image): -
Choose an instance type. For purposes of this demo - choose
t2.micro
: -
Keep on clicking Next: .... from Step 3 to Step 5 in the dashboard. On "Step 6: Configure A Security Group", there:
- Click on
Add Rule
button and add a new rule forHTTP
by selectingHTTP
from the dropdown. - In the Source column click on the dropdown and choose Anywhere so that you can ssh into your instance from any local machine.
- Click on
At the end of this step, your console should look something like this:
-
Click on Review and Launch and then click on Launch on next screen. You will prompted to create a new publick key which will be used to SSH into your instance. After your create a new public key, hit Download Key Pair.
-
At this point, you have succesfully launched an AWS EC2 instance. Click on View Instances to see your newly deployed instance.
Open a terminal of your choice and type the following command. Replace the xx.xx.xx.xx
with your Public IP from the dasboard. The default usernames provided by EC2 are admin
, ubuntu
and ec2-user
:
$~ >> ssh -i ~/path/to/your-pem-file.pem ubuntu@xx.xx.xx.xx
If you get an error saying "permission too open", then change the permissions on the file by typing:
$~ >> chmod 400 your-pem-file.pem
If everything went well you should be able to ssh
int your server successfully.
- Update and Upgrade the package manager
apt
:
$~ >> sudo apt update && sudo apt upgrade
- Install build
curl
,gpg
andbuild-essentials
packages. Note: Since Ubuntu 16.04 LTS's realease, you can now useapt
instead ofapt-get
! You are free to choose either:
$~ >> sudo apt install -y curl gnupg build-essential
- Install RVM (Ruby Version Manager):
$~ >> sudo gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
$~ >> curl -sSL https://get.rvm.io | sudo bash -s stable
$~ >> sudo usermod -a -G rvm `whoami`
- Confirm
rvm
was installed by typingrvm --version
. If you don't see the following output, logout of your instance and login again and then try the command:
- Run the following commands, to make sure the environment variable
rvmsudo_secure_path
is set to1
. On macOS it is found that, the following command is needed to set the correct environment variable to avtivatervm
:
$~ >> if sudo grep -q secure_path /etc/sudoers; then sudo sh -c "echo export rvmsudo_secure_path=1 >> /etc/profile.d/rvm_secure_path.sh" && echo Environment variable installed; fi
- Install Ruby:
$~ >> rvm install ruby
$~ >> rvm --default use ruby
The above command installs the latest version of the ruby. To install a specific version you can do:
$~ >> rvm install ruby-2.3.0
$~ >> rvm --default use ruby-2.3.0
If Ruby was installed correctly, you can check its version by running the following command: ruby -v
and playing around with the Interactive Ruby Console (irb):
Bundler is a popular tool for managing application gem dependencies. To install run the following command:
$~ >> gem install bundler --no-rdoc --no-ri
Rails uses NodeJS to precompile the asset pipeline. To install Node:
$~ >> sudo apt-get install -y nodejs &&
sudo ln -sf /usr/bin/nodejs /usr/local/bin/node
Passenger is an open source web application server for Ruby. It handles HTTP requests, manages processes and resources, and enables administration, monitoring and problem diagnosis. Passenger is very easy to use, makes deploying in production much easier and is scalable.
To install Passenger on your EC2 instance follow the commands below:
- Install Passenger's PGP Key and add HTTPS support for APT:
$~ >> sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 561F9B9CAC40B2F7 &&
sudo apt-get install -y apt-transport-https ca-certificates
- Add Passenger's APT repository:
$~ >> sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger xenial main > /etc/apt/sources.list.d/passenger.list' && sudo apt-get update
- Install Passenger + Nginx
$~ >> sudo apt-get install -y nginx-extras passenger
- Now we will enable Passenger Nginx module:
sudo nano /etc/nginx/nginx.conf
- Uncomment the line in the
http
block by removing the#
symbol, that says:# include /etc/nginx/passenger.conf;
- To save the file press:
Ctrl+O
=> Press the enter key =>Ctrl+X
- If you do not see a
http
block, add it yourself:
http {
include /etc/nginx/passenger.conf
}
$~ >> sudo service nginx restart
-
If everything went well and Nginx with Passenger was installed correctly, you should see the following page when you visit your EC2 instance's public IP:
-
Validate if Passenger was installed or not correctly:
- Add new user:
$~ >> sudo adduser abhi
- Give new user
sudo
permissions:
$~ >> sudo visudo
A editor will open up, find root ALL=(ALL:ALL) ALL
under User privilege section
and add the following line:
root ALL=(ALL:ALL) ALL
abhi ALL=(ALL:ALL) ALL
To save the file press: Ctrl + O
=> Hit enter to save the file name => Ctrl+Y
- Issue the following command to get the public key. Copy the output of the command, we will use this in th next step.
$~ >> cat ~/.ssh/authorized_keys
- Create a
.ssh
directory and make a fileauthorized_keys
there and set correct permissions on them:
- Edit the
~/.ssh/authorized_keys
file by:
$~ >> nano ~/.ssh/authorized_keys
-
Paste the public key you copied on step 1 here and save the file and exit.
-
Enter
exit
twice to exit out of the server. -
If everything worked correctly, you should now be able to log in to your server by the new user you created!
Note: Creating a new user is very important, as the root user doesn't throw any confirmation messages when you run commands - which can be dangerous. The new user has to always use sudo
which asks for password and saves us from any wrong command being issued.
I have already deployed my project on Github, since it is easier to transfer files from a git server than using FTP, but you may suit yourself.
Note: The commands henceforth are written from the new user account and not the root user, unless otherwise mentioned
- Install Git:
$~ >> sudo apt install -y git
- Make a new directory under
/var/www
and clone the project there:
$~ >> sudo mkdir /var/www/photosite-webapp
$~ >> sudo chown your-new-user-name: /var/www/photosite-webapp
- Clone your project from github into
/var/www/photosite-webapp
with correct user permissions:
$~ >> sudo -u your-new-user-name -H git clone https://your-github-project-url
If everything worked correctly, you should now have your project's code on your server:
- If you're already not inside your project directory, then go into your project directory:
$~ >> cd /var/www/photosite-webapp/Project-Name-On-Github
$~ >> ls
- Make sure your
Gemfile
has the followinggem sqlite3
outside of all the groups and then run the following commands (libpq-dev
is used to install native extensions forpg
gem) :
$~ >> sudo apt-get install libpq-dev
$~ >> bundle install --deployment --without development test
$~ >> sudo nano config/database.yml
- Rails also needs a unique secret key with which to encrypt its sessions. Starting from Rails 4, this secret key is stored in
config/secrets.yml
. But first, we need to generate a secret key. Run:
$~ >> bundle exec rake secret
This command will output a secret key, copy that and put it inside config/secrets.yml
's production
section:
- Change the security permissions on DB and
secrets.yml
file:
$~ >> chmod 700 config db
$~ >> chmod 600 config/database.yml config/secrets.yml
- Run the following command to precompile assets and run migrations:
$~ >> bundle exec rake assets:precompile db:migrate RAILS_ENV=production
- Determin the ruby command that Passenger should use:
$~ >> passenger-config about ruby-command
Please copy the path given for the Command
variable, for me it looks like this:
Command: /usr/local/rvm/gems/ruby-2.4.0/wrappers/ruby
- Create a new file
photosite-webapp.conf
under/etc/nginx/sites-enabled/
:
$~ >> sudo nano /etc/nginx/sites-enabled/photosit-webapp.conf
Please note that, on the line passenger_ruby
- put whatever you copied on Step 1 of this section and on the line server_name
put your EC2 instance's public IP or if you have a DNS, put it's name there.
- Finally, restart the server:
$~ >> sudo service nginx restart
If everything worked correctly, visit your Public IP of EC2 (for me): 34.208.175.125
- and you should see your app running!
Unfortunately if you faced errors, type the following command to see the error logs:
$~ >> sudo tail -n 20 /var/log/nginx/error.log
Screenshots from the live app: