Flyimg 1.12.10 配置:parameters.yml 全参数详解与逐项生效验证

Flyimg 1.12.10 配置篇:parameters.yml 全参数总览与逐项生效实测,覆盖页面开关、缓存头、URL 签名、域名白名单、AVIF/WebP 协商、默认质量、限流、超时、分隔符与 cron 清理,附限流仅作用于未命中请求的机制发现与排障实录、生产配置模板。

FlyimgFlyimg自托管2026/10/28

Flyimg 1.12.10 配置:parameters.yml 全参数详解与逐项生效验证

目标:把 Flyimg 1.12.10 的唯一配置文件 parameters.yml 的全部参数讲透——每个参数的默认值、含义与改动后的行为,并对安全、缓存、格式协商、限流等核心参数逐项实测「改了确实生效」。全部验证在 Ubuntu 22.04 + PHP 8.3.36 真机完成,安装过程见 《Flyimg 1.12.10 安装:Ubuntu 22.04 源码直装与 systemd 服务化》。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS x86_64;PHP 8.3.36(NTS)+ php8.3-yaml 扩展;nginx/1.18.0;
  • Flyimg:1.12.10(源码 commit 2878b1b790a7613b50c62d77bad0d68597980454),部署目录 /var/www/flyimg,服务端口 80(实测经 8146 反向端口暴露,正文统一写 80);
  • 源图:局域网源站 192.168.1.10:8000 提供 Citroen-DS.jpg(2266x1957,1,025,710B)与 Rovinj-Croatia.jpg(640x360,58,657B)、flyimg.png(800x258,34,968B);
  • 参数基线:除逐项实验临时改动外,均以 1.12.10 默认 parameters.yml 为基线,实验后已恢复;
  • 实测工具:curl 8.x、ImageMagick identify(核对输出尺寸)。

二、前置条件

Flyimg 服务已安装并可用(首页 curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1/ 返回 200),配置文件位于 /var/www/flyimg/config/parameters.yml。若尚未安装,先完成安装篇全流程。

三、参数查看与修改方式

3.1 参数文件与生效机制

Flyimg 唯一的应用配置就是 /var/www/flyimg/config/parameters.yml(YAML 格式)。生效机制是本篇最重要的事实:应用在处理每个请求时重新加载该文件,改动即时生效,不需要重启 nginx 或 php-fpm。实测把 header_cache_days 从 365 改为 7:

sed -i "s/^header_cache_days: 365/header_cache_days: 7/" /var/www/flyimg/config/parameters.yml
grep "^header_cache_days" /var/www/flyimg/config/parameters.yml

实测回显:

header_cache_days: 7
curl -s -I "http://127.0.0.1/upload/w_300,q_80/http://192.168.1.10:8000/Citroen-DS.jpg" | grep -i cache-control

实测回显:

Cache-Control: max-age=604800, public, s-maxage=604800

7 天 = 604800 秒,无需任何服务重启。同理把标题改掉:

sed -i "s/^home_page_title: Flyimg/home_page_title: Flyimg 运维实验室/" /var/www/flyimg/config/parameters.yml
curl -s http://127.0.0.1/ | grep -o "<title>[^<]*</title>"

实测回显:

<title>Flyimg 运维实验室</title>

💡 说明:即时生效来自 PHP 请求级执行模型——每次请求都会执行 app.php 重新构造参数对象。好处是改配置零停机;代价是每次请求都多一次 YAML 解析(这也是安装篇必须装 php-yaml 扩展的原因)。

3.2 辅助 CLI:URL 签名生成

配置了 security_key 之后,可用应用自带的 CLI 生成签名 URL(用法与实测见 5.4 节):

cd /var/www/flyimg && php app.php encrypt w_300,q_80/http://192.168.1.10:8000/Citroen-DS.jpg

四、参数总览

parameters.yml 顶层参数共 25 个左右(含嵌套块),按功能域归类如下(默认值以 1.12.10 原始文件为准):

