Lighttpd 1.4.85 配置参数详解

Lighttpd 1.4.85 配置指令全实测:server 核心指令、站点行为、日志格式、Basic 认证与 TLS、URL 改写重定向、压缩与多 worker、条件块语法、生产配置模板与取值陷阱 FAQ,回显全部实测(2026-10-20)。

LighttpdLighttpd网络配置2026/10/21

Lighttpd 1.4.85 配置参数详解

目标:把 lighttpd 1.4.85 常用配置指令逐组讲透并全部实测——每条指令给出语法、真实验证回显与行为说明,收尾给一份可直接落地的生产配置模板;文中的坑(dir-listing.activate 的取值陷阱、单引号字符串不被支持等)均为实测发现。安装过程见 B1 安装指南篇。

一、环境信息

本文全部指令在以下环境逐条实测,回显照抄:

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • lighttpd 版本:1.4.85(官方源码 meson 编译,lighttpd/1.4.85 (ssl),特性含 epoll/sendfile/zlib/zstd/brotli/OpenSSL;编译方法见 B1 方案 B)
  • 安装前缀:/usr/local/lighttpd(配置 /usr/local/lighttpd/etc/,日志 /usr/local/lighttpd/var/log/)
  • 测试站点根:/srv/www(含 index.html、sub/index.html、secret/data.txt、deny/x.inc、404.html)
  • 端口:主服务 80;临时测试用 8081;TLS 443
  • 对照参考:Ubuntu 22.04 apt 版 lighttpd 1.4.63 的默认主配置(/etc/lighttpd/lighttpd.conf)
  • 实测日期:2026-10-20;未实测的默认值均标注「官方文档值」并给出处

二、配置文件体系与加载顺序

本节先讲清 1.4.85 的配置组织方式,避免「改了没生效」类问题。lighttpd 配置是纯文本键值 + 条件块语法,启动时一次性解析;与 Ubuntu 打包版的三层软链体系不同,编译版通常用单文件或 include 组织。

  1. 主配置入口:lighttpd -f <file> 指定的文件(编译版本文用 /usr/local/lighttpd/etc/lighttpd-min.conf;apt 版是 /etc/lighttpd/lighttpd.conf)。
  2. include / include_shell:可把片段并入主配置。Ubuntu 版用 include_shell "/usr/share/lighttpd/include-conf-enabled.pl" 把 conf-enabled/ 下全部软链片段依次带入——这就是 Ubuntu「启用模块只建软链」的原理;编译版可直接写 include "/usr/local/lighttpd/etc/mime.conf" 拆分文件。
  3. 生效顺序:指令按文件内从上到下解析,后写的同名键覆盖先写的;条件块内部的值覆盖外层全局值(同键嵌套时以最内层为准)。
  4. 语法自检:改完配置先跑 lighttpd -tt -f <file>(连模块一起加载验证),通过再重载——本文所有配置片段均经过该命令实测验证(-tt 的完整用法见 D1 CLI 命令篇)。

三、核心服务器指令(server.*)

本组指令决定进程身份、监听方式与日志落点,是最小可运行配置的骨架。以下逐条实测。

3.1 server.modules(模块加载)

server.modules = (
  "mod_accesslog", "mod_dirlisting", "mod_access", "mod_alias",
  "mod_auth", "mod_authn_file", "mod_deflate", "mod_redirect",
  "mod_rewrite", "mod_openssl", "mod_h2"
)

实测要点:模块名按需列写即可,顺序影响不大(本文做过仅有顺序差异的对照实验,mod_accesslog 在前在后行为一致);但某模块的指令想生效,必须先加载该模块——实测把 dir-listing.activate 写进配置而未加载 mod_dirlisting 时,-tt 报:

WARNING: unknown config-key: dir-listing.activate(ignored)

