LigHttpd - 輕量級網頁伺服器

1、前言

LigHttpd 為一輕量級 Web Server,設計目的以安全、快速、小巧為主要設計理念,以 FastCGI 來支援 PHP。

LigHttpd 支援常用 Web 功能如下:
  • virtual hosts
  • virtual directory listings
  • URL-Rewriting, HTTP-Redirects
  • automatic expiration of files
  • Large File Support (64bit fileoffsets)
  • Ranges (start-end, start-, -end, multiple ranges)
  • on-the-fly output-compression with transparent caching (deflate, gzip, bzip2)
  • authentication (basic, digest, plain files, htpasswd, htdigest, ldap)
  • fast and secure application controlled downloads
  • Server Side Includes
  • User Tracking
  • FastCGI, CGI, SSI

LigHttpd 針對 PHP 支援:
  • same speed as or faster than apache + mod_php4
  • includes a utility to spawn FastCGI processes (neccesary for PHP 4.3.x)
  • via FastCGI and CGI interface
  • support Code Caches like Turckmm, APC or eaccelarator
  • load-balanced FastCGI (one webserver distibutes request to multiple PHP-servers via FastCGI)

LigHttpd 支援安全性作法如下:
  • chroot(), set UID, set GID
  • protecting docroot 
  • strict HTTP-header parsing



文章目錄

1、前言
2、實作環境
3、安裝及設定
          步驟1.安裝 lighttpd 套件
          步驟2.安裝 php5 套件
          步驟3.修改 lighttpd 設定檔 (lighttpd.conf)
          步驟4.設定 /etc/rc.conf
          步驟5.啟動 lighttpd 服務
4、參考
5、Me FAQ
          Q1.(configfile.c.1081) base-docroot doesn't exist: /usr/local/www/data/?
          Q2.(mod_accesslog.c.514) opening access-log failed: Permission denied /var/log/lighttpd.access.log?
          Q3.裝了 lighttpd 及 php 後無法連 mysql?
          Q4.(network.c.159) socket failed: Protocol not supported?
          Q5.(network.c.300) can't bind to port: 0.0.0.0 80 Address already in use?
          Q6.點選 .cgi 變成下載視窗?
          Q7.Unrecognized character \x7F at /home/web/nagios/cgi-bin/tac.cgi line 1.?
          Q8.cronolog 無法套用在 lighttpd.error.log 上?
          Q9./var/run/lighttpd/php-fastcgi.socket-0 No such file or directory?



2、實作環境

  • FreeBSD 6.x-RELEASE
  • lighttpd-1.4.x



3、安裝及設定

步驟 1. 安裝 lighttpd 套件

切換至 Ports Tree 路徑安裝 lighttpd 套件。
cd /usr/ports/www/lighttpd     //切換至安裝路徑
make install clean             //安裝套件並清除暫存檔案




步驟 2. 安裝 php5 套件

切換至 Ports Tree 路徑安裝 php5 套件。
cd /usr/ports/lang/php5          //切換至安裝路徑
make install clean               //安裝套件並清除暫存檔案

修改 php.ini-dist 來支援 FastCGI
; cgi.fix_pathinfo=0              //預設值
cgi.fix_pathinfo=1                //修改後




步驟 3. 修改 lighttpd 設定檔 (lighttpd.conf)

修改 lighttpd 設定檔 (lighttpd.conf) 設定檔內容都很直覺以下僅說明要支援如下需求的修改內容。
  • PHP (FastCGI)
  • Perl (CGI Module)
  • Using Authentication - Methods digest 所做的修改

步驟 3-1. 支援 PHP (FastCGI)

修改 lighttpd 設定檔 (lighttpd.conf) 內容使其支援 PHP Language (FastCGI)。
vi /usr/local/etc/lighttpd.conf
 server.modules = (
                   "mod_fastcgi",  //將此行註解移除 (支援 FastCGI)
                  )