功能域参数默认值一句话含义
页面debugfalse调试模式,异常页带堆栈
页面home_page_titleFlyimgdemo 首页标题
页面demo_page_enabledtruedemo 首页开关,关了返回空页
日志log_levelerrorMonolog 级别(debug/info/notice/warning/error)
缓存header_cache_days365响应头 max-age 天数
缓存disable_cachefalse关闭产物落盘,直接回响应
清理enable_cronjob_cleanuptruevar/tmp 清理任务开关
清理cronjob_cleanup_interval0 */5 * * *清理调度(cron 表达式)
安全security_key / security_iv''(空)URL 签名密钥/IV,空=不启用
安全restricted_domainsfalse源站域名白名单开关
安全whitelist_domains官方示例域名白名单(精确+通配 *.example.com)
格式enable_avif / enable_webp / enable_jxltrue三种现代格式自动协商
格式heic_speed8AVIF(HEIF 库)编码速度档
格式webp_threads1WebP 编码线程
引擎thread1ImageMagick 线程数
源站source_image_request_timeout5拉源图超时(秒)
源站header_extra_options官方 UA 示例拉源图附带的额外请求头
源站forward_request_headers透传给源站的请求头白名单
存储storage_systemlocal本地或 s3
存储aws_s3.*官方示例region/bucket_name/endpoint 等嵌套块
解析options_separator','(逗号)URL 参数分隔符
解析app_domain''(空)指定应用域名(特殊部署下覆盖自动探测)
限流rate_limit_enabledfalse限流开关
限流rate_limit_storage / rate_limit_limits 等file / 未启用限流后端与规则(见 5.9)
映射options_keys40 个短键URL 短键 → 处理参数的映射
映射default_options40 项处理参数默认值(quality 90 等)

参数键全量清单可在本机一句话导出(与官方 docs/configuration.md 一致,查询日期 2026-10-28):

grep -E "^[a-z_]+:" /var/www/flyimg/config/parameters.yml

实测回显(输出节选,实测首尾):

debug: false
log_level: error
home_page_title: Flyimg
demo_page_enabled: true
...
options_keys:
  q: quality
  o: output
  ...

五、核心参数分类详解(逐项生效验证)

5.1 页面与日志:debug、demo_page_enabled、log_level

debug 开启后异常响应从通用 500 页变成带堆栈的调试页(排障利器,平时保持 false)。demo_page_enabled 控制根路径 / 的行为,实测:

sed -i "s/^demo_page_enabled: true/demo_page_enabled: false/" /var/www/flyimg/config/parameters.yml
curl -s -o /tmp/demo-off.html -w "false: HTTP %{http_code} | %{size_download}B\n" http://127.0.0.1/
sed -i "s/^demo_page_enabled: false/demo_page_enabled: true/" /var/www/flyimg/config/parameters.yml
curl -s -o /dev/null -w "true: HTTP %{http_code} | %{size_download}B\n" http://127.0.0.1/

实测回显:

false: HTTP 200 | 0B | text/html; charset=UTF-8
true: HTTP 200 | 10362B

关闭后首页返回 200 但 0 字节空页(官方文档描述「returns an empty page with 200 code」,实测一致);开启时是 10KB 的 demo 演示页。公网暴露时建议关闭 demo 页,只保留 /upload 处理入口。

5.2 URL 签名:security_key 与 security_iv

两个值都为空(默认)时任意 URL 可请求;一旦设置,所有请求必须携带签名,否则 403。实测设置演示密钥:

python3 - << "PYEOF"
p = open("/var/www/flyimg/config/parameters.yml").read()
p = p.replace("security_key: ''", "security_key: 'flyimg-secret-key-2026'")
p = p.replace("security_iv: ''", "security_iv: 'flyimg-iv-2026'")
open("/var/www/flyimg/config/parameters.yml","w").write(p)
PYEOF
grep -E "^security" /var/www/flyimg/config/parameters.yml

实测回显:

security_key: 'flyimg-secret-key-2026'
security_iv: 'flyimg-iv-2026'

未签名请求实测:

curl -s -o /dev/null -w "无签名: HTTP %{http_code}\n" "http://127.0.0.1/upload/w_300/http://192.168.1.10:8000/Citroen-DS.jpg"
无签名: HTTP 403

用自带 CLI 生成签名 URL(算法为 AES 加密后 Base64,来源官方 docs/security.md):

