September 13,2006

[Ruby 筆記] Rails 於 lighttpd 上的設定

這篇主要是根據昨晚設定時的 try and error 的經驗寫出來的。

Ruby on Rails 基本上可以藉由 Fastcgi 套用到各種 Web server 上,像是 Apache 或者 lighttpd 等,其中 Ruby on Rails 的作者又大力推崇 lighttpd,它有效能好、擴充性佳以及精簡等優點,它還有個號稱的優點 - 容易設定,不過昨晚我在嘗試設定 Ruby on Rails 時倒是常常碰壁,我想主要是幾個問題吧,第一,大部分的文件都不夠詳細,常常只見一個設定檔,也沒見裡頭有什麼詳細的說明,依樣畫葫蘆後,出了問題還是搞不太懂,第二,沒有足夠的 debug information,lighttpd 是可以對 fastcgi 設定 debug level,但是一開始設定時我經常遇到的問題都是我不知道有沒有跑進我的設定中,nothing,只好 try and error 慢慢踹。希望我這篇筆記對同樣要作此設定的人有幫助。

[目的]
我設定檔的目的很簡單,我的機器沒有多個域名,只有一個,假設叫做 www.myruby-test.com,在這個域名上,我想掛上多個 Ruby on Rails apps,例如我想掛上 wiki、blog 等 apps,我想採用的作法是利用多個第一層目錄來區別不同的 app,例如 http://www.myruby-test.com/wiki/ 或者 http://www.myruby-test.com/blog/ 等,但是 Ruby on Rails 是以目錄名稱來代表 Controller 或 Action,所以利用了第一層目錄名稱會造成某種干擾,這解決方法後面會提到。

[安裝]
先安裝好 Ruby、Gems、Ruby on Rails 等,這些安裝方法請參考 Ruby on Rails Official Web site

請安裝好 lighttpd,安裝方法請參考 lighttpd Official Web site

安裝 fastcgi 。

安裝 Ruby Fastcgi binding ,Debian 或者 Ubuntu 用者可以直接下以下命令安裝:
% apt-get install libfcgi-ruby1.8

[建立 Rails App]
舉例來說,我想建立一個 Rails App 於 /var/rails/ 目錄下,假設名叫叫做 wiki 的 app 好了,使用以下命令:
% cd /var/rails/; rails wiki

建立幾個基本的 Controller,例如 Hello:
% cd wiki; script/generate controller Hello

[設定 lighttpd]
假設我的 lighttpd 設定檔在 /etc/lighttpd/lighttpd.conf ,我的設定如下(我挑選幾個重要的 section):

server.modules              = (
            "mod_access",
            "mod_alias",
            "mod_accesslog",
            "mod_fastcgi",
            "mod_rewrite",
            "mod_redirect",
)
server.document-root       = "/var/www/"
server.errorlog            = "/var/log/lighttpd/error.log"
accesslog.filename         = "/var/log/lighttpd/access.log"
index-file.names           = ( "index.php", "index.html",
                               "index.htm", "default.htm", "dispatch.fcgi" )
server.username            = "www-data"
server.groupname           = "www-data"
### FASTCGI
fastcgi.server = ( ".php" => ((
                     "bin-path" => "/usr/bin/php-cgi",
                     "socket" => "/tmp/php-fastcgi.socket",
                     "max-procs" => 1,
                     "bin-environment" => (
                       "PHP_FCGI_CHILDREN" => "16",
                       "PHP_FCGI_MAX_REQUESTS" => "10000"
                     ),
                     "bin-copy-environment" => (
                       "PATH", "SHELL", "USER"
                     ),
                     "broken-scriptfilename" => "enable"
                 ))
                )

$HTTP["url"] =~ "^/wiki/" {
        server.document-root = "/var/rails/wiki/public"
        server.error-handler-404 = "/dispatch.fcgi"
        fastcgi.server = ( ".fcgi" =>
                ( "localhost" => (
                        "bin-path" => "/var/rails/wiki/public/dispatch.fcgi",
                        "socket" => "/tmp/wiki-rails.socket",
                        "min-procs" => 1,
                        "max-procs" => 10
                )))
        fastcgi.debug = 1
}
server.modules 是設定要 lighttpd 載入的 modules,我們需要 fastcgi、rewrite跟redirect module,為什麼?照作就對了。

在 index-file.names 中加一個 dispatch.fcgi 檔名。