补上模块后告警消失(-tt 退出码 0)。另注意 1.4.71+ 部分模块(indexfile/access/alias/redirect/rewrite/dirlisting/staticfile 等)已并入主程序,无需对应 .so,但仍要在 server.modules 列出以激活其指令(本文 1.4.85 构建中 mod_dirlisting.so 等同时以动态模块存在)。

3.2 server.port / server.bind(监听)

server.bind = "0.0.0.0"
server.port = 80

实测:改为 server.port = 8080 重启后,curl -sI http://localhost:8080 返回 HTTP/1.1 200 OK(Server: lighttpd/1.4.85),原 80 端口停止响应。server.bind 省略时监听全部地址;只监听本机可设 "127.0.0.1"。端口被占用时启动失败的完整排障实录见 B1 FAQ Q1(can't bind to socket: 0.0.0.0:80: Address already in use)。

3.3 server.document-root(站点根)

server.document-root = "/srv/www"

实测:该目录必须存在且可读,请求 / 时依次尝试 index-file.names;目录无 index 且未开目录列表时返回 403 Forbidden(实测:仅加载 mod_dirlisting 而不设 dir-listing.activate,curl -si http://127.0.0.1:8081/ 返回 HTTP/1.1 403 Forbidden)。这是全配置唯一必填的服务器级指令。

3.4 server.username / server.groupname(运行身份)

server.username = "www-data"
server.groupname = "www-data"

实测说明:以 root 启动时绑定 80 特权端口后降权到该用户运行;Ubuntu apt 版默认即此写法。编译版最小配置省略时进程以启动者身份运行(生产环境建议显式降权)。文件权限需与该身份匹配,否则出现 403/404。

3.5 server.pid-file / server.errorlog / server.upload-dirs

server.pid-file = "/usr/local/lighttpd/var/run/lighttpd.pid"
server.errorlog = "/usr/local/lighttpd/var/log/error.log"
server.upload-dirs = ( "/var/cache/lighttpd/uploads" )

实测:server.pid-file 写出的主进程号可用于脚本化管理(如 kill -USR1 $(cat ...) 触发优雅重启,见 D1);server.errorlog 指定的文件会在启动时创建,启动成功记录 server started、失败记录具体原因(实测样例行:2026-10-20 17:05:59: (../src/server.c.1973) server started (lighttpd/1.4.85))。server.upload-dirs 是请求体上传的临时目录,Ubuntu 默认 /var/cache/lighttpd/uploads(实测该目录存在且归 www-data)。

四、站点行为指令

本组指令决定「请求进来之后返回什么」。

4.1 index-file.names(目录默认页)

index-file.names = ( "index.html" )

实测:请求目录路径时按序查找;配合 mimetype.assign 使用。Ubuntu 默认值为 ( "index.php", "index.html" )。

4.2 mimetype.assign(MIME 映射)

mimetype.assign = ( ".html" => "text/html", ".txt" => "text/plain", ".inc" => "text/plain" )

实测:响应头 Content-Type: text/html 与该映射一致;映射缺失的类型默认按 application/octet-stream 处理。apt 版通过 include_shell "/usr/share/lighttpd/create-mime.assign.pl" 从 /etc/mime.types 自动生成完整表。

4.3 dir-listing.activate(目录列表)—— 含取值陷阱实测

标准用法(只对指定路径开启列表):

$HTTP["url"] =~ "^/sub/" {
  dir-listing.activate = "enable"
}

实测(条件作用域):请求 / 返回 HTTP/1.1 403 Forbidden,请求 /sub/ 返回 HTTP/1.1 200 OK 并输出目录索引页——列表只对 /sub/ 前缀生效。

⚠️ 实测发现的取值陷阱:dir-listing.activate 的值只接受 "enable"。写成 dir-listing.activate = "disable" 时,-tt 与启动日志都会报 WARNING: unknown config-key: dir-listing.activate(ignored),且目录列表实际处于开启状态(实测 curl / 返回 200 与完整 Index of / 页面),行为与直觉相反。实测结论:想关闭目录列表,直接不写该指令、或不加载 mod_dirlisting(默认即关,实测不写时返回 403);想全局开、局部关的场景,用条件块把 "enable" 限定到需要的路径。

4.4 url.access-deny(访问拒绝)

url.access-deny = ( "~", ".inc" )

实测:对 .inc 结尾的请求返回 403 Forbidden(模组 mod_access;保护备份文件 ~ 与源码片段是经典用法)。

4.5 server.error-handler-404(错误处理页)

server.error-handler-404 = "/404.html"

实测:请求不存在的 /no-such-page 返回处理页内容 <h1>custom 404 page</h1>;注意状态码为 HTTP/1.1 200 OK 而非 404(静态文件作为 error-handler 的既有行为,详见 FAQ)。

五、日志指令

5.1 accesslog.filename(访问日志位置)

accesslog.filename = "/usr/local/lighttpd/var/log/access.log"

实测:每个请求一行即时落盘;配合系统 logrotate 轮转(apt 版随包自带 /etc/logrotate.d/lighttpd)。

5.2 accesslog.format(访问日志格式)

默认格式即 Apache CLF(%h %V %u %t "%r" %>s %b)。自定义示例(实测生效):

accesslog.format = "%h %V %u %t \"%r\" %>s %b"

实测自定义格式输出(tail -1 /usr/local/lighttpd/var/log/access.log):

127.0.0.1 127.0.0.1 - [20/Oct/2026:16:44:17 +0000] "GET /big.txt HTTP/1.1" 200 13492

⚠️ 实测发现两条写法约束:① 单引号字符串不被 1.4.85 配置解析器支持——写 accesslog.format = '%h ...' 时报 invalid character in variable name(configfile parser failed at: =);② 内嵌双引号必须写成 \" 转义(官方示例同款写法)。常用占位符:%h 客户端 IP、%V 服务器名、%u 认证用户、%t 时间、%r 请求行、%>s 最终状态码、%b 响应字节数、%{User-Agent}i 请求头。

六、认证与 TLS 指令

6.1 Basic 认证(mod_auth + mod_authn_file)

auth.backend = "plain"
auth.backend.plain.userfile = "/usr/local/lighttpd/etc/auth.users"
auth.require = ( "/secret/" => (
  "method" => "basic",
  "realm"  => "test-realm",
  "require" => "valid-user"
) )

用户文件 /usr/local/lighttpd/etc/auth.users 内容为 admin:q1w2e3r4(权限 600)。实测无凭据访问受保护路径:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="test-realm", charset="UTF-8"

带凭据访问(curl -u admin:q1w2e3r4)返回 HTTP/1.1 200 OK 并正常输出 top secret dir。生产建议:密码文件置于站点根之外、权限 600、属主与 server.username 一致。

6.2 TLS/HTTPS(mod_openssl,条件块监听)

$SERVER["socket"] == ":443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/usr/local/lighttpd/etc/server.pem"
}

自签证书生成与合并(pemfile = 私钥 + 证书顺序拼接):

cd /usr/local/lighttpd/etc
openssl req -x509 -newkey rsa:2048 -nodes -keyout server.key -out server.crt -days 365 -subj "/CN=localhost"
cat server.key server.crt > server.pem

实测 HTTPS 验证(curl -k 跳过自签校验):

HTTP/2 200

解读:1.4.85 的 HTTP/2 由 mod_h2 承载(需在 server.modules 列出),走 TLS ALPN 协商,所以 curl 直接以 HTTP/2 200 响应。生产环境把 ssl.pemfile 换成 CA 签发的全链证书即可,续期后 kill -USR1 优雅重载。

七、URL 处理指令

7.1 alias.url(路径别名)

alias.url = ( "/docs/" => "/srv/www/sub/" )

实测:curl -sI http://127.0.0.1/docs/ 返回 HTTP/1.1 200 OK(内容来自 /srv/www/sub/),对客户端完全透明。

7.2 url.rewrite(内部改写)

url.rewrite = ( "^/nolink/(.*)$" => "/sub/$1" )

实测:curl -s http://127.0.0.1/nolink/ 返回 HTTP/1.1 200 OK、内容为 /sub/ 的 <h1>sub dir</h1>——不产生跳转头,客户端无感知。

7.3 url.redirect(外部重定向)

url.redirect = ( "^/old/(.*)$" => "/sub/$1" )

实测:curl -sI http://127.0.0.1/old/abc 返回:

HTTP/1.1 301 Moved Permanently
Location: /sub/abc

选型记忆:rewrite = 服务端换路径(浏览器地址不变)、redirect = 返回 301/302 让浏览器重新请求。

八、性能与压缩指令

8.1 server.max-worker(多进程)

server.max-worker = 2

实测:重启后进程形态为 1 主 + 2 子(ps -ef 可见 3 个 lighttpd 进程,PID 6936 主、6937/6938 为子进程),多核机器上可提升静态吞吐;小内存机器保持默认单进程即可(默认值 1,官方文档值,官方 wiki《Performance》条目)。

8.2 mod_deflate 响应压缩

deflate.mimetypes = ( "text/plain", "text/html" )

实测(10KB 级文本 big.txt,GET 请求带 Accept-Encoding: gzip):

ETag: "1303632381-gzip"
Vary: Accept-Encoding
Content-Length: 958
Content-Encoding: gzip

原文 13492 字节压缩到 958 字节;ETag 追加 -gzip 后缀以便缓存正确失效。两个实测细节:HEAD 请求不压缩(实测 curl -sI 同一文件无 Content-Encoding);压缩只对 deflate.mimetypes 列出的类型生效。编译版需带 zlib/zstd/brotli 头文件构建(见 B1 5.3 踩坑记录)。连接数类参数 server.max-connections(默认 1024)、server.max-keep-alive-requests(默认 16)、server.max-keep-alive-idle(默认 5 秒)为官方文档值(官方 wiki《Performance - lighttpd wiki》,2026-10-20 实查),一般保持默认。

九、条件块语法

条件块是 lighttpd 配置的精髓,本文已实测三种:

条件块含义本文实测场景
$HTTP["url"] =~ "正则"请求路径匹配只对 /sub/ 前缀开目录列表(4.3)
$SERVER["socket"] == ":443"监听套接字匹配TLS 监听块(6.2)
$HTTP["host"] == "域名"Host 头匹配虚拟主机(语法同款,本文用 IP 直连未触发)

嵌套规则:条件块可嵌套,内层可覆盖外层同键值;== 精确匹配、=~ 正则匹配。auth.require 的键本身就是「路径前缀 → 参数表」映射,与条件块配合可实现按目录的差异化策略。

十、生产配置模板(1.4.85)

以下模板由本文全部实测片段组装而成,可直接落地(路径按需替换);每一段均在前文对应小节实测验证过:

server.modules = (
  "mod_accesslog", "mod_dirlisting", "mod_access", "mod_alias",
  "mod_auth", "mod_authn_file", "mod_deflate", "mod_redirect",
  "mod_rewrite", "mod_openssl", "mod_h2"
)

server.document-root = "/srv/www"
server.bind          = "0.0.0.0"
server.port          = 80
server.username      = "www-data"
server.groupname     = "www-data"
server.pid-file      = "/usr/local/lighttpd/var/run/lighttpd.pid"
server.errorlog      = "/usr/local/lighttpd/var/log/error.log"
server.upload-dirs   = ( "/var/cache/lighttpd/uploads" )

accesslog.filename = "/usr/local/lighttpd/var/log/access.log"
accesslog.format   = "%h %V %u %t \"%r\" %>s %b"

index-file.names = ( "index.html" )
mimetype.assign  = ( ".html" => "text/html", ".txt" => "text/plain" )
url.access-deny  = ( "~", ".inc" )

