Hướng dẫn deploy rails app lên vps


Xin chào các bạn,hôm nay mình xin hướng dẫn cách deploy một rails app lên vps để chạy trên môi trường production.
Trong bài viết này mình sẽ mặc định là các bạn đã có một vps rồi nhé,còn cách làm thế nào để đăng ký được một vps thì các bạn lên google và tự search nhé.Oke rồi nhé,chúng ta cùng bắt đầu nào.

1.Chuẩn bị server.

Mình sử dụng vps của google để làm ví dụ trong bài viết này nhé.Để làm việc được thuận lợi nhất sau khi truy cập được vào vps,việc đầu tiên là nên tạo các tài khoản để tiện cho việc deploy sau này nhé.Sau khi ssh được vào vps thực hiện tạo tài khoản như sau

 sudo adduser quanbh  
 sudo nano /etc/sudoers  

Sau khi mở file sudoers lên sẽ giống như thế này



Bạn tiến hành add user vào file này và set quyền cho nó,như của mình thì đã thêm dòng %quanbh ALL=(ALL) ALL vào file.Rồi nhấn ctrl + x để save lại file.

Tiếp theo nếu các bạn muốn mỗi khi ssh vào server mà k phải nhập password thì chỉ cần gõ các lệnh sau.

 su <user_name>
 mkdir .ssh  
 sudo chmod 700 .ssh  
 nano ~/.ssh/authorized_keys  
 sudo chmod 600 ~/.ssh/authorized_keys  

Đầu tiên swich sang user của mình tiếp theo tạo thư mục .ssh và cấp quyền,tạo file authorized_keys thêm public key của máy các bạn vào file authorized_keys này,sau đó save lại và cấp quyền cho file này.

Để tạo được pulic key của máy mình(máy local của các bạn nhé) các bạn bật terminal lên và gõ vào lệnh sau:

 ssh-keygen -t rsa -C "your.email@example.com" -b 4096  

Sau khi tạo xong pulic key để lấy giá trị của nó và paste vào file authorized_keys trên servere thì gõ lệnh sau

 cat ~/.ssh/id_rsa.pub  

Sau khi đã add public key của mình vào server thì những lần đăng nhập sau chỉ cần ssh vào như sau

 ssh <user_name>@<ip_server>  

Oke chúng ta đã làm xong công tác chuẩn bị và có một server để thực hành deploy rồi nhé, tiếp theo chúng ta sẽ tiến hành cài đặt môi trường cho chính server này nhé.

2.Cài đặt môi trường cho server.

Đầu tiên tiến hành cài đặt các dependencies cho rails như sau:

 curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -  
 curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -  
 echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list  
 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 software-properties-common libffi-dev nodejs yarn  

Tiếp theo cài đặt RVM

 sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev  
 gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB  
 curl -sSL https://get.rvm.io | bash -s stable  
 source ~/.rvm/scripts/rvm  
 rvm install 2.4.1  
 rvm use 2.4.1 --default  
 ruby -v  

Cài đặt bundle và Rails

 gem install rails -v '5.1.6'  
 gem install bundler  

Cài đặt SQL,trong hướng dẫn này mình sử dụng mongodb để chạy rails app nhé.và hđh của server là ubuntu 16.04

 sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4  
 echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list  
 sudo apt-get update  
 sudo apt-get install -y mongodb-org  
 sudo service mongod start  

Cài đặt Nginx,như đã trình bày ở bài trước nginx sẽ là webserver đứng trước app server là puma của mình nhé

 sudo apt-get update  
 sudo apt-get install curl git-core nginx -y  
 sudo service nginx start  

Cài đặt git

 apt-get update  
 apt-get install git-core  
 git --version  

Add public key server các bạn vào git,các bạn sẽ thấy bước này giống cái ban đầu mình làm,ở bước trên chúng ta add public key của máy các bạn vào server bước này chúng ta add pulic key server các bạn vào git thôi.(nhớ là chúng ta đang ở trên server nhé,các bước này mình đang tạo cho server)

  ssh-keygen -t rsa -C "your.email@example.com" -b 4096   
  cat ~/.ssh/id_rsa.pub   

Copy đoạn mã dài ngoằng và vào webiste git và add vào như sau

