Friday, 21 October 2016

Steps And Commands For RoR Application Deployment On Linode Server

I deployed my Ruby-on-Rails application on a cloud server.

About a couple of years ago, I got into this practice of hosting my applications on the cloud. At that time AWS did not offer Ubuntu machines. I love Ubuntu so I did not go to AWS. I also have this feeling that access and deployment procedures on the biggies (AWS and Azure) are slightly more cumbersome than the not-so-biggies. Amongst these, Site5 is the cheapest but I don't get root access and was very disappointed with their lack of support. For $20 a month, I got a 4 GB RAM server on Linode compared to 2 GB RAM on Digital Ocean. Hence I went with Linode.

I am the lone fella who designed and coded my application. Hence I have not yet started using a git server, either on-premise or cloud. Since my MacBook has Time Machine enabled on to my external hard disk, I get some sort of primitive version control. So my deployment procedure is to simply ftp my code to the server and restart the process. In this post I am sharing the steps and commands I followed.

Of course, as the application and team size grow, a better methodology would be to put the code on git branch, merge into master, either pull or push it to the cloud server, build and start the server. These steps can be automated with the help of tools like Capistrano.

My tech stack is Ruby, Rails, RVM, MySQL, Nginx and Phusion Passenger. The two articles that give all details are:
I had to do a few things and note a few other useful commands in addition to those given in these two articles. So, here we go.

Remote login and create a user with name deploy
$ ssh root@my_ipaddress
--> Enter root password

Create user
$ sudo adduser deploy
password : my_password
$ sudo adduser deploy sudo
$ exit

MacBook: setup ssh keys
$ ssh-keygen -t rsa
--> Press enter key
--> Enter passphrase
--> Enter same passphrase again

$ ssh-copy-id deploy@my_ipaddress

$ ssh deploy@my_ipaddress
Enter passphrase
Check Remember password in my keychain

$ sudo apt-get update
$ 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 python-software-properties libffi-dev

$ sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
$ gpg --keyserver hkp:// --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
$ curl -sSL | bash -s stable
$ source ~/.rvm/scripts/rvm
$ rvm install 2.3.1
$ rvm use 2.3.1 --default
$ ruby -v
$ gem install bundler

$ sudo apt-key adv --keyserver hkp:// --recv-keys 561F9B9CAC40B2F7
$ sudo apt-get install -y apt-transport-https ca-certificates
$ sudo sh -c 'echo deb xenial main > /etc/apt/sources.list.d/passenger.list'
$ sudo apt-get update
$ sudo apt-get install -y nginx-extras passenger

$ sudo apt-get install mysql-server mysql-client libmysqlclient-dev
username: root
password: my_password

$ sudo vi /etc/nginx/sites-enabled/default
server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

  server_name my_ipaddress;
  passenger_enabled on;
  rails_env    production;
  root         /home/deploy/myapp/public;

  # redirect server error pages to the static page /50x.html
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   html;
$ sudo vi /etc/nginx/nginx.conf
# Phusion Passenger config
# Uncomment it if you installed passenger or passenger-enterprise
include /etc/nginx/passenger.conf;

$ sudo mkdir myapp
$ cd myapp

Code in local folder should have mail configuration.
$ vi config/environments/production.rb
  config.action_mailer.default_url_options = {host: 'localhost', port: 80}
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :authentication => :plain,
    :address => "",
    :port => 587,
    :domain => "",
    :user_name => "",
    :password => "my_encrypted_password",
    :enable_starttls_auto => true
Launch FileZilla
Host : sftp://my_ipaddress -- Username: deploy -- Password: my_password
ftp all folders in local app folder (except tmp) to server: /home/deploy/myapp

Cloud Server
$ sudo service mysql start
$ mysqladmin -u root -pmy_password variables | grep socket
$ vi config/database.yml
--> socket: /var/run/mysqld/mysqld.sock (output from the previous mysqladmin command)
$ bundle install
$ rake db:create RAILS_ENV=production
$ rake db:migrate RAILS_ENV=production

$ rake assets:precompile RAILS_ENV=production
rake aborted!
Devise.secret_key was not set. Please add the following to your Devise initializer:
  config.secret_key =

$ vi config/initializers/devise.rb
config.secret_key = horribly_long_encrypted_key
$ rake assets:precompile RAILS_ENV=production

$ rake secret RAILS_ENV=production
$ vi config/secrets.yml

$ vi config/environments/production.rb
  # config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present?
  config.serve_static_files = true
  config.assets.digest = true
$ sudo service nginx start

Open Chrome browser, url http://my_ipaddress

Post Script
In case you want to do it all over again,
login as root, stop nginx, delete user, purge nginx

$ pgrep -u deploy
$ ps -f --pid $(pgrep -u deploy)
$ killall -9 -u deploy
$ deluser --remove-home deploy

$ sudo apt-get purge nginx-extras passenger
$ sudo apt-get purge nginx-common
$ sudo apt-get autoremove

References for these additional steps:

1 comment: