6 分鐘閱讀

Ubuntu 16.04 / Ruby 2.3.1 / Rails 5.0.0

Create a Linode

  • plan:
  • Ubuntu 16.04 LTS Disk
  • 256MB Swap Image

  • login user:
  • root 123456

ssh to remote side and build environment

$ ssh root@xxx.xxx.xxx.xxx
#=>  Linode > dashboard > remote access

1) update all packages

$ sudo apt-get -y update;sudo apt-get -y upgrade;sudo apt-get -y autoremove;

2) setup time zone

$ sudo dpkg-reconfigure
or 
$ sudo timedatectl set-timezone Asia/Taipei

3) Generate locales

$ sudo locale-gen zh_TW zh_TW.UTF-8 zh_CN.UTF-8 en_US.UTF-8;

4) install MySQL

setup root pw: 1234

  $ sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password password 1234';sudo debconf-set-selections <<< 'mysql-server mysql-server/root_password_again password 1234';sudo apt-get -y install mysql-server mysql-common mysql-client libmysqlclient-dev;

5) install necessary packages

	$ sudo apt-get install -y build-essential git-core bison openssl libreadline6-dev curl zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3  autoconf libc6-dev libpcre3-dev curl libcurl4-nss-dev libxml2-dev libxslt-dev imagemagick nodejs libffi-dev

6) install rvm & ruby 2.3.1

$ sudo \curl -sSL https://get.rvm.io | bash;source ~/.rvm/scripts/rvm;rvm install 2.3.1;

if Mac $ sudo \curl -sSL https://get.rvm.io | bash;source /etc/profile.d/rvm.sh;rvm install 2.3.1;

7) install nginx

$ sudo apt-get -y install nginx;

8) install Rails & bundler

$ gem install rails -v '5.0.0' -V --no-ri --no-rdoc;gem install bundler -V --no-ri --no-rdoc;

check your settings

$ date
# Wed Aug  6 10:05:17 CST 2016

$ rvm list
# =* ruby-2.3.1

$ ruby -v
# ruby 2.3.1

$ rails -v
# Rails 5.0.0

$ nginx -v
# nginx version: nginx/1.4.6 (Ubuntu)

$ mysql -u root -p
# enter pw 1234, there will goes `mysql>`, and you can type `exit` to leave 

Create database

1) login

$ mysql -u root -p

2) create database ( replace YOUR_DATABASE_NAME )

mysql> create database YOUR_DATABASE_NAME default character set utf8mb4;

3) make a check

mysql> show databases;

1) delete default setting

$ sudo rm /etc/nginx/sites-enabled/default

2) add our symlink ( replace YOUR_PEOJECT_NAME )

$ sudo ln -nfs "/home/deploy/YOUR_PROJECT_NAME/current/config/nginx.conf" "/etc/nginx/sites-enabled/YOUR_PROJECT_NAME"

3) make a check

$ ls -la /etc/nginx/sites-enabled/
# =>lrwxrwxrwx 1 root root 45 Aug  5 12:06 kixERP -> /home/deploy/YOUR_PROJECT_NAME/current/config/nginx.conf 

add a deploy user

1) setup your password (other information you can just enter to pass )

$ adduser deploy

2) Add user deploy to group sudo

$ gpasswd -a deploy sudo

close root login

1) find “PremitRootLogin” , change from yes to no

$ vim /etc/ssh/sshd_config

2) restart ssh service

$ service ssh restart

login by user deploy

1) setup ssh-key login

ssh deploy@xxx.xxx.xxx.xxx 'mkdir -p ~/.ssh;cat >> ~/.ssh/authorized_keys' < ~/.ssh/id_rsa.pub

If not work.. Maybe you should login first (ssh deploy@xxx.xxx.xxx.xxx) And answer ‘yes’ to add the host fingerprint to the ~/.ssh/known_hosts Then try again..

2) login

ssh deploy@xxx.xxx.xxx.xxx

ssh-key generate

1) generate ssh-key

$ ssh-keygen

2) copy the public key

$ cat ~/.ssh/id_rsa.pub

3) paste the key into your github or bitbucket

  • github
  • Bitbucket - YOUR_PROJECT_NAME / Settings / Deployment keys

Setup Capistrano

1) setup Gemfile

  - gem 'sqlite3'
  + gem 'sqlite3', group: :development
  
  - # gem 'therubyracer', platforms: :ruby
  
  + gem 'therubyracer', platforms: :ruby
  
  + group :development do
  +   gem 'capistrano',         '~> 3.6.0', require: false
  +   gem 'capistrano-rvm',     '~> 0.1',   require: false
  +   gem 'capistrano-rails',   '~> 1.1.7', require: false
  +   gem 'capistrano-bundler', '~> 1.1.4', require: false
  +   gem 'capistrano3-puma',   '~> 1.2.1', require: false
  + end
  
  + group :production do
  +   gem "mysql2"
  + end
