赫謙小便籤

Rails Based on Unicorn + Nginx on Ubuntu Linux @ Linode

這篇文章是從原本「赫謙隨筆(Posterous)」中轉過來的,所以內文是一樣的。

最近在配置公司主機,其實說真的好像在自討苦吃一樣,在推薦Linode之前原本也考慮過AWS,但是因為不熟所以不敢去碰只好選了Linode … 而且Linode其實也不錯就是了:P

Okay,閒話休提,我來講講配置這整個環境的主要流程一下 … 我選的是Linode 1024方案(記憶體配1023 MB給我是哪招?),一開始用32bit的系統但覺得好像效能有點差,所以後來重切硬碟裝上Ubuntu 11 64bit的系統 … (結果記憶體吃更大囧”)

總之,先選好你要的Linux OS,然後根據XDite的Rails 101看Ubuntu配置,不過phpMyAdmin那邊可以跳過不看,passenger也不必裝,這邊用的是Nginx + Unicorn。

記得,不要用apt-get的方式安裝nginx,所以直接上 nginx.org 抓最新stable的版本下來,然後根據這段configure參數來編譯

nginx configure with arguments
1
./configure   --prefix=/usr   --conf-path=/etc/nginx/nginx.conf   --pid-path=/var/run/nginx.pid   --lock-path=/var/lock/nginx.lock   --http-log-path=/var/log/nginx/access.log   --error-log-path=/var/log/nginx/error.log   --http-client-body-temp-path=/var/lib/nginx/body   --http-proxy-temp-path=/var/lib/nginx/proxy   --http-fastcgi-temp-path=/var/lib/nginx/fastcgi   --http-uwsgi-temp-path=/var/lib/nginx/uwsgi   --http-scgi-temp-path=/var/lib/nginx/scgi   --with-http_ssl_module   --with-http_stub_status_module   --user=nginx   --group=nginx   --without-mail_pop3_module   --without-mail_imap_module   --without-mail_smtp_module --with-http_gzip_static_module; make && make install

如果你有什麼要調整的再自己去調整,然後編譯完nginx後我們就可以裝unicorn了,裝unicorn就gem i unicorn就好。

關於nginx的設定,可以上網找找,我這邊大多是用預設值的,而虛擬主機的部分看底下設定檔

nginx conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
upstream demoapp {
  server unix:/tmp/app.sock fail_timeout=0;
}

server {
  listen 80;

  root /path/to/app/current/public;
  server_name app.domain.com;
  access_log /var/log/nginx/app-access.log;
  error_log /var/log/nginx/app-error.log;
  rewrite_log on;

  location / {
    proxy_redirect off;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    if (!-f $request_filename) {
      proxy_pass http://demoapp;    }
  }


  location ~* (stylesheets|javascripts|images) {
    if (!-f $request_filename) {
      break;
    }
    if ($query_string ~* "^[0-9]{10}$") {
      expires max;
      break;
    }
  }

  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /path/to/app/current/public;
  }
}

因為我會用Capistrano來deploy,所以路徑最後一定是 current/public ,建議不要想要去改預定的東西,那只是找麻煩而已 …

之後存檔離開,我們要把這個虛擬主機檔案丟在 /etc/nginx/sites-avaliable 底下,然後

ln -s /etc/nginx/sites-avaliable/demoapp /etc/nginx/sites-enabled/

下個指令

$ service nginx restart

restart nginx沒有用 … 或者/etc/init.d/nginx restart也可以

到此,nginx的設定就搞定了,我們就可以做其他的東西了 …

記得,deploy千萬不要用root哦,哪天被打到哭了不要說我沒有講 … =.=

切換到負責deploy的身分上(記得這身分不要給sudoer permission),然後在家目錄開一個資料夾叫做 configs,建立兩個檔案: database.yml.production 跟 database.yml.production.demoapp

會這樣做是因為database.yml.production可以拿來當skel檔案,有新的app的時候只要copy過去修改內容即可 …

接著在本地端在config中新增一個unicorn.rb

unicorn.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
app_root = "/root/path/of/app"
app_name = "demoapp"
listen "/tmp/app.sock", :backlog => 2048 #這邊要跟nginx虛擬主機檔中upstream內定義的務必一樣
worker_processes 4 #看情況開
preload_app false
timeout 30

module Rails
  class <<self
    def root
      File.expand_path(__FILE__).split('/')[0..-3].join('/')
    end
  end
end
_working_directory = File.join(app_root, app_name, "current")
working_directory _working_directory
logs_path = "#{_working_directory}/log"
pid "#{_working_directory}/tmp/pids/unicorn.pid"
stderr_path "#{logs_path}/unicorn.stderr.log"
stdout_path "#{logs_path}/unicorn.stdout.log"

GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true

before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!

  old_pid = "#{Rails.root}/tmp/pids/unicorn.pid.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      puts "Send 'QUIT' signal to unicorn error!"
    end
  end
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
end

存檔離開,扔入git並且push過後就可以準備deploy了,deploy搞定之後基本上就成功了 ….

這邊講得很簡陋,不過因為是公司的主機的關係,所以我一定得講得很簡陋XD 不過大致上的流程都講完了,就也只是這樣子而已 … 下一篇再來講怎樣透過Capistrano去Deploy …

最近Github釋出了Hubot,我也還沒有時間去看呢 … 有人要分享怎樣做嗎XDDD

之後我會再貼上我配置主機的方式,希望有人願意share心得一起交流

Comments