Ferron 2.8.1 配置参数详解

Ferron 2.8.1 全量配置参数详解:KDL 配置结构、热重载实测、按功能域分类的指令清单(作用域/默认值)、负载均衡与 ACME 质询对比、三套生产模板与真实排障,2026-10-20。

Ferron网络配置安全2026/10/21

Ferron 2.8.1 配置参数详解

目标:系统梳理 Ferron 2.8.1(官方最新稳定版)的全部配置参数:配置文件组织结构、修改与热重载流程、按功能域分类的指令清单(作用域/默认值/用法)、三套生产配置模板与真实排障记录。指令默认值以官方 2.8.1 版文档为准,配置行为均经真实环境实测验证(查询/实测日期 2026-10-20)。

一、环境信息

项值
操作系统Ubuntu 22.04.5 LTS(jammy),x86_64
目标软件Ferron 2.8.1(Stable 通道,2026-06-17 发布,APT 方式安装)
配置文件/etc/ferron.kdl(KDL 格式)
指令默认值依据Ferron 2.8.1 官方文档(tag 2.8.1 源码 docs/configuration/,与发布二进制同源)
实测方式systemctl 托管运行 + 前台运行对照、curl 验证响应、journalctl 溯源
查询/实测日期2026-10-20

二、前置条件

  • 已按《Ubuntu 22.04 安装 Ferron 指南》完成 Ferron 2.8.1 安装,systemctl status ferron 显示 active (running)。
  • 了解 KDL 语法三要素:节点(指令名 + 空格分隔的参数值)、属性(key=value 形式的具名参数,布尔值用 #true/#false,空值用 #null)、子块(节点名 { ... } 花括号嵌套);// 为行注释。
  • 理解 Ferron 的配置作用域三层模型:仅全局(只能写在 globals 或 * 块)、全局+虚拟主机(两处均可,主机级覆盖全局)、通用(几乎所有块内可用)。每条指令的实际允许作用域见下文分类清单。

三、配置查看与修改方式

3.1 配置文件与组织结构

Ferron 2.x 的配置文件(默认 /etc/ferron.kdl)由「顶层块」组成,块名即虚拟主机匹配器:

块名写法含义
globals { ... }全局配置(不绑定任何虚拟主机,可放全局级指令)
:80 { ... }匹配任意主机名的 80 端口请求
*:80 { ... }同上(显式通配写法)
example.com { ... }匹配域名 example.com(443 端口隐含,自动 TLS 生效的前提写法)
example.com:8080 { ... }匹配指定域名与端口
"192.168.1.1" { ... }按 IP 地址匹配(需加引号)
location "/admin" { ... }主机块内的路径级配置(可嵌套)

主机块内的 location 块、condition/if/if_not 条件块、snippet 片段与 include 拆分详见「十一、路由、URL 处理与访问控制参数」。

3.2 修改与热重载实测流程

标准修改流程:编辑 /etc/ferron.kdl → sudo systemctl reload ferron → journal 溯源确认 → curl 验证行为。实测(给 :80 块加一条响应头指令后重载):

:80 {
  root "/var/www/ferron"
  header "X-Test-Header" "ferron-reload-ok"
}
sudo systemctl reload ferron

journal 实测回显:

Oct 20 17:44:43 ferron-web systemd[1]: Reloading Ferron web server...
Oct 20 17:44:43 ferron-web ferron[4395]: Reloading the server configuration...
Oct 20 17:44:43 ferron-web systemd[1]: Reloaded Ferron web server.

验证生效(实测回显,新增头已出现):

curl -sI http://localhost/ | grep -iE "HTTP/|x-test|server:"
HTTP/1.1 200 OK
x-test-header: ferron-reload-ok
server: Ferron

热重载机制:systemd 单元中 ExecReload=kill -HUP $MAINPID,进程收到 SIGHUP 后原地重读配置,监听端口与进程 PID 均不变,适合反代后端不中断场景。

3.3 临时配置与免文件运行

不落盘验证配置用 --config-string 直接内联传入(实测,在 80 端口被占用时换 8088 冒烟测试):

ferron --config-string ':8088 { root "/opt/servetest" }'
HTTP server is listening on [::]:8088...

两个易踩的语义差异(均实测确认):

  • 顶层未知指令:热重载时进程直接报 Invalid top-level directive 退出,进入 systemd 重启循环(见「十四、常见问题」)。
  • 主机块内未知指令:Ferron 2.8.1 静默忽略并正常启动——指令拼写错误不会导致服务失败,但也不会生效,排障时先核对拼写。

3.4 配置拆分与复用

  • include "/etc/ferron/sites/*.kdl":把站点配置拆分到独立文件(2.1.0+),主文件保持干净。
  • snippet / use:定义可复用配置片段(2.6.0+ 支持跨 include 文件复用),如全局安全响应头只写一次。

四、参数总览(速查表)

高频指令速查(完整语义见后续各章;默认值为官方 2.8.1 文档口径):

指令作用域默认值一句话说明
root通用无静态站点根目录
log / error_log全局+主机无(不配置则不落盘)访问/错误日志文件路径
protocols仅全局"h1" "h2"启用的协议版本
timeout仅全局300000(毫秒)单请求最大处理时长
listen_ip仅全局"::"监听 IP
proxy通用无反向代理上游(可多条)
lb_algorithm通用"two_random"负载均衡算法
cache通用#falseHTTP 缓存开关
limit通用#false限流开关(rate 25 rps)
tls全局+主机无手工指定证书与私钥路径
auto_tls全局+主机条件性 #true自动 TLS 开关
status通用无自定义状态码/认证/跳转/响应体
user通用无Basic 认证用户与哈希
allow / block全局+主机无IP 白/黑名单(CIDR)
header / header_remove / header_replace通用无响应头增/删/改
error_page通用无自定义错误页
rewrite通用无正则 URL 重写
fcgi_php通用#nullPHP FastCGI 上游
directory_listing通用#false目录列表开关
etag通用#trueETag 开关

💡 布尔语义约定:KDL 中开关型指令的裸写(如 directory_listing)等价于 #true;#null 多用于「恢复默认/禁用」。

五、HTTP 核心与网络参数

仅全局指令,写在 globals 或 * 块(官方《core directives》页口径):

指令默认值说明
default_http_port80域名块隐含的 HTTP 端口;#null 禁用
default_https_port443域名块隐含的 HTTPS 端口;#null 禁用
protocols"h1" "h2"支持 "h1"/"h2"/"h3"(h3 为实验性)
timeout300000请求最大处理毫秒数,超时重置连接;不建议关闭(防 Slow HTTP 攻击)
listen_ip"::"监听地址,改 "0.0.0.0" 仅 IPv4
io_uring#null(2.4.0+)#null 表示自动回退(内核支持则启用);对 Tokio 构建无效
tcp_send_buffer / tcp_recv_buffer无TCP 收发缓冲字节数
protocol_proxy#false接收 PROXY protocol(前置 LB 传真实 IP 时开启)
buffer_request#null请求缓冲字节数,可缓解 Slowloris 类攻击
buffer_response#null响应缓冲字节数
h2_initial_window_size / h2_max_frame_size / h2_max_concurrent_streams / h2_max_header_list_size / h2_enable_connect_protocolHyper 默认HTTP/2 细调参数

六、日志与可观测参数

指令作用域默认值说明
log <path>全局+主机无访问日志文件,默认 Combined Log Format(实测格式见下)
error_log <path>全局+主机无错误日志文件
log_format全局Combined自定义占位符模板,占位符清单见本节末
log_date_format全局"%d/%b/%Y:%H:%M:%S %z"时间戳格式(POSIX)
log_json全局禁用(2.7.0+)JSON 访问日志,启用后 log_format 失效
log_stdout / log_stderr全局#false(2.5.0+)访问日志输出到标准流
error_log_stdout / error_log_stderr全局#false(2.5.0+)错误日志输出到标准流
log_rotate_size / log_rotate_keep全局#null(禁用,2.6.0+)访问日志按大小轮转与保留份数
error_log_rotate_size / error_log_rotate_keep全局#null错误日志轮转
otlp_service_name全局"ferron"OTLP 上报服务名
otlp_logs / otlp_metrics / otlp_traces全局#null protocol="grpc"OpenTelemetry 三信号上报端点(grpc/http/protobuf/http/json)

访问日志实测样例(默认 Combined 格式,::ffff: 前缀为 IPv4-mapped IPv6 表示):

::ffff:127.0.0.1 - - [20/Oct/2026:17:11:57 +0000] "GET / HTTP/1.1" 200 2411 "-" "curl/7.81.0"

可用占位符(官方 placeholders 参考页):{client_ip}、{auth_user}、{timestamp}、{method}、{path_and_query}、{version}、{status_code}、{content_length}、{header:Referer}、{header:User-Agent} 等。

七、静态文件与内容参数

指令默认值说明
root <path>无站点根目录;#null 禁用静态服务
index"index.html" "index.htm"(静态)目录请求的索引文件序列(FastCGI 场景默认含 index.php)
etag#trueETag 响应头
compressed#true静态文件动态压缩,算法优先级 zstd → br → gzip → deflate(2.8.0 起)
precompressed#false直出预压缩文件(.gz/.br/.zst/.deflate),配合 ferron-precompress 工具预生成
directory_listing#false目录列表(生产建议保持关闭)
mime_type <ext> <type>无追加 MIME 映射
file_cache_control <value>#null静态文件 Cache-Control 响应头
dynamic_compressed#false动态内容(反代/FastCGI 响应)压缩
replace <a> <b> / replace_last_modified / replace_filter_typestext/html 过滤响应体字符串替换(2.1.0+)

预压缩实测:ferron-precompress /var/www/ferron 后站点目录出现成套压缩产物(实测清单节选):

index.html      index.html.br   index.html.deflate   index.html.gz   index.html.zst
favicon.ico     favicon.ico.br  favicon.ico.deflate  favicon.ico.gz  favicon.ico.zst
FunnelSans-Bold.woff2  FunnelSans-Bold.woff2.br  FunnelSans-Bold.woff2.gz  ...

八、缓存参数

HTTP 缓存模块(cache)参数(反代场景常用,静态文件本身有 file_cache_control 控制客户端缓存):

指令默认值说明
cache#false缓存开关
cache_max_entries1024缓存条目上限(#null 不限;键由方法+重写后 URL+Host+Vary 头构成)
cache_max_response_size2097152(2 MB)可缓存的响应体大小上限
cache_vary无参与缓存键区分的请求头
cache_ignore无缓存时忽略的响应头

九、反向代理与负载均衡参数

核心是 proxy 指令,可写多条实现上游池:

:80 {
  proxy "http://localhost:3000"
  proxy "http://localhost:3001"
  lb_algorithm "round_robin"
  lb_health_check
}
指令默认值说明
proxy <url>无上游地址(http/https/Unix socket unix= 属性);limit=/idle_timeout=(默认 60000ms)属性可限连接与空闲超时
lb_algorithm"two_random"算法见下表
lb_health_check#false被动健康检查开关
lb_health_check_max_fails3连续失败次数阈值
lb_health_check_window5000健康检查统计窗口(毫秒)
lb_retry_connection#true连接失败自动重试其他后端
proxy_keepalive#true到后端保持连接
proxy_concurrent_conns16384(2.3.0+)到后端并发连接上限
proxy_no_verification#false跳过后端 TLS 证书校验(自签场景)
proxy_intercept_errors#false拦截后端错误响应改由本机处理
proxy_request_header / proxy_request_header_remove / proxy_request_header_replace无请求头增/删/改(值支持 {path} 等占位符)
proxy_http2#false后端走 HTTP/2(需 https 上游)
proxy_http2_only#false仅 HTTP/2(gRPC 场景)
proxy_proxy_header#null向后端发送 PROXY protocol("v1"/"v2")
proxy_srv <url>无基于 DNS SRV 记录的动态上游(http://_http._tcp.example.com/)

💡 技术拓展:lb_algorithm 四种负载均衡算法对比——

算法调度策略适用场景
random纯随机选取后端性能同质、请求量均匀
round_robin依次轮转后端性能同质、需要确定性分布
least_conn当前并发请求数最少者请求处理耗时不均(长连接/WebSocket 混布)
two_random(默认)随机取两个、选并发更少者(power of two choices)通用默认,兼顾随机性与负载感知

默认 two_random 是「随机 + 最少连接」的折中:无全局锁开销,负载倾斜概率远低于纯随机。

十、TLS 与安全参数

10.1 手工证书与协议级参数

指令默认值说明
tls <cert> <key>无手工指定证书链与私钥路径
tls_min_version / tls_max_version"TLSv1.2" / "TLSv1.3"TLS 版本区间
tls_cipher_suiteRustls 默认套件白名单(启用 h3 时必须保留 TLS_AES_128_GCM_SHA256)
tls_ecdh_curvesRustls 默认ECDH 曲线
tls_client_certificate#false客户端证书校验(mTLS;字符串值指定 CA 路径)
ocsp_stapling#trueOCSP 装订
trust_x_forwarded_for#false信任上游 X-Forwarded-For(处于反代之后时开启)

10.2 自动 TLS(ACME)参数

指令默认值说明
auto_tls条件性 #true块名为公网域名且端口未显式指定时自动开启
auto_tls_contact#nullACME 账户邮箱
auto_tls_challenge"tls-alpn-01"质询方式:http-01/tls-alpn-01/dns-01
auto_tls_letsencrypt_production#true#false 切换 Let's Encrypt staging 环境
auto_tls_directory无自定义 ACME 目录(覆盖上一条)
auto_tls_cacheOS 用户数据目录(~/.local/share/ferron-acme)ACME 数据缓存目录
auto_tls_on_demand#false按需签发(首次访问时申请,务必配合下一条防滥用)
auto_tls_on_demand_ask#null按需签发白名单校验 URL(?domain= 参数回调)
auto_tls_eab#nullACME External Account Binding
auto_tls_save_data <cert> <key>#null(2.5.0+)导出自动获取的证书与私钥
auto_tls_post_obtain_command#null(2.5.0+)获证后回调命令(注入 FERRON_ACME_* 环境变量)

💡 技术拓展:三种 ACME 质询方式对比——

质询验证途径前置条件典型场景
http-0180 端口回读令牌80 可从公网访问常规网站
tls-alpn-01(默认)443 端口 TLS ALPN 握手443 可从公网访问只开 443 的站点
dns-01DNS TXT 记录DNS API 凭据通配符证书、内网源站、CDN 后源站

dns-01 需以 provider=<服务商> 属性指定 DNS 服务商并配凭据(内置 Cloudflare、Route 53、bunny.net、deSEC、DigitalOcean、OVH、Porkbun 等 10+ 家)。

10.3 访问控制与限流参数

指令默认值说明
status <code>无多功能状态码指令:realm=+users= 做 Basic 认证(401)、location= 做跳转、body= 自定义响应体、allowed=/not_allowed= 按 IP 生效、url=/regex= 按路径生效
user <name> <hash>无Basic 认证用户(哈希用 ferron-passwd 生成,Argon2/PBKDF2/scrypt)
allow / block无IP/CIDR 白名单与黑名单(可多条)
abort#false(2.6.0+)直接断开连接不回包
limit#false限流:rate= 平均速率(默认 25 rps)、burst= 峰值(默认 4 倍 rate)

Basic 认证实测配置(生成哈希与生效验证):

:80 {
  root "/var/www/ferron"
  status 401 realm="Restricted Area" users="admin"
  user "admin" "$argon2id$v=19$m=19456,t=2,p=1$..."
}

实测三态:无凭据 401;curl -u admin:<密码> 200;错误凭据 401,错误日志出现 Authorization failed for user "admin" and client "::ffff:127.0.0.1"。

十一、路由、URL 处理与访问控制参数

指令默认值说明
header / header_remove / header_replace无响应头增/删/改(值支持 {path} 占位符;实测见 3.2)
error_page <code> <path>无自定义错误页
server_administrator_email无默认 500 页展示的管理员邮箱
rewrite <regex> <replacement>无正则重写;directory=/file=/last=/allow_double_slashes= 属性
rewrite_log#false重写行为写入错误日志(排障利器)
wwwredirect#false裸域跳 www
no_redirect_to_https#false关闭 HTTP→HTTPS 强制跳转(块端口显式指定时恒为 true)
no_trailing_redirect#false关闭目录尾斜杠跳转
allow_double_slashes#false允许 URL 双斜杠
disable_url_sanitizer#false关闭 URL 清洗(有路径穿越风险,仅特殊应用需要)

结构块(组合指令实现精细化路由):

example.com {
  location "/api" {
    proxy "http://localhost:3000"
  }
  location "/static" {
    root "/var/www/assets"
  }
  condition "is_admin_ip" {
    is_remote_ip "10.0.0.0/8"
  }
  if_not "is_admin_ip" {
    status 403 body="Forbidden"
  }
}
  • condition "<名>" { ... }:命名条件块,内部放 is_remote_ip/is_forwarded_for/is_equal/is_regex/is_not_*/is_rego(OpenPolicyAgent Rego 策略)/is_language 等判定指令。
  • if "<名>" { ... } / if_not "<名>" { ... }:条件通过/不通过时生效的指令组。
  • set_constant <k> <v>:定义配置内常量(2.1.0+)。

十二、应用后端参数(CGI/SCGI/FastCGI)

指令默认值说明
fcgi_php <url>#nullPHP FastCGI(仅 .php 请求转发),TCP(tcp://localhost:9000/)或 Unix socket(unix:///run/php/php-fpm.sock)
fcgi <url>#null pass=#true通用 FastCGI 上游,pass=#false 时仅作为 location 命中处理
fcgi_extension / fcgi_environment无FastCGI 处理的扩展名与环境变量
scgi <url>#nullSCGI 上游 + scgi_environment
cgi#falseCGI 处理开关
cgi_extension / cgi_interpreter / cgi_environment内置解释器映射CGI 脚本扩展名、解释器(.pl/.py/.sh/.rb/.php 等已预置)与环境变量

十三、生产配置模板

13.1 模板一:静态站点(资源需求:内存 ~6 MB / 磁盘 <100 MB)

globals {
  log "/var/log/ferron/access.log"
  error_log "/var/log/ferron/error.log"
  log_rotate_size 10485760
  log_rotate_keep 7
}

example.com {
  root "/var/www/site"
  precompressed
  file_cache_control "public, max-age=3600"
  header "X-Content-Type-Options" "nosniff"
  header "X-Frame-Options" "DENY"
  header "Referrer-Policy" "strict-origin-when-cross-origin"
  error_page 404 "/404.html"
}

适用:文档站、博客、下载站。precompressed 配合 ferron-precompress 预生成 .zst/.br/.gz 省运行时 CPU。

13.2 模板二:反向代理 + 缓存 + 限流(资源需求:内存 ~10-20 MB / 磁盘视缓存条目而定)

globals {
  log "/var/log/ferron/access.log"
  error_log "/var/log/ferron/error.log"
  buffer_request 65536
}

app.example.com {
  proxy "http://10.0.0.11:3000"
  proxy "http://10.0.0.12:3000"
  lb_algorithm "least_conn"
  lb_health_check
  cache
  cache_max_entries 4096
  cache_max_response_size 1048576
  limit rate=100 burst=400
  proxy_request_header_replace "X-Real-IP" "{client_ip}"
}

适用:为多个内网服务做统一 TLS 网关与流量防护。

13.3 模板三:PHP 站点(资源需求:内存 ~6 MB + PHP-FPM 自身开销 / 磁盘 <100 MB)

blog.example.com {
  root "/var/www/wordpress"
  fcgi_php "unix:///run/php/php-fpm.sock"
  index "index.php" "index.html"
}

适用:WordPress 等 PHP 应用。前置条件:PHP-FPM 池监听套接字的属主需改为 ferron 用户(listen.owner = ferron、listen.group = ferron),否则报 503(官方默认配置内注释亦提示此点)。

十四、常见问题(FAQ)

14.1 改了配置不生效或重载失败

先分层排查(均实测复现):

  1. sudo systemctl reload ferron 后 journal 出现 Reloading the server configuration... 即重载已触发;未出现则服务本体已挂,systemctl status ferron 看真相。
  2. 顶层未知指令重载时报 Error while running a server: Invalid top-level directive at "/etc/ferron.kdl",进程退出并触发 Restart=on-failure 重启循环;修复配置后需 sudo systemctl reset-failed ferron && sudo systemctl start ferron(失败计数不清除时直接 start 会报 Job for ferron.service failed)。
  3. KDL 语法错误(如缺闭合花括号)前台运行会给出带行号的 miette 诊断:Failed to parse KDL document ... No closing '}' for child block。
  4. 主机块内未知指令被静默忽略(如误写 bad_directive "x" 服务照常启动)——「改了没生效」先查拼写。

14.2 Basic 认证哈希导致解析错误

ferron-passwd 生成的哈希粘入 user 指令时夹带换行/回车,实测报 Unexpected newline in single-line quoted string(miette 定位到行:列)。确保哈希单行粘贴且无尾随空白。认证生效判据:无凭据/错误凭据 401、正确凭据 200,错误日志含 Authorization failed for user。

14.3 端口冲突

Error while running a server: Cannot listen to HTTP port: Address already in use (os error 98):80/443 被占用。sudo ss -ltnp | grep :80 定位占用者;或用 :8080 形式块名换端口(注意:块名显式写端口后,auto_tls 默认逻辑关闭,需手工 tls 指令或 default_https_port 调整)。

14.4 域名块开了但 443 不通/证书没签下来

  • 域名 DNS 未指向本机或 80/443 未对公网开放(云安全组/防火墙);
  • auto_tls_challenge 与可达端口不匹配(只开 80 用 http-01,只开 443 用默认 tls-alpn-01,内网/通配符用 dns-01);
  • 调试期可 auto_tls_letsencrypt_production #false 切 staging 环境规避限频。

十五、参考链接