cd /var/www/flyimg && php app.php encrypt w_300,q_80/http://192.168.1.10:8000/Citroen-DS.jpg

实测回显:

Hashed request: YmdkRkJ4SHk4Zk0zZ1NhZjFGSERoZjVXdkFTTGwyMjNYY2Vid0t1T2pibmJna05tYzhjUU9Xa3hWNS9jWXVjalRoTzNIcEVpVGEwb0MwYVRISnJSaUE9PQ==
curl -s -o /dev/null -w "签名URL: HTTP %{http_code} | %{content_type} | %{size_download}B\n" "http://127.0.0.1/upload/YmdkRkJ4SHk4Zk0zZ1NhZjFGSERoZjVXdkFTTGwyMjNYY2Vid0t1T2pibmJna05tYzhjUU9Xa3hWNS9jWXVjalRoTzNIcEVpVGEwb0MwYVRISnJSaUE9PQ=="
签名URL: HTTP 200 | image/jpeg | 22867B

签名 URL 输出与无签名时期的同参数结果完全一致(22867B),说明签名只控制访问权、不影响处理结果。验证完成后把两个值恢复为空(本文后续实验不依赖签名)。

5.3 源站域名白名单:restricted_domains 与 whitelist_domains

开启后仅白名单内源站可拉取。实测白名单设为局域网源站 192.168.1.10:

python3 - << "PYEOF"
path = "/var/www/flyimg/config/parameters.yml"
lines = open(path).read().splitlines()
out, in_wl = [], False
for ln in lines:
    if ln.startswith("whitelist_domains:"):
        in_wl = True
        out.append(ln); out.append("  - 192.168.1.10")
        continue
    if in_wl:
        if ln.startswith("  - "): continue
        in_wl = False
    out.append(ln)
p = "\n".join(out) + "\n"
p = p.replace("restricted_domains: false", "restricted_domains: true")
open(path,"w").write(p)
PYEOF
grep -A2 "whitelist_domains" /var/www/flyimg/config/parameters.yml | head -3

实测回显:

whitelist_domains:
  - 192.168.1.10
curl -s -o /dev/null -w "白名单内: HTTP %{http_code}\n" "http://127.0.0.1/upload/w_300,q_80/http://192.168.1.10:8000/Rovinj-Croatia.jpg"
curl -s -o /dev/null -w "白名单外: HTTP %{http_code}\n" "http://127.0.0.1/upload/w_300,q_80/https://flyimg.io/demo-images/Citroen-DS.jpg"

实测回显:

白名单内: HTTP 200
白名单外: HTTP 403

⚠️ 排障实录:本项与签名联动验证时一度「白名单内外全 403」——原因是没有先清掉 5.2 设置的 security_key,所有请求先被签名校验拦截。两个安全参数同时启用时,排查顺序应为:先签名(403 且响应是通用错误页),后域名(403 且带域名提示)。控制变量逐一验证是配置篇的基本功。通配符写法注意:YAML 中 *.example.com 必须加引号,否则解析报错(官方 security.md 原文警示,查询日期 2026-10-28)。

验证后恢复 restricted_domains: false。

5.4 格式协商开关:enable_avif、enable_webp、enable_jxl

默认三者全开。用 Accept 头模拟浏览器协商(同一张 2266x1957 源图,w_300,q_80):

SRC="http://192.168.1.10:8000/Citroen-DS.jpg"
curl -s -o /dev/null -w "全开+浏览器Accept: %{http_code} %{content_type} %{size_download}B\n" \
  -H "Accept: image/avif,image/webp,image/apng,image/*,*/*;q=0.8" \
  "http://127.0.0.1/upload/w_300,q_80/$SRC"
curl -s -o /dev/null -w "仅webp: %{http_code} %{content_type} %{size_download}B\n" \
  -H "Accept: image/webp,*/*" "http://127.0.0.1/upload/w_300,q_80/$SRC"
curl -s -o /dev/null -w "无协商: %{http_code} %{content_type} %{size_download}B\n" \
  "http://127.0.0.1/upload/w_300,q_80/$SRC"

实测回显:

全开+浏览器Accept: 200 image/avif 27888B
仅webp: 200 image/webp 20966B
无协商: 200 image/jpeg 22867B

