Xiaopei's DokuWiki

These are the good times in your life,
so put on a smile and it'll be alright

User Tools

Site Tools


it:lighttpd

lighttpd

Docs - Lighttpd - lighty labs

TO READ: http://www.aslibra.com/blog/go.php/category/lighttpd/

  • 尽量用 rewrite, 不用 $HTTP["url"], alias.url, server.error-handler-404 !!

tips

  • Since 1.4.21, New setting to disable returning of a 417 if “Expect: 100-continue” header is given:
    server.reject-expect-100-with-417 = "disable" 

old notes

lighttpd docs

lighttpd 配置的语法

option NAME = VALUE
merge NAME += VALUE
NAME modulename.key
VALUE ( <string> | <integer> | <boolean> | <array> | VALUE [ + VALUE ]*)
<string> “text”
<integer> digit*
<boolean> ( "enable" | "disable" )
<array> “(” [ <string> “⇒” ] <value> [, [ <string> “⇒” ] <value> ]* “)”
INCLUDE “include” VALUE
INCLUDE_SHELL “include_shell” STRING_VALUE

lighttpd 最讨厌的地方就是 option 不可覆盖, 不是 duplicate 就是 has to

基本配置

  # default document-root
  server.document-root = "/var/www/example.org/pages/"
 
  # TCP port
  server.port = 80
 
  # selecting modules
  server.modules = ( "mod_access", "mod_rewrite" )
 
  # variables, computed when config is read.
  var.mymodule = "foo"
  server.modules += ( "mod_" + var.mymodule )
  # var.PID is initialised to the pid of lighttpd before config is parsed
 
  # include, relative to dirname of main config file
  include "mime.types.conf"
 
  # read configuration from output of a command
  include_shell "/usr/local/bin/confmimetype /etc/mime.types"

条件配置

  <field> <operator> <value> {
    ...
    <field> <operator> <value> {
      ... nesting: match only when parent match
    }
  }
  else <field> <operator> <value> {
    ... the "else if" block
  }

where <field> is one of one of the following:

Field name Description
$HTTP[“cookie”]match on cookie
$HTTP[“host”]match on host
$HTTP[“useragent”]match on useragent
$HTTP[“referer”]match on referer
$HTTP[“url”]match on url. If there are nested blocks, this must be the most inner block.
$HTTP[“querystring”]match on querystring, eg, after the ? in this type url: index.php?module=images..
$HTTP[“remoteip”]match on the remote IP or a remote Network (Warning: doesn't work with IPv6 enabled)
$HTTP[“request-method”](Introduced in version 1.4.19) match on the request method.
$HTTP[“scheme”](Introduced in version 1.4.19) match on the scheme used by the incoming connection. This is either “http” or “https”.
$HTTP[“language”](Introduced in version 1.4.21) match on the Accept-Language header.
$SERVER[“socket”]match on socket. Value must be on the format “ip:port”, where ip is an IP address(optional) and port a port number. Only equal match (==) is supported. It also binds the daemon to this socket. Use this if you want to do IP/port-based virtual hosts.
$PHYSICAL[“path”](Introduced in version 1.5.0) - match on the mapped physical path of the file / cgi script to be served.
$PHYSICAL[“existing-path”](Introduced in version 1.5.0) - match on the mapped physical path of the file / cgi script to be served only if such a file exists on the local filesystem.

<operator> is one of:

Operator Value
==string equal match
!=string not equal match
=~perl style regular expression match
!~perl style regular expression not match

and <value> is either a quoted (“”) literal string or regular expression.

  # disable directory-listings for /download/*
  dir-listing.activate = "enable"
  $HTTP["url"] =~ "^/download/" {
    dir-listing.activate = "disable"
  }
 
  # handle virtual hosting
  # map all domains of a top-level-domain to a single document-root
  $HTTP["host"] =~ "(^|\.)example\.org$" {
    server.document-root = "/var/www/htdocs/example.org/pages/"
  }
 
  # multiple sockets
  $SERVER["socket"] == "127.0.0.1:81" {
    server.document-root = "..."
  }
 
  $SERVER["socket"] == "127.0.0.1:443" {
    ssl.pemfile = "/var/www/certs/localhost.pem"
    ssl.engine = "enable"
 
    server.document-root = "/var/www/htdocs/secure.example.org/pages/"
  }
 
  # deny access for all googlebot
  $HTTP["useragent"] =~ "Google" {
    url.access-deny = ( "" )
  }
 
  # deny access for all image stealers (anti-hotlinking for images)
  $HTTP["referer"] !~ "^($|http://www\.example\.org)" {
    url.access-deny = ( ".jpg", ".jpeg", ".png" )
  }
 
  # deny the access to www.example.org to all user which
  # are not in the 10.0.0.0/8 network
  $HTTP["host"] == "www.example.org" {
    $HTTP["remoteip"] != "10.0.0.0/8" {
     url.access-deny = ( "" )
    }
  }
 
  # Allow only 200.19.1.5 and 210.45.2.7 to
  # have access to www.example.org/admin/
  $HTTP["host"] == "www.example.org" {
    #!~ is a perl style regular expression not match
    $HTTP["remoteip"] !~ "^(200\.19\.1\.5|210\.45\.2\.7)$" {
      $HTTP["url"] =~ "^/admin/" {
        url.access-deny = ( "" )
      }
    }
  }

troubleshooting

试用 “-t” or “-p” 可测试配置.

$ lighttpd -t -f lighttpd.conf
#  -p      Print the parsed configuration file in its internal form and exit.
#  -t      Test the configuration file for syntax errors and exit.
# -t 和 -p 效果类似

配置

/etc/lighttpd/下,有conf-availableconf-enabled目录和lighttpd.conf文件。可将新的配置写在conf-available目录中,2位数字说明加载顺序,并在conf-enabledln -s

配置示例

lighttpd.conf
server.modules   = ( "mod_rewrite",
                     "mod_redirect",
                     "mod_alias",
                     "mod_access",
                     "mod_auth",
                     "mod_status",
                     "mod_simple_vhost",
                     "mod_evhost",
                     "mod_userdir",
                     "mod_secdownload",
                     "mod_fastcgi",
                     "mod_proxy",
                     "mod_cgi",
                     "mod_ssi",
                     "mod_compress",
                     "mod_usertrack",
                     "mod_expire",
                     "mod_rrdtool",
                     "mod_accesslog" )
 
server.document-root = "/var/www/servers/www.example.org/pages/" 
 
server.port = 80
 
server.username = "www" 
server.groupname = "www" 
 
mimetype.assign = (
  ".html" => "text/html", 
  ".txt" => "text/plain",
  ".jpg" => "image/jpeg",
  ".png" => "image/png" 
)
 
static-file.exclude-extensions = ( ".fcgi", ".php", ".rb", "~", ".inc" )
index-file.names = ( "index.html" )
 
$HTTP["host"] == "www2.example.org" {
  server.document-root = "/var/www/servers/www2.example.org/pages/" 
  $HTTP["url"] =~ "^/download/" {
    dir-listing.activate = "enable" 
  }
}

The order of the modules is important1):

  1. The modules are executed in the order as they are specified. Loading mod_auth AFTER mod_fastcgi might disable authentication for fastcgi backends (if check-local is disabled). As auth should be done first, move it before all executing modules (like proxy, fastcgi, scgi and cgi).
  2. rewrites, redirects and access should be first, followed by auth and the docroot plugins.
  3. Afterwards the external handlers like fastcgi, cgi, scgi and proxy and at the bottom the post-processing plugins like mod_accesslog.

条件配置 Conditional Configuration

语法:

  <field> <operator> <value> {
    ...
    <field> <operator> <value> {
      ... nesting: match only when parent match
    }
  }
  else <field> <operator> <value> {
    ... the "else if" block
  }

使用变量 Using variables

使用 var.foo = “bar” 可声明变量, 其他地方就能用 foovar.foo 使用变量.

在某条件下引入的文件中对全局做配置

即 setting a server wide configuration inside a included-file from conditionals. 方法是使用 global {…}

lighttpd.conf
  server.modules = ()
  $HTTP["host"] == "www.example.org" {
    include "incl-php.conf" 
  }
incl-php.conf
  global {  # <=== ATTENTION!
    server.modules += ("mod_fastcgi")
    static-file.exclude-extensions += (".php")
  }
  fastcgi.server = "..." 

mod_access

deny access to files.

  • url.access-deny: Denies access to all files with any of given trailing path names.
    url.access-deny = ( "~", ".inc")

mod_accesslog

我倾向在 accesslog 默认格式上加 %T: time used in seconds, 以检测请求处理耗时, 而位置可以在 %b: bytes sent for the body 旁边.

accesslog.format = "%h %V %u %t \"%r\" %>s %T %b \"%{Referer}i\" \"%{User-Agent}i\"" 
$ awk '{print  $10, $7}' access.log | sort -n  | tail 
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
31 /lims/!equipments?st=60
32 /lims/!equipments?st=60
#s addr

修改后 lighttpd reload & 需要手动 logrotate: logrotate –force /etc/logrotate.d/lighttpd.

mod_setenv

增加环境变量和 HTTP 请求/回复头

  • setenv.add-environment
    setenv.add-environment = ( 
      "TRAC_ENV" => "lighttpd",
      "RAILS_ENV" => "production" 
    )
  • setenv.add-response-header
    setenv.add-response-header = (
      "Content-Encoding" => "gzip" 
    )
  • setenv.add-request-header
    setenv.add-request-header = (
      "X-Proxy" => server.name
    )

mod_auth

mod_alias

The alias module is used to specify a special document-root for a given url-subset.The alias module is used to specify a special document-root for a given url-subset.

# 第一处
alias.url = ( "/cgi-bin/" => "/var/www/servers/www.example.org/cgi-bin/" )
# 其他
alias.url += ( "/content" => "/var/www/servers/www.somecontent.org/" )

Docs ModAlias - Lighttpd - lighty labs

mod_redirect

The redirect module is used to specify redirects for a set of URLs.

在系统升级/维护时, 可使用 mod_redirect 将所有访问转至 under construction 页面, 而不停止 lighttpd

url.redirect = ( "^/show/([0-9]+)/([0-9]+)$" => "http://www.example.org/show.php?isdn=$1&page$2",
                 "^/get/([0-9]+)/([0-9]+)$"  => "http://www.example.org/get.php?isdn=$1&page$2" )

# make an external redirect
# from any www.host (with www.) to the host (without www.)
$HTTP["host"] =~ "^www\.(.*)$" {
  url.redirect = ( "^/(.*)" => "http://%1/$1" )
}

Docs ModRedirect - Lighttpd - lighty labs

mod_rewrite

internal redirects, url rewrite.

url rewriting does not work within a $HTTP[“url”] conditional.

Docs ModRewrite - Lighttpd - lighty labs

mod_magnet

通过 lua 脚本, allows you to do more complex URL rewrites and caching

lua 脚本虽然强大, 但由于 mod_magnet 由 lighttpd 执行, 会耗 lighttpd 的资源, 阻塞其他请求

Docs ModMagnet - Lighttpd - lighty labs

mod_proxy

$HTTP["host"] == "rails.example.com" {
        proxy.server += (
                "" => (
                        ( "host" => "127.0.0.1", "port" => "3000" )
                )
        )
}

需注意, host 中不能用下划线 _, 也许是 lighttpd 或 mod_proxy 的 bug, 带下划线的地址访问时 400 Bad Request.

debug

  • lua 中使用 print() 可输出到 error.log

FastCGI

CGI 的缺点

Common_Gateway_Interface

CGI 要求每次请求都要 fork 一个 CGI 进程处理, fork 进程很耗资源, 尤其当 CGI 程序需要实时解释时.

解决方法一是使用编译好的 CGI 程序而不是脚本语言(这会影响编程的效率), 二是使用 FastCGI, 三是通过 mod_php 等 web server 模块让 CGI 程序在 server 内运行.

FastCGI 的特点

http://www.fastcgi.com FastCGI

FastCGI 像是一个常驻(long-live)型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次(这是 CGI 最为人诟病的 fork-and-execute 模式)。它还支持分布式的运算, 即 FastCGI 程序可以在网站服务器以外的主机上执行, 并且接受来自其它网站服务器来的请求。

lighttpd mod_fastcgi 配置说明

http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModFastCGI

fastcgi.conf
( <extension> => 
  ( [ <name> => ] 
    ( # Be careful: lighty does *not* warn you if it doesn't know a specified option here (make sure you have no typos)
      "host" => <string> ,
      "port" => <integer> ,
      "socket" => <string>,                 # either socket or host+port
      "bin-path" => <string>,               # optional 
      "bin-environment" => <array>,         # optional 
      "bin-copy-environment" => <array>,    # optional 
      "mode" => <string>,                   # optional
      "docroot" => <string> ,               # optional if "mode" is not "authorizer" 
      "check-local" => <string>,            # optional
      "max-procs" => <integer>,             # optional - when omitted, default is 4
      "broken-scriptfilename" => <boolean>, # optional
      "fix-root-scriptname" => <boolean>,   # optional, since 1.4.23 (option didn't work before 1.4.23)
      "disable-time" => <integer>,          # optional
      "allow-x-send-file" => <boolean>,     # optional
      "kill-signal" => <integer>,           # optional, default is SIGTERM(15) (v1.4.14+)
    ),
    ( "host" => ... 
    ) 
  )
)
  • <extension>: is the file-extension or prefix (if started with “/”)
  • <name>: optional name that shows up in the generated statistics of mod_status, useful for indicating which backend handler processed this extension (e.g. The name “php” would show as “fastcgi.backend.php.*”)
  • “host”: is ip of the FastCGI process (no support for hostnames right now, see #1417)
  • “port”: is tcp-port on the “host” used by the FastCGI process
  • “bin-path”: path to the local FastCGI binary which should be started if no local FastCGI is running
  • “socket”: path to the unix-domain socket
  • “mode”: is the FastCGI protocol mode. Default is “responder”, also “authorizer” mode is implemented.
  • “docroot”: is optional and is the docroot on the remote host for default “responder” mode. For “authorizer” mode it is MANDATORY and it points to docroot for authorized requests. For security reasons it is recommended to keep this docroot outside of server.document-root tree.
  • “check-local”: is optional and may be “enable” (default) or “disable”. If enabled the server first checks for a file in local 'server.document-root' tree and returns 404 (Not Found) if no such file, and does not fall back to FastCGI. If disabled, the server forwards a request to the FastCGI interface without this check.
  • “broken-scriptfilename”: breaks SCRIPT_FILENAME in a way that PHP can extract PATH_INFO from it (default: disabled)
  • “fix-root-scriptname”: use this for backends with extension “/” (and check-local is disabled).
  • “disable-time”: time to wait before a disabled backend is checked again (don't set this to 0 for backends you spawn with lighttpd, i.e. bin-path set, as lighty won't restart your backends then)
  • “allow-x-send-file”: controls if X-LIGHTTPD-send-file, X-Sendfile and X-Sendfile2 (since 1.4.24) headers are used. See X-Sendfile.

If bin-path is set:

  • “max-procs”: the number of fastcgi processes that will be started
  • “bin-environment”: put an entry into the environment of the started process
    • PHP provides 2 special environment variables
      • PHP_FCGI_CHILDREN: the number of spawned workers under the control of a single watching process
      • PHP_FCGI_MAX_REQUESTS: the number of requests what a single worker handles before it kills itself
  • “bin-copy-environment”: clean up the environment and copy only the specified entries into the fresh environment of the spawn process(to increase the security)
  • “kill-signal”: By default lighttpd send SIGTERM to FastCGI processes, which were spawned by lighttpd. Applications, which link libfcgi, need to be killed with SIGUSR1. This applies to php <5.2.1, lua-magnet and others.

配置举例

fastcgi.conf.example
## FastCGI programs have the same functionality as CGI programs,
## but are considerably faster through lower interpreter startup
## time and socketed communication
##
## Documentation: /usr/share/doc/lighttpd-doc/fastcgi.txt.gz
##                http://www.lighttpd.net/documentation/fastcgi.html
 
server.modules   += ( "mod_fastcgi" )
 
## Start an FastCGI server for php (needs the php5-cgi package)
fastcgi.server    = ( ".php" => 
	((
		"bin-path" => "/usr/bin/php-cgi",
		"socket" => "/tmp/php.socket",
		"max-procs" => 8,
		"idle-timeout" => 20,
		"bin-environment" => ( 
			"PHP_FCGI_CHILDREN" => "10",
			"PHP_FCGI_MAX_REQUESTS" => "10000"
		),
		"bin-copy-environment" => (
			"PATH", "SHELL", "USER"
		),
		"broken-scriptfilename" => "enable"
	))
)

以上配置可产生如下进程

$ pstree
init───lighttpd───8*[php-cgi───10*[php-cgi]]

external fastcgi

spawn-fcgi 折腾了一下午, 好像是可实现 PHP_FCGI_CHILDREN, 但 max-procs 怎么实现? 是要开多个进程使用多个端口么? 另外还有 PHP_FCGI_MAX_REQUESTS 怎么设置呢? spawn-fcgi 自 09 年至今已经没更新了.

后来看到这篇文章(早看到能省不少时间), php 5.3.3 已集成 php-fpm. 而 Ubuntu 10.04 LTS 以后 php 便是 5.3.3 了.

所以别在 spawn-fcgi 浪费时间了, 该看下 php-fpm.

2012/06/02 18:27

调优

要清楚配置要随着系统性能设置改变

lighttpd

文件描述符

文件描述符

Since file descriptors are used for TCP/IP sockets, files and directories, a simple request for a PHP page might result in using 3 file descriptors:

  1. the TCP/IP socket to the client
  2. the TCP/IP and Unix domain socket to the FastCGI process
  3. the filehandle to the file in the document root to check if it exists

As lighttpd is a single-threaded server, its main resource limit is the number of file descriptors, which is set to 1024 by default (on most systems).

超过限制后, 会产生 sockets disabled, connection limit reached 错误.

对于高负载站点, 可放宽此限制:

server.max-fds = 2048

PHP 性能

访问日志

it/lighttpd.txt · Last modified: 2013/08/19 07:22 (external edit)