#### fastcgi module                //將下列這幾行的註解移除
 fastcgi.server             = ( ".php" =>                              
                               ( "localhost" =>
                                 (
                                   "socket" => "/tmp/php-fastcgi.socket",
                                   "bin-path" => "/usr/local/bin/php-cgi"
                                 )
                               )
                              )


步驟 3-2. 支援 Perl (CGI Module)

修改 lighttpd 設定檔 (lighttpd.conf) 內容使其支援 Perl Language (CGI Module)。
vi /usr/local/etc/lighttpd.conf
 server.modules = (
                   "mod_cgi",    //將此行註解移除 (支援 CGI Module)
                  )
#### CGI module                  //將下列這幾行的註解移除
 cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
                                ".cgi" => "/usr/bin/perl" )

步驟 3-3. 支援 Authentication (Methods digest)

修改 lighttpd 設定檔 (lighttpd.conf) 內容使其支援 Using Authentication - Methods digest,其功能為類似 Apache .htaccess 保護功能,以下為簡述設定方式詳細內容可參考 Docs:ModAuth - lighttpd - Trac
vi /usr/local/etc/lighttpd.conf
 server.modules = (
                   "mod_auth",   //將此行註解移除 (支援 Auth Module)
                  )
#### auth module
 auth.backend                   = "htdigest"                  //使用 username, realm, md5 password backend
 auth.backend.htdigest.userfile = "/home/web/.lighttpdpwd"    //指定身份認證檔存放路徑
 auth.require                   = ( "/nagios" =>              //指定需要身份認證的網頁路徑
                                   (
                                    "method"  => "digest",    //指定認證方式
                                    "realm"   => "Authentication Nagios Login",   //認證視窗說明文字
                                    "require" => "valid-user" //.lighttpdpwd內定義的認證使用者
                                   )
                                  )

修改完 lighttpd 設定檔 (lighttpd.conf) 之後接下來就是建立認證密碼檔案及設定可進行登入的使用者帳號密碼,而 Lighttpd 的 htdigest 與 Apache 的 htpasswd 其不同點僅為對於密碼部份進行加密的方式不同而以,若您系統有安裝 Apache Distribution 則可使用這二個指令,若未安裝 Apache Distribution 的話可使用 hash、md5 指令來達成 htdigest 功能。
  • htdigest (Lighttpd):使用 md5 對密碼部份進行加密
  • htpasswd (Apache):使用 crypt 對密碼部份進行加密

建立密碼檔方式一、直接使用 htdigest 指令 (有安裝 Apache Distribution)
如下指令為功能為,因為剛才在 lighttpd.conf 設定檔中指定的認證方式為 digest 而其認證的條件有三項 (username,realm,md5 password),所以等一下使用 htdigest 指令時其指定的 realm 文字要與 lighttpd.conf 設定檔中的 realm 所指定的文字 相同,否則屆時將造成認證失敗。
  • 建立密碼檔案: /home/web/.lighttpdpwd
  • 認證文字 (realm): Authentication Nagios Login
  • 使用者帳號: weithenn
htdigest -c /home/web/.lighttpdpwd 'Authentication Nagios Login' weithenn
 Adding password for weithenn in realm Authentication Nagios Login.
 New password:            //輸入使用者帳號 weithenn 的密碼
 Re-type new password:    //再次確認密碼

設定完成後可查看認證檔案的內容其排列順序為 username : realm : md5 password
cat home/web/.lighttpdpwd
 weithenn:Authentication Nagios Login:c3a5d217851ae00b0692deeaa2546d3f


建立密碼檔方式二、使用 hash、md5 指令 (未安裝 Apache Distribution mod_auth_digest)
利用 hash 及 md5 指令撰寫而成的 htdigest.sh 利用它來建立認證密碼檔案及設定使用者帳號密碼,所以可不需要安裝 mod_auth_digest 且產生與 htdigest 指令效果相同的認證密碼檔案。請建立 htdigest.sh 檔案內容如下
vi htdigest.sh         //建立 htdigest.sh 內容如下
 #!/bin/sh
 user=$1
 realm=$2
 pass=$3
 hash=`echo -n "$user:$realm:$pass" | /sbin/md5 | cut -b -32`
 echo "$user:$realm:$hash"