关闭 enable_avif 后复测,浏览器 Accept 降级回 WebP:

sed -i "s/^enable_avif: true/enable_avif: false/" /var/www/flyimg/config/parameters.yml
curl -s -o /dev/null -w "关avif后: %{http_code} %{content_type} %{size_download}B\n" \
  -H "Accept: image/avif,image/webp,image/*,*/*;q=0.8" "http://127.0.0.1/upload/w_300,q_80/$SRC"

实测回显:

关avif后: 200 image/webp 20966B

三个开关独立生效、优先级为 AVIF > WebP > 原格式(与官方文档一致)。验证后恢复 enable_avif: true。三种格式的体积与耗时横向对比及 URL 强制输出(o_png/o_webp 等)见组内运维篇。

5.5 默认处理参数:default_options(quality 实测)

default_options 块定义 40 个处理参数的默认值(URL 未指定时生效)。实测改默认质量:

python3 - << "PYEOF"
p = open("/var/www/flyimg/config/parameters.yml").read()
p = p.replace("default_options:\n  quality: 90", "default_options:\n  quality: 60")
open("/var/www/flyimg/config/parameters.yml","w").write(p)
PYEOF
sed -n "/^default_options/,+1p" /var/www/flyimg/config/parameters.yml

实测回显:

default_options:
  quality: 60
curl -s -o /dev/null -w "无q参数(默认60): %{http_code} %{size_download}B\n" "http://127.0.0.1/upload/w_300/$SRC"
curl -s -o /dev/null -w "显式q_80: %{http_code} %{size_download}B\n" "http://127.0.0.1/upload/w_300,q_80/$SRC"

实测回显:

无q参数(默认60): 200 13070B
显式q_80: 200 22867B

默认值改动只影响「URL 未显式传参」的请求,URL 参数优先。验证后恢复 quality: 90。

5.6 缓存行为:header_cache_days 与 disable_cache

header_cache_days 已在 3.1 验证(365→7 对应 max-age=31536000→604800)。disable_cache 实测:

sed -i "s/^disable_cache: false/disable_cache: true/" /var/www/flyimg/config/parameters.yml
BEFORE=$(ls /var/www/flyimg/web/uploads | wc -l)
curl -s -o /dev/null -w "第1次: %{http_code} %{time_total}s\n" "http://127.0.0.1/upload/w_320,q_80/$SRC"
curl -s -o /dev/null -w "第2次: %{http_code} %{time_total}s\n" "http://127.0.0.1/upload/w_320,q_80/$SRC"
AFTER=$(ls /var/www/flyimg/web/uploads | wc -l)
echo "uploads 文件数: $BEFORE -> $AFTER"

实测回显:

第1次: 200 0.075854s
第2次: 200 0.079055s
uploads 文件数: 7 -> 7

disable_cache=true 时:两次请求耗时相同(都重新处理,无缓存加速),且新参数组合没有落盘新文件(7→7)。适合「处理结果即抛弃」的动态场景(如用户实时调整预览)。验证后恢复 false。

5.7 源站超时:source_image_request_timeout

默认 5 秒。把超时调到 1 秒并用延迟 8 秒的模拟源站复现:

sed -i "s/^source_image_request_timeout: 5/source_image_request_timeout: 1/" /var/www/flyimg/config/parameters.yml
curl -s -o /dev/null -w "慢源站(8s): HTTP %{http_code} | 耗时 %{time_total}s\n" \
  "http://127.0.0.1/upload/w_100/http://192.168.1.10:8100/slow.png"

实测回显:

慢源站(8s): HTTP 503 | 耗时 1.003885s

1.003 秒返回 503,与 1 秒超时精确吻合——超时参数即时生效、行为可预测。这也是安装篇排障实录 ③(外网源站 8s 超过默认 5s 导致 503)的根因复现。生产值建议:源站内网稳定时 5-10s,跨公网拉图可放宽到 30s。验证后恢复 30(本文源站为局域网模拟,保留宽松值)。

5.8 限流:rate_limit_enabled 系列参数

开启 file 后端限流,规则为每分钟 5 次:

python3 - << "PYEOF"
p = open("/var/www/flyimg/config/parameters.yml").read()
p = p.replace("rate_limit_enabled: false", """rate_limit_enabled: true
rate_limit_storage: file
rate_limit_limits:
  - { value: 1, unit: minute, requests: 5 }""")
open("/var/www/flyimg/config/parameters.yml","w").write(p)
PYEOF
grep -A3 "^rate_limit_enabled" /var/www/flyimg/config/parameters.yml

实测回显:

rate_limit_enabled: true
rate_limit_storage: file
rate_limit_limits:
  - { value: 1, unit: minute, requests: 5 }

⚠️ 排障实录(重要机制发现):先用同一 URL 连发 7 次,7 次全 200——限流「没生效」。查 1.12.10 源码 ImageHandler::processImage() 发现,限流检查位于「缓存文件不存在」分支内:缓存命中的请求不经过限流。换 7 个不同参数组合(每次都未命中)重测:

for i in 1 2 3 4 5 6 7; do
  W=$((151+i))
  curl -s -o /dev/null -w "第${i}次(w_${W}): HTTP %{http_code}\n" \
    "http://127.0.0.1/upload/w_${W},q_75/http://192.168.1.10:8000/Rovinj-Croatia.jpg"
done

实测回显:

第1次(w_152): HTTP 200
第2次(w_153): HTTP 200
第3次(w_154): HTTP 200
第4次(w_155): HTTP 200
第5次(w_156): HTTP 200
第6次(w_157): HTTP 429
第7次(w_158): HTTP 429

429 响应头实测:

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1793169120

结论:限额按「未命中缓存的新生成请求」计数,标准 X-RateLimit-* 头齐全;第 6 次触发即第 6 个新请求。rate_limit_storage 可选 file(单机持久)或 redis(多实例共享,依赖 predis,predis/predis 已在 composer.json 中);rate_limit_limits 支持多窗口叠加(如分钟/小时/天各一条)。验证后恢复 rate_limit_enabled: false。

5.9 参数分隔符:options_separator

默认逗号。改为分号后实测:

python3 - << "PYEOF"
p = open("/var/www/flyimg/config/parameters.yml").read()
p = p.replace("options_separator: ','", "options_separator: ';'")
open("/var/www/flyimg/config/parameters.yml","w").write(p)
PYEOF
curl -s -o /dev/null -w "分号分隔(URL编码%3B): %{http_code} %{size_download}B\n" \
  "http://127.0.0.1/upload/w_300%3Bq_85/$SRC"
curl -s -o /dev/null -w "旧逗号分隔: %{http_code} %{size_download}B\n" \
  "http://127.0.0.1/upload/w_300,q_85/$SRC"

实测回显:

分号分隔(URL编码%3B): 200 26868B
旧逗号分隔: HTTP 500 1603B

分隔符改动即时生效,且旧分隔符立即失效(整个参数段被当作一个未知键解析报错)。改分隔符后,前端调用方(官方 web/js/main.js 的 OPTIONS_SEPARATOR 常量)必须同步,参数文件注释里有原文警示。验证后恢复逗号。

5.10 临时目录清理:enable_cronjob_cleanup 与 cronjob_cleanup_interval

这两个参数由安装篇 4.6 节的 cleanup-tmp.sh 消费(而非应用运行时):脚本读取开关与 cron 表达式,生成 /etc/cron.d/cleanup-cron(实测回显 0 */5 * * * root /var/www/flyimg/cleanup-tmp.sh)。改 interval 后重跑脚本即可更新调度行:

sed -i 's/^cronjob_cleanup_interval: "0 \*\/5 \* \* \*"/cronjob_cleanup_interval: "0 */2 * * *"/' /var/www/flyimg/config/parameters.yml
cd /var/www/flyimg && ./cleanup-tmp.sh
cat /etc/cron.d/cleanup-cron

实测回显:

0 */2 * * * root /var/www/flyimg/cleanup-tmp.sh

调度行从每 5 小时变为每 2 小时。清理逻辑只删 var/tmp 中超过 1 小时的临时文件(避免与进行中的请求竞态),不动 web/uploads 产物缓存。验证后恢复默认 0 */5 * * *。

5.11 存储后端:storage_system(local/s3)