最後加上一組 vhost 設定,這應該是 lighttpd 獨特的設定方式吧,妳可以藉由 request 的 URL 或 host 來判斷該載入哪個 module,在這裡我設定了一組 $HTTP["url"] =~ "^/wiki/"  設定,這很酷,看的懂這是什麼意思嗎?這代表著如果進來的 request uri 是以 wiki 目錄開頭就會符合這組設定,後面的 "^/wiki" 是符合 perl 的 regular expression。然後在這 vhost 設定中,我們要另外設定 document root,以及 error handler,document root 必須是 Rails app 下的 public 目錄,因為他最重要的 fastcgi despatch 程式在這個目錄下。而 error-handler-404 則指向 "/dispatch.fcgi" ,當遇到找不到的路徑或檔案時,可以通通交由這隻程式去判斷。

最後就是要設定一組 fastcgi 設定,在這個設定中,我們需要指定以 ".fcgi" 最為結尾的檔名都交由這組設定去處理,也就是交由 Rails app 中的 dispatch.fcgi 去處理。在這 fastcgi 中,妳必須設定 bin-path,也就是 dispatch.fcgi,妳可以在妳 Rails app 的 public/ 目錄下找到,此外,lighttpd 與 fastcgi 是透過 Unix domain socket 溝通的,所以妳還要給他個檔案作為 socket,這個檔案最好是在所有人都可以寫入的地方,例如 "/tmp" 就是個好地方。再來要指定 processes 數量,這是指 fastcgi 的 processes 數量,數量越多的話,在流量大時,處理速度越快,但反之是,如果你設太大,流量又沒那麼多時,只是突耗 CPU 跟 memory 而已,自己評估衡量一下吧。

為什麼要作這樣的設定?事實上我也不是很瞭解,但是我猜測,因為 Rails 的 URL 都是以路徑構成,在 index-file 中加入個 dispatch.fcgi 會讓純路徑的 URL 去找尋這個檔案,這個檔案的附檔名便會符合 fastcgi 中的設定,並去透過 socket 去 query 真正的 dispatch.fcgi,而這隻程式就是 Rails  fastcgi 的 核心,由他來 dispatch commands。

[設定 Rails]
這樣就好了嗎?重跑 lighttpd 後,妳可以嘗試打開 browser 去瀏覽 http://www.myruby-test.com/wiki/ ,妳會得到 Application Error 錯誤訊息,為什麼?記得前面提過的 Rails 目錄名稱是有意義的吧? "/wiki/" 會被  Rails 當作 Controller 去處理,所以 我們還需要對 Rails app 作設定,找到 config 目錄下的routes.rb 檔,找到並更改下設定:

map.connect 'wiki/:controller/service.wsdl', :action => 'wsdl'
map.connect 'wiki/:controller/:action/:id'
See? 妳要跟 Rails 講,我前面還有一層 wiki 路徑啊,不要誤判了,這時候妳去存取 http://www.myruby-test.com/wiki/hello/ 就可以看到你想要的結果了。此外,妳要開放妳 Rails app 下的 tmp 目錄的權限,在我的例子中,lighttpd 是以 www-data 這個 uid 執行,而 Rails 會寫一些暫存檔至 tmp/ 目錄下,在我的範例中就是 /var/rails/wiki/tmp,所以最好將這個目錄以及子目錄的 owner uid 改為 www-data,否則 Rails 會無法寫入一些暫存檔而造成錯誤。

[參考文件]
事實上,在妳安裝完 Ruby 後,就有一份 lighttpd.conf 可以參考了,妳可以找一下: /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/configs/lighttpd.conf ,它是 Rails 用來跑 server 時的設定檔,也可以拿來參考。




Posted by syshen at 樂多Roodo! │13:06 │回應(5)引用(0)Programming
樂多分類:網路/3C 共同主題:網頁設計 工具:編輯本文
Ads by Roodo! 

引用URL

http://cgi.blog.roodo.com/trackback/2141166
回應文章
其實你只要使用 ruby script/server lighttpd ,他就會把 /usr/lib/ruby/gems/1.8/gems/rails-1.1.6/configs/lighttpd.conf
copy 到您的 config/lighttpd.conf
Posted by thegiive at September 13,2006 17:12
感激,這個我知道,不過我 lighttpd 並不是只拿來跑這 app, 也拿來跑其他 php 等,所以我希望用同一設定檔來 host 不同的 Rails app 。
Posted by syshen at September 13,2006 17:53
不過還是感恩
你這篇解決我對於 single host multi app 的問題
我將您的重點紀錄在這邊
如果你感覺到不快可以告訴我
我會砍掉
Posted by thegiive at September 13,2006 18:48
不會不會,謝謝你的引用 :-)
Posted by syshen at September 13,2006 19:26
Hello , 這個作法,CSS 跟圖片會顯示不出來。解法請到 Lighttpd 的 Rails加 PHP 設定 (相同 Domain不同目錄)底下去看。
Posted by thegiive at November 9,2006 08:42