chmod +x htiegest.sh   //給予 htdigest.sh 執行的權限

建立 htdigest.sh 檔案完成後便可開始建立 lighttpd 認證密碼檔案,其輸入順序為使用者帳號 (User)、認證視窗說明文字 (realm)、使用者密碼 (password-hash),如下指令即為將這三者輸出字串寫入至認證密碼檔案內。值得注意的地方為若要新增第二個使用者記得使用 >> 來導入不然會將認證密碼檔案內容全部覆蓋掉。
  • 建立密碼檔案: /home/web/.lighttpdpwd
  • 認證文字 (realm): Authentication Nagios Login 
  • 使用者帳號: weithenn
./htdigest.sh 'weithenn' 'Authentication Nagios Login' '123456' > /home/web/.lighttpdpwd     //建立第一個使用者
./htdigest.sh 'jiakai' 'Authentication Nagios Login' '456789' >> /home/web/.lighttpdpwd     //建立第二個使用者


步驟 3-4. 限制 IP 網段存取網站

簡單來說當您想允許或阻擋某些 IP 網段來存取網站時可以在設定檔中加入如下設定即可達到限制的目的。

限制單一 IP 網段允許/禁止存取網站
 $HTTP"remoteip" == "192.168.1.0/24" {   //僅禁止 192.168.1.0 網段,其它網段皆可存取
       url.access-deny = ( "" )
 }
 $HTTP"remoteip" != "192.168.1.0/24" {   //僅允許 192.168.1.0 網段,其它網段皆禁止存取
       url.access-deny = ( "" )
 }

限制多個 IP 網段允許/禁止存取網站
 $HTTP"remoteip" =~ "192.168.1.0/24|192.168.2.0/24" {  //僅禁止 192.168.1.0、192.168.2.0 網段,其它網段皆可存取
       url.access-deny = ( "" )
 }
 $HTTP"remoteip" !~ "192.168.1.0/24|192.168.2.0/24" {  //僅允許 192.168.1.0、192.168.2.0 網段,其它網段皆禁止存取
       url.access-deny = ( "" )
 }

限制單一 IP 網段允許存取網站某個目錄 (例如 後台)
 $HTTP"remoteip" != "192.168.1.0/24" {                 //僅允許 192.168.1.0 網段能存取 http://www.weithenn.org/admin,其它網段皆禁止存取此路徑
    $HTTP"url" =~ "^/admin/" {
      url.access-deny = ( "" )
    }
 }




步驟 4. 設定 /etc/rc.conf

修改 /etc/rc.conf 以便系統重新開機時能自動載入 Lighttpd 服務。
vi /etc/rc.conf
 lighttpd_enable="YES"        //加入此行




步驟 5. 啟動 lighttpd 服務

在啟動 Lighttpd 服務以前請先建立 Lighttpd Log 檔,因為 Lighttpd 服務預設並沒有寫入 /var/log 的權限,因此 Log 檔須事先建立否則啟動 Lighttpd 服務時將會因為 Log 檔無法建立而發生錯誤。
cd /var/log                         //切換路徑至 log
touch lighttpd.{access,error}.log   //建立 access 及 error 的 log 檔案
chown www /var/log/lighttpd.*       //改變 log owner
chmod 666 /var/log/lighttpd.*       //改變 log 權限

建立好相關 Log 檔後就可鍵入下列指令來啟動 Lighttpd 服務吧。
/usr/local/etc/rc.d/lighttpd start  //啟動 Lighttpd 服務
檢查一下 Lighttpd 服務是否啟動成功
sockstat |grep www
 www      lighttpd   25128 4  tcp4   *:80                  *:*
 www      php-cgi    48312 0  stream /tmp/php-fastcgi.socket-3
 www      php-cgi    48311 0  stream /tmp/php-fastcgi.socket-3
 www      php-cgi    48310 0  stream /tmp/php-fastcgi.socket-2
 www      php-cgi    48309 0  stream /tmp/php-fastcgi.socket-2
 www      php-cgi    48308 0  stream /tmp/php-fastcgi.socket-1
 www      php-cgi    48307 0  stream /tmp/php-fastcgi.socket-1
 www      php-cgi    48306 0  stream /tmp/php-fastcgi.socket-0
 www      php-cgi    48305 0  stream /tmp/php-fastcgi.socket-0




4、參考




5、Me FAQ

Q1. (configfile.c.1081) base-docroot doesn't exist: /usr/local/www/data/?

Error Message:
無法啟動 Lighttpd 服務並出現如下錯誤訊息
/usr/local/etc/rc.d/lighttpd start
 Starting lighttpd.
 2006-09-25 17:20:51: (configfile.c.1081) base-docroot doesn't exist: /usr/local/www/data/
 2006-09-25 17:20:51: (server.c.553) setting default values failed

Ans:
我忘了指定網站根目錄,而其預設值為 /usr/local/www/data 但此目錄並不存在,因此啟動 lighttpd 時出現錯誤,修改後即可順利啟動 lighttpd 服務。



Q2. (mod_accesslog.c.514) opening access-log failed: Permission denied /var/log/lighttpd.access.log?

Error Message:
無法啟動 Lighttpd 服務並出現如下錯誤訊息
/usr/local/etc/rc.d/lighttpd start
 Starting lighttpd.
 2006-09-25 17:25:27: (mod_accesslog.c.514) opening access-log failed: Permission denied /var/log/lighttpd.access.log
 2006-09-25 17:25:27: (server.c.834) Configuration of plugins failed. Going down.

Ans:
原因在於 Lighttpd 服務預設並沒有寫入 /var/log 的權限,因此其 Log 檔須事先建立否則啟動 Lighttpd 時服務將會因為 Log 檔無法建立而發生錯誤。
touch /var/log/lighttpd.access.log   //建立 access log 檔
touch /var/log/lighttpd.error.log    //建立 error log 檔
chown www /var/log/lighttpd.*        //改變 log owner
chmod 666 /var/log/lighttpd.*        //改變 log 權限




Q3. 裝了 lighttpd 及 php 後無法連 mysql?

Error Message:
裝完 Lighttpd 及 PHP 開啟本來能連結 MySQL 的 PHP 程式後卻出現如下錯誤訊息顯示無法連接 MySQL?
Call to undefined function: mysql_connect()
Ans:
在 Google 上找到此篇討論 lighttpd forum - FastCGI+MySQL 後即可解決此一問題,先將 lighttpd 服務停止,若此時 /tmp 內還有 FastCGI sockets 存在則請刪除,刪除之後再度重新啟動 Lighttpd 服務後即可順利連結 MySQL 了。



Q4. (network.c.159) socket failed: Protocol not supported?

Error Message:
無法啟動 Lighttpd 服務並出現如下錯誤訊息?
/usr/local/etc/rc.d/lighttpd start
 Starting lighttpd.
 2007-04-25 10:11:33: (network.c.159) socket failed: Protocol not supported

Ans:
問題在於 lighttpd 設定檔 lighttpd.conf 內有個選項 Enable IPV6,但此次實作的主機其核心 (Kernel) 已經把 options INET6 項目註解掉,所以便出現 Protocol not supported 此次解決方法為將 lighttpd.conf 內 Enable IPV6 選項註解即可,當然您也可修改您的核心開啟支援 IPv6 項目後再重新編譯核心即可。
vi /usr/local/etc/lighttpd.conf
 server.use-ipv6 = "enable"       //預設值
 #server.use-ipv6 = "enable"      //修改後 (註解該項目)




