Samples app to demonstrate deployment of Rail 4 app on AWS with Phusion Passenger and Nginx
- AWS(EC2, RDS, ElasticIP, AMI), Ruby 2.1.2, Rails 4.1, RVM, Phusion Passenger, Nginx, Ubuntu 14.04, MySQL, GitHub
- Update database.yml
- Add section staging
- We’ll update it with valid details later in this tutorial
- Add new environment file /config/environments/staging.rb and copy+paste content of “/environments/production.rb” file for now
- Commit and push changes in git repository
-
Go to AWS console and click on Elastic IPs in left panel in EC2 section
-
Click on "Allocate New Address" at the top of the page
-
Click on "Yes, Allocate"
-
Select newly issued Elastic IP and click on "Actions"
-
Select option "Associate Address"
-
Type Instance-Id or Name of the instance in Instance textbox
-
Select relevant Instance from dropdown
- Open bash_profile file
$ vi ~/.bash_profile
- Add below line in bash_profile file
$ alias ssh-app-server1="ssh -i ~/.ssh/key-pair.pem ubuntu@1.1.1.1" # Replace with your server ip / Elastic IP / public DNS
- Note: Ubuntu creates a default user “ubuntu” &
- Save
$ :wq
- Refresh file
$ source ~/.bash_profile
- Try Alias
$ ssh-app-server1
-
Go to AWS RDS section
-
Click on “Get started now”
-
Select engine “MySQL”
-
Select “Dev/Test” option
- Note: For testing / learning purpose, select this option as it launches RDS instance with Single availability zone.
- For production environment, prefer Multi-AZ (Availability Zone) option
-
Select DB instance class as db.t2.micro
-
Select Multi-AZ Deployment as No
-
Give valid inputs under “Setting” section for
- DB Instance Identifier, Username, Password
-
Click on “Next Step”
-
Select “VPC Security Group(s)” as default / launch-wizard-1
-
Click on “Launch”
-
Click on “View DB Instance”
-
Modify security group
- Select the RDS Instance
- Click on details icon
- Click on link of “Security Groups” value as selected in configuration wizard
-
Add new Rule
- Select security group
- Click on tab Inbound
- Click on “Edit”
- A popup opens
- Click on “Add Rule”
- Select option MYSQL/Aurora from Type dropdown
- Select option “Anywhere” from Source dropdown
- Note: It’s not advisable to allow Source as Anywhere for Production environment.
- Click on “Save”
- Copy “Endpoint” and add it as a host
- Update root user credentials (username & password) as mentioned while configuring instance
- Connect to server
$ ssh-app-server1
- Update system
$ sudo apt-get update
$ sudo apt-get install -y curl gnupg build-essential
- Rub below commands
$ 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`
-
Note: path where RVM gets installed - /usr/local/rvm/
-
set rvmsudo_secure_path=1
$ 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
- Re-login to server to activate RVM, else RVM does not work.
- We are going to install and use version 2.1.2. You can choose version you want to install
$ rvm install ruby 2.1.2
$ rvm --default use ruby 2.1.2 (set it as a default ruby version)
$ gem install bundler --no-rdoc --no-ri
- Node.js is must for Rails apps
- Run below commands to install
$ sudo apt-get install -y nodejs &&
$ sudo ln -sf /usr/bin/nodejs /usr/local/bin/node
- Verify installation by checking version. Run below command
$ node -v
- Install Phusion 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
$ sudo sh -c 'echo deb https://oss-binaries.phusionpassenger.com/apt/passenger trusty main > /etc/apt/sources.list.d/passenger.list'
$ sudo apt-get update
- Install Passenger + Nginx
$ sudo apt-get install -y nginx-extras passenger
- Enable Passenger Nginx module and Restart Nginx
- Edit /etc/nginx/nginx.conf
$ sudo vi /etc/nginx/nginx.conf
- Uncomment line “# include /etc/nginx/passenger.conf;” by removing “#” and Save file
include /etc/nginx/passenger.conf;
- Restart Nginx
$ sudo service nginx restart
- Validate installation
$ sudo /usr/bin/passenger-config validate-install
- Finally, check whether Nginx has started the Passenger core processes
$ sudo /usr/sbin/passenger-memory-stats
-
Note: You should see both Nginx processing & Passenger processes. Please refer to the passenger troubleshooting guide if result does not look like shown below
-
Check for updates of newly installed Passenger and Nginx packages
$ sudo apt-get update
$ sudo apt-get upgrade
Congratulations! Your server is now ready to deploy Rails application.
- Replace “Ubuntu” adminuser with new user with admin privileges
- Run below command to create a new user
$ sudo adduser username
- Make SSH key of ubuntu adminuser accessible to username
$ sudo mkdir -p ~username/.ssh
$ touch $HOME/.ssh/authorized_keys
$ sudo sh -c "cat $HOME/.ssh/authorized_keys >> ~username/.ssh/authorized_keys"
$ sudo chown -R username: ~username/.ssh
$ sudo chmod 700 ~username/.ssh
$ sudo sh -c "chmod 600 ~username/.ssh/*"
- Run below command to install
$ sudo apt-get install git
- Setup git
$ git config --global user.name "Your Name"
$ git config --global user.email "youremail@domain.com"
- Verify configurations
$ git config --list
- Generate SSH key to access your GitHub account from the server
- Add SSH key to your GitHub account
- Make SSH key accessible to username created as per above
$ sudo sh -c "cat $HOME/.ssh/id_rsa >> ~username/.ssh/id_rsa"
$ sudo sh -c "cat $HOME/.ssh/id_rsa.pub >> ~username/.ssh/id_rsa.pub”
- Test SSH connection with GitHub
- Prepare directory structure
$ sudo mkdir -p /var/www/yourappname
$ sudo chown username: /var/www/yourappname (make it accessible to username created as per above)
- Go to directory
$ cd /var/www/yourappname
- Clone code of your rails app. Alternatively you can use my sample app (https://github.com/rutisyrz/passenger_nginx_rails_sample_app)
$ git clone git://github.com/username/yourappname.git code
- Note: Run command “sudo chmod 777 /var/www/yourappname/” incase you get “fatal: could not create work tree dir 'code'.: Permission denied” error while cloning repository.
- Login as a new user - username
$ sudo -u username -H bash -l
- Set ruby version in RVM
$ rvm use ruby 2.1.2
- Install MySQL client package
$ sudo apt-get install mysql-client libmysqlclient-dev
- Go to app root directory
$ cd /var/www/yourappname/code
- Install bundle
$ bundle install --deployment --without development test
- ERROR: There was an error while trying to write to
*/var/www/yourappname/code/.bundle/config*
. It is likely that you need to grant write permissions for that path. Run command -
$ sudo chmod -R 777 /var/www/cloud_monitor_agent/code/.bundle/
- ERROR: While executing gem ... (Gem::FilePermissionError) Run command -
$ sudo chmod -R 777 /usr/local/rvm/gems/ruby-2.1.2
- Assuming you have updated your database.yml with valid config details. If not, please update the same
- Generate and update unique secret key for Staging environment.
- Run command
$ bundle exec rake secret
- Update config/secrets.yml file with value generated by above command
$ sudo vi config/secrets.yml
staging:
secret_key_base: <%=ENV["SECRET_KEY_BASE"]%>
- Create a log file for Staging environment with “0666” permission
$ sudo touch log/staging.log
$ sudo chmod 0666 log/staging.log
- Setup database
$ bundle exec rake db:setup RAILS_ENV=staging
$ bundle exec rake db:migrate RAILS_ENV=staging
- Compile assets
$ bundle exec rake assets:precompile RAILS_ENV=staging
- Run command
$ passenger-config about ruby-command
-
Copy path after “Command:” in result printed and paste it somewhere in text file. We’ll use it later in this tutorial
-
Go back to admin account (ubuntu) user by running a command exit
-
Create an Nginx configuration file and setup a virtual host entry that points to your app
$ sudo vi /etc/nginx/sites-enabled/yourappname.conf
- Copy + Paste below content (with proper valid formatting)
server {
listen 80;
server_name <elastic ip / ec2 public dns>;
# Tell Nginx and Passenger where your app's 'public' directory is
root /var/www/yourappname/code/public;
# Turn on Passenger
passenger_enabled on;
rails_env staging; # Add this line to run app in staging env.
passenger_ruby /ruby-path; # Replace with path copied from result as mentioned above
}
- Save file
- Restart nginx. Run command
$ sudo service nginx restart
- http://elastic ip OR ec2 public dns
- Or run command
$ curl http://elastic ipORec2 public dns
- Create Image of EC2 instance to fast-track the server config process next time when you are in need of more similar app servers
- Go to EC2 dashboard, select instance
- Click on “Action”
- Select option “Image”
- Select option “Create Image”