Ubuntu 16.04.2 + Apache 2.4.18 + Passenger + Ruby 2.4.1 + Rails 5.1.1 + PostgreSQL
2017.6.5
Local 端開發、測試
安裝 rvm
$ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
$ \curl -sSL https://get.rvm.io | bash -s stable
使用 rvm 安裝 ruby 2.4.1
$ rvm install 2.4.1
將 2.4.1 設為 ruby 預設版本
$ rvm --default use 2.4.1
檢視 ruby 版本
$ ruby -v
新建一個 gemset 叫為 rails51
$ rvm gemset create rails51
把 rails51 設為預設的 gemset
$ rvm use 2.4.1@rails51 --default
安裝 rails 5.1.1
$ gem install rails -v 5.1.1
檢視 rails 版本
$ rails --version
創建新的 rails 專案,假設專案名稱為 xxx
$ rails new xxx
在 rails 專案資料夾下建檔 .ruby-version 及 .ruby-gemset
$ echo "ruby-2.4.1" > .ruby-version
$ echo "rails51" > .ruby-gemset
開始在 development 環境開發、測試。
Local 端安裝、設定 Capistrano
edit local Gemfile
group :development do
gem 'capistrano-rails'
gem 'capistrano-rvm'
gem 'capistrano-passenger'
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'
require 'capistrano/passenger'
deploy.rb
在 config/deploy.rb 裡設定共用資訊 (假設專案名稱為 xxx)
set :application, 'xxx'
set :repo_url, 'git@gitlab.com:dila/xxx.git'
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
上面的 deploy_to 是 server 上要放置本專案的路徑。要在 server 上把這個資料夾建好。
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
在 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 安裝 passenger
參考 Installing Passenger + Apache on Ubuntu 16.04 LTS (with APT)
Server 安裝 rvm, ruby, rails
按照 Installing Ruby with RVM 說明安裝 RVM, Ruby, Node.js
設定安裝 ruby gem 時不要安裝 documentation, 編輯 ~/.gemrc
gem: --no-document
Check the Gem Manager
$ gem update --system
把 Nokogiri 安裝在 Global gemset
$ rvm gemset use global
$ gem update
$ gem install nokogiri
建立 gemset
rvm gemset create rails51
切換 gemset
rvm 2.4.1@rails51
安裝 rails 5.1.1
gem install rails -v 5.1.1
如果希望在 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
$ 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 上要放本專案路徑,要先建好。然後在 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