Q5. (network.c.300) can't bind to port: 0.0.0.0 80 Address already in use?

Error Message:
無法啟動 Lighttpd 服務並出現如下錯誤訊息?
/usr/local/etc/rc.d/lighttpd start
 Starting lighttpd.
 2007-04-25 10:32:40: (network.c.300) can't bind to port: 0.0.0.0 80 Address already in use

Ans:
問題在於 lighttpd 設定檔 lighttpd.conf 內有個指定主機 IP 其預設值為 0.0.0.0:80,此次解決方法為將 lighttpd.conf 內修改為該機器的 Public IP 即可。
vi /usr/local/etc/lighttpd.conf
 $SERVER"socket" == "0.0.0.0:80" { }       //預設值
 $SERVER"socket" == "61.60.59.58:80" { }   //修改後




Q6. 點選 .cgi 變成下載視窗?

Error Message:
安裝了 Nagios 後嘗試連結 .cgi 網頁都變成下載 .cgi 檔案?

Ans:
因為還未設定 Lighttpd 支援 CGI Module 所導致,透過修改 lighttpd 設定檔 lighttpd.conf 即可支援 CGI Module
vi /usr/local/etc/lighttpd.conf
 server.modules = (
                   "mod_cgi",  //將此行註解移除 (支援 CGI Module)
                  )
#### CGI module                //將下列這幾行的註解移除
 cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
                                ".cgi" => "/usr/bin/perl" )

修改完成並重新啟動 Lighttpd 服務後,若想確定 Lighttpd 是否支援 CGI Module 可寫個簡單的 test.cgi 來測試看看 Lighttpd 是否能處理 CGI 檔案。
vi test.cgi           //建立 test.cgi 內容如下
 #!/usr/bin/perl
 print "Content-type: text/html\n\n";
 print "<h1>hello world</h1>";
chmod +x test.cgi     //給予 test.cgi 可執行的權限




Q7. Unrecognized character \x7F at /home/web/nagios/cgi-bin/tac.cgi line 1.?

Error Message:
安裝了 Nagios 嘗試連結 .cgi 網頁時出現如下錯誤訊息
 500 - Internal Server Error
查看 Lighttpd 的 Error Log 檔為說明 Lighttpd 不認可 cgi 的描述
tail /var/log/lighttpd.error.log
 Unrecognized character \x7F at /home/web/nagios/cgi-bin/tac.cgi line 1.

Ans:
會造成這樣的情況是因為 Nagios 的 cgi 不是 Perl CGI 而是 Binary Code 所以您使用 Perl 去處理它就會造成 500 - Internal Server Error 的結果,請修改 lighttpd 設定檔 lighttpd.conf 後就可順利讀取 Nagios 的 cgi 了。
vi /usr/local/etc/lighttpd.conf
#### CGI module
 cgi.assign                 = ( ".pl"  => "/usr/bin/perl",
                                ".cgi" => "/usr/bin/perl" ) //預設值 (使用 Perl 來處理 CGI)
                                ".cgi" => "" )              //修改後 (不需特定解析程序來執行 CGI)




Q8. cronolog 無法套用在 lighttpd.error.log 上?

Error Message:
安裝了 cronolog 套件後想套用在 Lighttpd Access 及 Error Log 上,但啟動 Lighttpd 服務時卻會發生錯誤訊息如下
/usr/local/etc/rc.d/lighttpd start
 2007-11-28 17:17:22: (log.c.62) opening errorlog '|/usr/local/sbin/cronolog /var/log/%Y_%m_%d-error.log' failed: No such file or directory
 2007-11-28 17:17:22: (server.c.945) opening errorlog failed, dying

