Ubuntu 16.04.3 + Apache 2.4.18 + Puma + Ruby 2.5.0 + Rails 5.1.5 + PostgreSQL (未完成)

2017.6.5

Local 端開發、測試

我的 local 開發端是 Max OS 10.13,參考 Install Ruby on Rails – Mac OS X

創建新的 rails 專案,假設專案名稱為 xxx

$ rails new xxx

在 rails 專案資料夾下建檔 .ruby-version 及 .ruby-gemset

$ echo "ruby-2.5.0" > .ruby-version
$ echo "rails5" > .ruby-gemset

開始在 development 環境開發、測試。

Local 端安裝、設定 Capistrano

edit local Gemfile

group :development do
  gem "capistrano", "~> 3.10", require: false
  gem "capistrano-rails", "~> 1.3", require: false
end
group :production do
  gem 'pg'
end

安裝

bundle install --without production

Capistrano 初始化

cd [ProjectRoot]
cap install

Capfile

編輯 Capfile

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

deploy.rb

在 config/deploy.rb 裡設定共用資訊 (假設專案名稱為 xxx)

set :application, 'xxx'
set :repo_url, 'git@gitlab.com:dila/xxx.git'
set :rvm_custom_path, '/usr/share/rvm'
set :deploy_to, '/project/path/on/server'
set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')

append :linked_files, 'config/database.yml', 'config/secrets.yml'

append :linked_dirs, 'db/import'

namespace :deploy do

task :restart do

on roles(:web), in: :sequence do

execute :touch, release_path.join('tmp/restart.txt')

end

end

end

後面我們會在 server 上使用 apt-get 方式將 rvm 安裝在 /usr/share/rvm,

capistrano 不會自動偵測到,所以要用 rvm_custom_path 設定。

上面的 deploy_to 是 server 上要放置本專案的路徑。要在 server 上把這個資料夾建好。

預設會在 /var/www/xxx,如果同預設值,就不必設這個參數。

linked_files, 會建一個 symbolic link 由 current/config/database.yml 指到 shared/config/database.yml.

如果有 static files 放在 public 裡,例如 public/images,那也要加入 linked_dirs:

append :linked_dirs, 'db/import', 'public/images'

production.rb

編輯 config/deploy/production.rb

server 'example.com.tw', user: 'UserName', roles: %w{web}
set :rvm_ruby_version, '2.4.1@rails51'

上面的 example.com.tw 要換成 server 的網址。

UserName 要換成連上 server 的 user name.

把 application 放上 GitLab

如果專案是公開的,也可以選擇用 GitHub,因為我的專案不是對外公開的,所以選擇用 GitLab 的 private project.

在 gitlab 新建一個 project,如果 gitlab project owner 不是自己,那要將自己的 gitlab 帳號加入這個 gitlab project 的 members,Project Access 設為 Master,這樣待會才能 push.

在 local 端將 rails app project 初始化為 git repository

cd [ProjectRoot]

git init

gitignore

編輯 .gitignore 設定哪些東西不要放進 git