# 目录列表只对下载区开放(不要用 dir-listing.activate = "disable" 关闭,见 4.3 陷阱)
$HTTP["url"] =~ "^/downloads/" {
  dir-listing.activate = "enable"
}

# Basic 认证保护区
auth.backend = "plain"
auth.backend.plain.userfile = "/usr/local/lighttpd/etc/auth.users"
auth.require = ( "/secret/" => (
  "method" => "basic", "realm" => "test-realm", "require" => "valid-user" ) )

# 路径别名 / 内部改写 / 外部跳转
alias.url    = ( "/docs/" => "/srv/www/sub/" )
url.rewrite  = ( "^/nolink/(.*)$" => "/sub/$1" )
url.redirect = ( "^/old/(.*)$"    => "/sub/$1" )

# 响应压缩
deflate.mimetypes = ( "text/plain", "text/html" )

# HTTPS(自签证书生产环境请替换为 CA 证书)
$SERVER["socket"] == ":443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/usr/local/lighttpd/etc/server.pem"
}

上线前三步验证(均实测通过):

/usr/local/lighttpd/sbin/lighttpd -tt -f /usr/local/lighttpd/etc/lighttpd-min.conf && echo CONFIG-TEST-OK

实测回显:

CONFIG-TEST-OK
systemctl restart lighttpd-local && systemctl is-active lighttpd-local

实测回显:

active
curl -skI https://localhost | head -2

实测回显:

HTTP/2 200

十一、常见问题(FAQ)

Q1:dir-listing.activate = "disable" 为什么报警告且行为反直觉?

见 4.3 实测:该指令值只接受 "enable";写 "disable" 会产生 unknown config-key: dir-listing.activate(ignored) 告警且目录列表实际开启。关闭列表的正确姿势:不写该指令(默认关,实测 403)或用条件块只对需要的路径 "enable"。

Q2:配置里用单引号包字符串直接解析失败?

1.4.85 配置解析器不支持单引号字符串。实测 accesslog.format = '%h %V ...' 报:

configfile.c.2204) source: /usr/local/lighttpd/etc/lighttpd-min.conf line: 8 pos: 33 invalid character in variable name
configfile parser failed at: %h %V %u %t

统一用双引号,内嵌双引号转义为 \"(官方示例同款)。

Q3:error-handler-404 指向静态文件后,404 变成了 200?

既有行为:静态文件作为 server.error-handler-404 时响应状态码为处理页自身的 200(实测 /no-such 返回 HTTP/1.1 200 OK + 自定义页内容)。需要真实 404 状态码时改用动态脚本处理或在应用层兜底。

Q4:模块指令写了却提示 unknown config-key?

对应模块没进 server.modules(见 3.1 实测)。补上模块名告警即消失;仍无效则用 -tt 单独最小化复现排查。

Q5:改完配置如何做到不停机生效?

lighttpd -tt 自检通过后执行 systemctl reload lighttpd(或向主进程发 kill -USR1),单元文件里 ExecReload=/bin/kill -USR1 $MAINPID,实测 USR1 后日志先记录 server stopped by UID = 0 PID = 6936 随即 server started,期间服务持续可访问(回显详见 D1 信号控制一节)。

十二、参考链接

  1. 官方配置 Wiki(含各指令默认值):https://redmine.lighttpd.net/projects/lighttpd/wiki/WikiStart#Configuration
  2. mod_dirlisting / mod_auth / mod_deflate 官方文档(redmine wiki 对应页面)
  3. Ubuntu apt 版默认主配置:/etc/lighttpd/lighttpd.conf(随包文件)
  4. 本文实测:lighttpd 1.4.85(meson 编译,Ubuntu 22.04.5),实测日期 2026-10-20;安装过程见 《Ubuntu 22.04 安装 Lighttpd 指南》,命令行工具用法见 《Lighttpd 1.4.85 常用 CLI 命令详解》