$ bundle install
$ cap install  
# => ask for installing other package? no

2) modify Capfile

# Load DSL and set up stages
require "capistrano/setup"
# Include default deployment tasks
require "capistrano/deploy"

require 'capistrano/rails'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/puma'

# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

3) replace config/deploy.rb

# config valid only for current version of Capistrano

set :repo_url,        'git@github.com: YOUR_GIT_ACCOUNT/YOUR_PROJECT_NAME'
set :application,     'YOUR_PROJECT_NAME'
set :user,            'deploy'
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)}/#{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/database.yml 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

desc 'Upload to shared/config'
  task :upload do
  on roles (:app) do
    upload! "config/database.yml", "#{shared_path}/config/database.yml"
    upload! "config/secrets.yml",  "#{shared_path}/config/secrets.yml"
  end
end

before :starting,  :check_revision
after  :finishing, :compile_assets
after  :finishing, :cleanup
after  :finishing, :restart
end

desc "Run rake db:seed on a remote server."
task :seed do
  on roles (:app) do
    within release_path do
      with rails_env: fetch(:rails_env) do
      	execute :rake, "db:seed"
      end
    end
  end
end

# ps aux | grep puma    # Get puma pid
# kill -s SIGUSR2 pid   # Restart puma
# kill -s SIGTERM pid   # Stop puma

4) modify config/deploy/production.rb

set :stage, :production
set :branch, :master

role :app, %w(deploy@xxx.xxx.xxx.xxx)
role :web, %w(deploy@xxx.xxx.xxx.xxx)
role :db, %w(deploy@xxx.xxx.xxx.xxx)

set :rails_env, "production"
set :puma_env, "production"
set :puma_config_file, "#{shared_path}/config/puma.rb"
set :puma_conf, "#{shared_path}/config/puma.rb"

5) create config/nignx.conf

	upstream puma-YOUR_PROJECT_NAME {
	  server unix:///home/deploy/YOUR_PROJECT_NAME/shared/tmp/sockets/YOUR_PROJECT_NAME-puma.sock;
	
	}
	
	server {
	  listen 80 default_server deferred;
	  # server_name example.com;
	
	  root /home/deploy/YOUR_PROJECT_NAME/current/public;
	  access_log /home/deploy/YOUR_PROJECT_NAME/current/log/nginx.access.log;
	  error_log /home/deploy/YOUR_PROJECT_NAME/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-YOUR_PROJECT_NAME;
	
	  }
	
	  error_page 500 502 503 504 /500.html;
	  client_max_body_size 10M;
	  keepalive_timeout 10;
	}

6) modify .gitignore

+ /config/database.yml
+ /config/secrets.yml
  • copy to *.sample
    • config/database.yml -> config/database.yml.sample
    • config/secrets.yml -> config/secrets.yml.sample
  • delete
    • config/database.yml
    • config/secrets.yml

7) first commit

$ git add .
$ git commit -m "ready to deploy"
$ git push origin master

8) add ymls back and modify

* copy 
 - config/database.yml.sample -> config/database.yml 
 - config/secrets.yml.sample -> config/secrets.yml


config/database.yml
  production:
  -  <<: *default
  -  database: db/production.sqlite3
  +  adapter: mysql2
  +  encoding: utf8mb4
  +  database: YOUR_PROJECT_NAME
  +  pool: 5
  +  username: root
  +  password:
  +  socket: /var/run/mysqld/mysqld.sock
config/secrets.yml
-  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
+  secret_key_base: e4a98dd1063a6765xxxxxxx # copy from development or test secret_key_base

First Deploy

1) check deploy

$ cap production deploy:check
if it shows database.yml does not exist, don't worry about that. just go next step to copy yml.

2) upload database.yml and secrets.yml from ssh( not git )

$ cap production deploy:upload

3) initial deploy

$ cap production deploy:initial

4) rake db:seed

$ cap production seed

Normal deploy

$ git add .
$ git commit -m "commit message"
$ git push origin master
$ cap production deploy	

Open your website

open your site by ip

http://xxx.xxx.xxx.xxx

if failure, just ssh to Server for log

$ ssh deploy@xxx.xxx.xxx.xxx
$ tail -f /home/deploy/YOUR_PROJECT_NAME/current/log/production.log

參考

  1. kakas/CapistranoDeployTest
  2. [(Mini Course) Deploy Rails Project to Linux Server Growth School](http://courses.growthschool.com/courses/deploy-rails-project-to-linux-server)
  3. [Deploying a Rails App on Ubuntu 14.04 with Capistrano, Nginx, and Puma DigitalOcean](https://www.digitalocean.com/community/tutorials/deploying-a-rails-app-on-ubuntu-14-04-with-capistrano-nginx-and-puma)

更新時間:

留言