Phù...!cuối cùng cũng đã cài xong đống dependencies cho server.Tiếp theo chúng ta sẽ setup cho rails project nhé.Hiện tại có thể 2 cách để deploy lên server đó là đưa project lên server và tiến hành deploy hoặc để ở máy local của bạn và deploy lên server.Trong bài viết này mình hướng dẫn deploy từ máy local lên server nhé.

3.Setup project ở máy local.

Các bạn mở project của mình lên thêm các gem sau vào gemfile.

 group :development do  
  gem 'capistrano',     require: false  
  gem 'capistrano-rvm',   require: false  
  gem 'capistrano-rails',  require: false  
  gem 'capistrano-bundler', require: false  
  gem 'capistrano3-puma',  require: false  
  gem 'rack-mini-profiler'  
  gem 'capistrano-shoryuken'  
 end  

Tiếp theo thực hiện bundle các gem trên và chạy lệnh install capichano.

 bundle  
 cap install  

Điều này sẽ tạo ra các file sau:
  • Capfile trong thư mục gốc của Rails app
  • deploy.rb file trong thư mục config 
  • thư mục deploy trong thư mục config
Thay thế nội dung của Capfile như sau:

 # Load DSL and set up stages  
 require "capistrano/setup"  
 # Include default deployment tasks  
 require "capistrano/deploy"  
 require "capistrano/scm/git"  
 install_plugin Capistrano::SCM::Git  
 require 'capistrano/rails'  
 require 'capistrano/bundler'  
 require 'capistrano/rvm'  
 require 'capistrano/puma'  
 install_plugin Capistrano::Puma  
 # Load custom tasks from `lib/capistrano/tasks` if you have any defined  
 Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }  

Thay thế nội dung của file config/deploy.rb

 server '1.52.48.121', port: 22, roles: [:web, :app, :db], primary: true  
 set :repo_url,    'git@github.com:quanbh/radatracking.git'  
 set :application,   'radareporter'  
 set :user,      'devcs18'  
 set :puma_threads,  [4, 16]  
 set :puma_workers,  0  
 # Don't change these unless you know what you're doing  
 set :pty,       true  
 set :use_sudo,    false  
 set :stage,      :production  
 set :deploy_via,   :remote_cache  
 set :deploy_to,    "/home/#{fetch(:user)}/apps/#{fetch(:application)}"  
 set :puma_bind,    "unix://#{shared_path}/tmp/sockets/#{fetch(:application)}-puma.sock"  
 set :puma_state,   "#{shared_path}/tmp/pids/puma.state"  
 set :puma_pid,    "#{shared_path}/tmp/pids/puma.pid"  
 set :puma_access_log, "#{release_path}/log/puma.error.log"  
 set :puma_error_log, "#{release_path}/log/puma.access.log"  
 set :ssh_options,   { forward_agent: true, user: fetch(:user), keys: %w(~/.ssh/id_rsa.pub) }  
 set :puma_preload_app, true  
 set :puma_worker_timeout, nil  
 set :puma_init_active_record, true # Change to false when not using ActiveRecord  
 ## Defaults:  
 # set :scm,      :git  
 set :branch,    :master  
 # set :format,    :pretty  
 # set :log_level,   :debug  
 # set :keep_releases, 5  
 ## Linked Files & Directories (Default None):  
 #set :linked_files, %w{config/secrets.yml}  
 # set :linked_dirs, %w{bin log tmp/pids tmp/cache tmp/sockets vendor/bundle public/system}  
 namespace :puma do  
  desc 'Create Directories for Puma Pids and Socket'  
  task :make_dirs do  
   on roles(:app) do  
    execute "mkdir #{shared_path}/tmp/sockets -p"  
    execute "mkdir #{shared_path}/tmp/pids -p"  
   end  
  end  
  before :start, :make_dirs  
 end  
 namespace :deploy do  
  desc "Make sure local git is in sync with remote."  
  task :check_revision do  
   on roles(:app) do  
    unless `git rev-parse HEAD` == `git rev-parse origin/master`  
     puts "WARNING: HEAD is not the same as origin/master"  
     puts "Run `git push` to sync changes."  
     exit  
    end  
   end  
  end  
  desc 'Initial Deploy'  
  task :initial do  
   on roles(:app) do  
    before 'deploy:restart', 'puma:start'  
    invoke 'deploy'  
   end  
  end  
  desc 'Restart application'  
  task :restart do  
   on roles(:app), in: :sequence, wait: 5 do  
    invoke 'puma:restart'  
   end  
  end  
  # before :starting,   :check_revision  
  after :finishing,  :compile_assets  
  after :finishing,  :cleanup  
  after :finishing,  :restart  
 end  
 # ps aux | grep puma  # Get puma pid  
 # kill -s SIGUSR2 pid  # Restart puma  
 # kill -s SIGTERM pid  # Stop puma  