/public/data/*
/config/database.yml
/config/secrets.yml
/db/import
.DS_Store

我的某些專案裡,使用 public/data 放供下載的檔案,這些檔案不必放上 git。如果沒用到,可以不必設。

database.yml 裡面有密碼,不要放上 git.

secrets.yml 裡面有 secret key,也不放上 git.

我的某些專案裡,使用 /db/import 放一些要匯入資料庫的檔案,這些檔不放上 git。如果沒用到,可以不必設。

.DS_Store 是 mac 產生的檔,也可以使用以下命令設為 global ignore:

git config --global core.excludesfile '~/.gitignore_global'

push

在 project root 下執行以下命令,push 到 gitlab:

git add .
git commit -m 'first commit'
git remote add origin git@gitlab.com:xxx/xxx.git
git push -u origin master

上面的 git@gitlab.com:xxx/xxx.git 要改成真正的 git repository path.

Server 安裝 apache

安裝 Ubuntu 過程中就選擇安裝 apache server.

Server 安裝 rvm, ruby, rails

安裝 rvm

rvm 可以安裝在 user home 目錄下,或是安裝成 system wide,選擇安裝為 system wide,參考:Ubuntu package for RVM

要新增 PPA repositories 需要 software-properties-common,如果還沒安裝的話,要執行:

sudo apt-get install software-properties-common

Add the PPA and install the package

sudo apt-add-repository -y ppa:rael-gc/rvm
sudo apt-get update
sudo apt-get install rvm

現在自己應該已經是 rvm group 的成員,登出再登入,讓一些設定生效。

rvm 會被安裝在 /usr/share/rvm

安裝 ruby

參考 Install Ruby on Rails – Ubuntu

rvm install 2.5.0

安裝 Node.js

sudo apt-get install nodejs

Gems

更新 Gem Manager

$ gem update --system

RVM’s Global Gemset

$ rvm gemset use global
$ gem update

Faster Gem Installation

設定安裝 ruby gem 時不要安裝 documentation

$ echo "gem: --no-document" >> ~/.gemrc

Install Bundler

$ gem install bundler

把 Nokogiri 安裝在 Global gemset

$ gem install nokogiri

install rails

建立 gemset

rvm gemset create rails5

切換 gemset,並設為預設的 gemset

rvm use 2.5.0@rails5 --default

安裝 rails 5.1.5

gem install rails -v 5.1.5

如果希望在 server 上執行 rake 命令時都是 production mode, 可以編輯 ~/.bashrc

export RAILS_ENV=production

安裝 gem pg

如果不先安裝 libpq-dev 的話,安裝 pg 會有問題。

sudo apt-get install libpq-dev
gem install pg

PostgreSQL 設定

查看目前 server 上的 PostgreSQL 版本:

psql --version

安裝 PostgreSQL

sudo apt-get update
sudo apt-get install postgresql postgresql-contrib

設定主機上的 PostgreSQL 資料庫。

新增資料庫 user

參考:PostgreSQL add or create a user account and grant permission for database

sudo adduser pg_xxx

上面的 pg_xxx 請改為真正的 user name, 通常我都是在 pg_ 後面加上專案名稱。

執行過程中要設定密碼,假設密碼設為 1234,後面會用到這個密碼。

新增 database, 並設權限

change to the postgres unix user

sudo su - postgres

執行

psql
create user pg_xxx with password '1234';
create database xxx;
grant all privileges on database xxx to pg_xxx;
ALTER DATABASE xxx OWNER TO pg_xxx;
ALTER USER pg_xxx CREATEDB;
\q

上面的 xxx 請改為專案名稱。

要給 create database 的權限,才能執行 rake db:reset。(如果沒有 create database 權限,db:reset 在 create database 時會失敗,但是好像也沒關係,因為它還是重建所有 table,而且在 create database 之前,通常 drop database 就會失敗了,因為有其他 connection 存在。)

切換為原 user

exit

測試連線

sudo su - pg_xxx
psql -d xxx -U pg_xxx

成功後,輸入 \q 離開 psql,輸入 exit 切換回原 user。

在 server 上安裝 git

Ubuntu 16.04.3 預設已經有 git,如果還沒有的話,可以執行以下命令安裝:

$ sudo apt-get update
$ sudo apt-get install git

將 rails project 從 Local 端 deploy 到 server 上

ssh private key 要放在 ~/.ssh 裡面,這樣才能由 server 連到 gitlab 取得 source.

設權限,取消其他使用者的權限,否則以下步驟會有錯誤:

chmod 600 ~/.ssh/id_rsa

前面 config/deploy.rb 裡有設 deploy_to,這是 server 上要放本專案路徑,要先建好。並且把自己設為 owner.

sudo mkdir -p /var/www/MyApp
sudo chown MyAppUser: /var/www/MyApp

上面的 MyApp 要改為專案名稱,MyAppUser 改為使用者 id,www-data 是使用者群組。

把自己加入 www-data 群組(把 xxx 改為 user id):

sudo usermod -a -G www-data xxx

查看 www-data 群組內有哪些使用者

getent group groupname

然後在 local 端 project root 下執行

cap production deploy


它會在 server 端建立專案資料夾,但是它會抱怨找不到 database.yml。

設定 database.yml

rails 根據 database.yml 來連上資料庫。下一步在 server 上的 project root 建立 shared/config/database.yml

production:
  adapter: postgresql
  encoding: unicode
  database: xxx
  host: localhost
  pool: 5
  username: pg_xxx
  password: 1234

設定 secrets.yml

把 local 端的 config/secrets.yml 傳到 server 端 shared/config/secrets.yml

在 local 端執行 rake secret 得到一個新的 secret key

把這個新的 secret key 寫到 shared/config/secrets.yml

production:
  secret_key_base: xxxxxxxxxx

在 local 端再次執行

cap production deploy

這次應該就可以完成了。

資料庫初始化

一開始可能需要手動在 server 上 project root 的 current 資料夾裡執行:

rake db:migrate

設定 apache

決定 Passenger 要使用的 Ruby

執行以下命令:

$ passenger-config about ruby-command

得到如下結果:

passenger-config was invoked through the following Ruby interpreter:

  Command: /home/ray/.rvm/gems/ruby-2.4.0@rails5/wrappers/ruby
  Version: ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-linux]
  To use in Apache: PassengerRuby /home/ray/.rvm/gems/ruby-2.4.0@rails5/wrappers/ruby
  To use in Nginx : passenger_ruby /home/ray/.rvm/gems/ruby-2.4.0@rails5/wrappers/ruby
  To use with Standalone: /home/ray/.rvm/gems/ruby-2.4.0@rails5/wrappers/ruby /usr/bin/passenger start
## Notes for RVM users
Do you want to know which command to use for a different Ruby interpreter? 'rvm use' that Ruby interpreter, then re-run 'passenger-config about ruby-command'.

把上面「To use in Apache」的這段複製起來,下面會用到:

PassengerRuby /home/ray/.rvm/gems/ruby-2.4.0@rails5/wrappers/ruby

網址是獨立 DNS

例如 http://xxx.dila.edu.tw

新增 /etc/apache2/sites-available/xxx.conf,內容範例:

<VirtualHost *:80>
  ServerName xxx.dila.edu.tw
  DocumentRoot /var/www/xxx/current/public
  PassengerRuby /home/ray/.rvm/gems/ruby-2.4.1@rails51/wrappers/ruby
  <Directory "/var/www/xxx/current/public">
    Options FollowSymLinks
    Require all granted
  </Directory>
</VirtualHost>

enable

 sudo a2ensite xxx

重新啟動 apache

sudo service apache2 restart

網址使用 subdirectory

例如 http://xxx.dila.edu.tw/SubURI

假設 rails project root: /var/www/ProjectName/current

編輯 /etc/apache2/sites-available/ProjectName.conf

Alias /SubURI /var/www/ProjectName/current/public
<Location /SubURI>
  PassengerBaseURI /SubURI
  PassengerAppRoot /var/www/ProjectName/current
  PassengerRuby /home/ray/.rvm/gems/ruby-2.4.0@rails5/wrappers/ruby
</Location>
<Directory /var/www/ProjectName/current/public>
  Allow from all
  Options -MultiViews
  Require all granted
</Directory>

編輯 /etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
  ...

Include sites-available/ProjectName.conf

</VirtualHost>

重新啟動 apache2

sudo service apache2 restart