Ans:
在 Google 上找了一下後發現這篇 #296 (Can't use cronolog with server.errorlog) - lighttpd - secure, fast, compliant, and very flexible web-server - Trac,大意為目前若使用 cronolog 來處理 Lighttpd Log 的話對於 Access Log 是 ok 的,但若是 Error Log 則目前還有點問題,而想想反正分析軟體通常也都只分析 Access Log 而以,所以就先這樣吧。
vi /usr/local/etc/lighttpd.conf
 #accesslog.filename  = "/var/log/lighttpd.access.log"     //預設值
 accesslog.filename    = "|/usr/local/sbin/cronolog /var/log/%Y_%m_%d-access.log"  //修改後
 server.errorlog         = "/var/log/lighttpd.error.log"               //預設值

而因為 Lighttpd 沒有寫入 /var/log 的權限,所以若採用上面的設定還是會有問題例如會跳出 /var/log/2007_11_29-access.log: Permission denied 所以將產生的路徑移到例如 /home/log 然後設 owner 為 www 這樣 Lighttpd 服務就可順利每天產生 Log 了。
 accesslog.filename = "|/usr/local/sbin/cronolog /home/log/%Y_%m_%d-access.log"



Q9. /var/run/lighttpd/php-fastcgi.socket-0 No such file or directory?

Error Message:
修改 Lighttpd 設定檔 lighttpd.conf 後,啟動 Lighttpd 服務但發現無法啟動成功且出現如下錯誤訊息?
tail /var/log/lighttpd.error.log
 2008-07-21 19:10:34: (log.c.75) server started
 2008-07-21 19:10:34: (mod_fastcgi.c.904) bind failed for: unix:/var/run/lighttpd/php-fastcgi.socket-0 No such file or directory
 2008-07-21 19:10:34: (mod_fastcgi.c.1340) ERROR: spawning fcgi failed.
 2008-07-21 19:10:34: (server.c.908) Configuration of plugins failed. Going down.

Ans:
因為 Lighttpd 新版本 (lighttpd-1.4.19_1) 的設定檔內容有修改過本來執行 php-fastcgi.sockstat 是在 tmp 資料夾,現在則改到 /var/run/lighttpd 下且執行的指令 php-cgi 好像又剛好有錯字 (php-cgi-cgi) 將執行指令修改回來即可
vi /usr/local/etc/lighttpd.conf
 fastcgi.server             = ( ".php" =>
                               ( "localhost" =>
                                 (
                                   "socket" => "/var/run/lighttpd/php-fastcgi.socket",
                                   "bin-path" => "/usr/local/bin/php-cgi-cgi"    //預設值
                                   "bin-path" => "/usr/local/bin/php-cgi"          //修改後
                                 )
                               )
                            )

由於 Lighttpd 新版本 (lighttpd-1.4.19_1) 將 php-fastcgi.sockstat 路徑改為 /var/run 下,因此請建立 FastCGI Socket 資料夾且允許 Lighttpd 服務 (www) 具有可寫入該資料夾的權限後即可成功啟動 Lighttpd 服務。
mkdir /var/run/lighttpd
chown www:www /var/run/lighttpd

啟動 Lighttpd 成功後可發現 FastCGI Socket 在 /var/run 下。
/usr/local/etc/rc.d/lighttpd start
# sockstat |grep www
 www      php-cgi    13471 0  stream /var/run/lighttpd/php-fastcgi.socket-3
 www      php-cgi    13461 0  stream /var/run/lighttpd/php-fastcgi.socket-3
 www      php-cgi    13376 0  stream /var/run/lighttpd/php-fastcgi.socket-2
 www      php-cgi    13375 0  stream /var/run/lighttpd/php-fastcgi.socket-2
 www      php-cgi    13374 0  stream /var/run/lighttpd/php-fastcgi.socket-1
 www      php-cgi    13373 0  stream /var/run/lighttpd/php-fastcgi.socket-1
 www      php-cgi    13366 0  stream /var/run/lighttpd/php-fastcgi.socket-0
 www      php-cgi    13365 0  stream /var/run/lighttpd/php-fastcgi.socket-0
 www      lighttpd   13364 4  tcp4   *:80                  *:*