默认 local(产物写 web/uploads)。改为 s3 后产物改写对象存储,依赖 league/flysystem-aws-s3-v3(已在 composer.lock 中),配套参数为 aws_s3 嵌套块(region/bucket_name/access_id/secret_key/endpoint,endpoint 可指向 S3 兼容服务)。⚠️ 本项未实际对接对象存储实测(需要真实 bucket 凭据),参数行为按官方 docs/storage-options.md 转述(查询日期 2026-10-28);切回 local 的方式为把参数改回 storage_system: local。

六、生产配置模板

以下为一份面向「8GB 内存、SSD、日均 50 万次取图、源站为内网对象存储」场景的参考模板,相对默认值的差异点都标了注释:

# /var/www/flyimg/config/parameters.yml 生产参考模板
debug: false                      # 异常不带堆栈,防信息泄露
log_level: warning                # 生产降噪,排障期临时调 debug
home_page_title: Flyimg
demo_page_enabled: false          # 公网关闭演示页
app_domain: ''                    # 无特殊部署需求保持自动探测

header_cache_days: 30             # 源图会更新,缩短边缘缓存窗口
enable_cronjob_cleanup: true
cronjob_cleanup_interval: "0 */2 * * *"   # 高流量下加快临时文件回收

security_key: 'flyimg-secret-key-2026'   # 演示密钥,生产请更换为高强度随机值
security_iv: 'flyimg-iv-2026'            # 同上;两值非空即强制 URL 签名
restricted_domains: true          # 锁定源站
whitelist_domains:
  - 192.168.1.10
  - "*.internal.example.com"

storage_system: local             # 有 S3 兼容存储时改 s3 并填 aws_s3 块
thread: 2                         # 4 核以上机器可加线程
heic_speed: 8
webp_threads: 1

source_image_request_timeout: 10  # 内网源站 10s 足够
rate_limit_enabled: true
rate_limit_storage: file          # 多实例部署改 redis
rate_limit_limits:
  - { value: 1, unit: minute, requests: 100 }
  - { value: 1, unit: hour, requests: 5000 }

enable_avif: true                 # 现代格式按流量策略取舍
enable_webp: true
enable_jxl: false                 # JXL 生态未普及,先关省 CPU

options_separator: ','
options_keys:                     # 保持官方默认 40 键映射,升级兼容
  q: quality
  o: output
  w: width
  h: height
  # ...(与发行版默认一致,此处省略展示,以原文件为准)

default_options:                  # 默认质量按业务画面要求定
  quality: 85
  output: auto
  # ...(其余 38 项与发行版默认一致)

模板解读:安全三件套(签名/白名单/关 demo 页)是公网暴露的底线;header_cache_days 与 rate_limit_limits 按流量结构调;JXL 在客户端支持不普及的当下收益有限,关闭可省编码算力。签名密钥属系统级敏感值,生产环境建议以部署工具的密钥管理注入,本文为演示落了明文。

七、常见问题

Q1:改了 parameters.yml 不生效? 确认改的是实际部署路径(/var/www/flyimg/config/parameters.yml);核对 YAML 语法(php -r "var_dump(function_exists('yaml_parse_file'));" 应为 bool(true),扩展缺失时参数解析本身会 500);参数为请求级加载,无需重启,但改完建议用一条真实 URL 验证。

Q2:开启限流后不生效? 先确认请求是否命中缓存——1.12.10 限流只拦缓存未命中的新生成请求(5.8 实测与源码定位)。测试请换不同参数组合或加 rf_1 强制刷新。

Q3:设置 security_key 后整站 403? 这是预期行为:所有 URL 必须带签名。用 php app.php encrypt <options>/<src> 生成签名 URL(5.2 实测);对外分发的 URL 由上游业务系统批量预生成。

*Q4:whitelist_domains 配了 .example.com 报 YAML 解析错? 星号开头必须加引号:"*.example.com"(官方文档原文警示)。

Q5:AVIF 输出很慢? AVIF 编码成本高于 JPEG/WebP,可通过 enable_avif: false 关闭、或调 heic_speed(数值越大越快、压缩率越低)权衡;CPU 密集场景建议 WebP 为主。

八、参考链接