có các điểm lưu ý các bạn phải đổi đó là

 server '1.52.48.121', port: 22, roles: [:web, :app, :db], primary: true  
 set :repo_url,    'git@github.com:quanbh/radatracking.git'  
 set :application,   'radareporter'  
 set :user,      'devcs18'  
 set :branch,   :master
  • server: là tên server của các bạn muốn deploy lên,
  • repo_url: là địa chỉ nơi các bạn chứa source nhé
  • application: là tên app
  • user: là user mà lúc đầu tạo để deploy ấy
  • branch: là nhánh mà bạn sẽ kéo source code về
Tiếp theo tạo file config/nginx.conf và thêm nội dung như sau

 upstream puma {  
  server unix:///home/<user_name>/apps/<appname>/shared/tmp/sockets/<appname>-puma.sock;  
 }  
 server {  
  listen 80 default_server deferred;  
  # server_name example.com;  
  root /home/<user_name>/apps/<appname>/current/public;  
  access_log /home/<user_name>/apps/<appname>/current/log/nginx.access.log;  
  error_log /home/<user_name>/apps/<appname>/current/log/nginx.error.log info;  
  location ^~ /assets/ {  
   gzip_static on;  
   expires max;  
   add_header Cache-Control public;  
  }  
  try_files $uri/index.html $uri @puma;  
  location @puma {  
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
   proxy_set_header Host $http_host;  
   proxy_redirect off;  
   proxy_pass http://puma;  
  }  
  error_page 500 502 503 504 /500.html;  
  client_max_body_size 10M;  
  keepalive_timeout 10;  
 }  

Phần lớn công việc đã xong,bước tiếp theo là deploy ứng dụng nào.:D

4.Deploy Rail App

Đầu tiên chúng ta cần đẩy source code lên git(bây giờ bạn đang ở máy local đấy nhé).

 git add -A  
 git commit -m "Set up Puma, Nginx & Capistrano"  
 git push origin master  

Ở lần sử dụng git đầu tiên có thể git sẽ yêu cầu các bạn config như sau

 git config --global user.name 'Your Name'  
 git config --global user.email you@example.com  

Tiếp theo chạy lệnh sau

 cap production deploy:initial  

Có thể có lỗi trong lần đầu tiên bạn deploy nhưng các bạn sẽ được thông báo lỗi,các bạn cứ google mà fix nhé.Sau khi deploy xong các bạn ssh vào server chạy lệnh sau:

 sudo rm /etc/nginx/sites-enabled/default  
 sudo ln -nfs "/home/<user>/apps/appname/current/config/nginx.conf" "/etc/nginx/sites-enabled/appname"  

Sau khi sửa đổi file nginx thì cũng phải restart lại service nhé

 sudo service nginx restart  

Oke vậy là xong rồi đấy,các bạn có thể hưởng thành quả được rồi.Sau đó nếu mỗi lần các bạn code thêm chức năng muốn deploy lại chỉ cần thêm các thay đổi lên git và tiến hành deploy lại như sau.

 git add -A  
 git commit -m "Deploy Message"  
 git push origin master  
 cap production deploy  

Xem thành quả sau khi deploy nào :)


Đây chỉ mới là bước đưa ứng dụng của bạn lên server thôi nhé còn phần trỏ domain về server thì hôm nào có thời gian mình sẽ viết thêm một bài nhé.Mình xin phép dừng bài viết tại đây,Cám ơn các bạn đã theo dõi.

Tài liệu tham khảo:
https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04
https://gorails.com/deploy/ubuntu/16.04


Nhận xét

Bài đăng phổ biến từ blog này

Cài đặt SSL cho website sử dụng certbot

Xây dựng một hệ thống comment real-time hoặc chat đơn giản sử dụng Pusher

CÁC BÀI TẬP SQL CƠ BẢN - PART 1

Xây dựng một hệ thống tracking hành vi người dùng (phần 1)

Xây dựng một hệ thống tracking hành vi người dùng (phần 2)

Enterprise architecture trên 1 tờ A4

Web caching (P2)

Bàn về async/await trong vòng lặp javascript

Web caching (P1)

Cài đặt môi trường để code website Rails