QuickShare 0.11.4 配置参数详解

QuickShare 0.11.4 全量配置参数详解:六组配置项与四个环境变量的默认值、加载优先级与实测生效证据,附生产配置模板与六类排障实录。

QuickShareQuickShare文件传输文件分享自托管2026/11/01

QuickShare 0.11.4 配置参数详解

QuickShare 是一款开箱即用的自托管文件分享服务,但「开箱即用」不等于「无需了解配置」:数据目录放哪、端口怎么改、上传限速多少、验证码开关在哪,这些都在一份配置文件里。本文基于 0.11.4 版本(当前最新稳定版),在真实 Ubuntu 服务器上逐项实测,给出全部配置参数的默认值、生效行为与排障实录。

环境与版本信息如下:

项目值
服务器系统Ubuntu 22.04 LTS(x86_64)
QuickShare 版本0.11.4(linux amd64 单二进制,官方发行包 quickshare_0.11.4_linux_amd64.zip)
服务二进制/opt/quickshare/bin/quickshare(约 32.7 MB,Go 静态编译)
配置文件/opt/quickshare/config.json
服务端口8129(本文实测端口,默认 8686)
管理员账号admin / q1w2e3r4
数据目录/opt/quickshare/quickshare(含 SQLite 数据库与文件索引)

组件定位与选型背景见《QuickShare 介绍与选型指南》,安装部署过程见《QuickShare 0.11.4 Docker Compose 部署指南》,本文聚焦其配置体系。

一、前置条件

  • 已按部署指南完成 QuickShare 安装,服务可正常启动(curl http://localhost:8129/v1/settings/health 返回正常)。
  • 可通过 SSH 登录服务器编辑配置文件,并具备重启服务进程的权限。
  • 了解基础 JSON/YAML 语法(配置文件两种格式均支持)。

本文所有实测均在同一台服务器完成:修改配置 → 重启服务 → 用 curl 验证行为变化,命令与输出均为真实记录,可直接复现。

二、配置的加载顺序与修改方式

2.1 五层加载顺序

QuickShare 0.11.4 的配置加载遵循固定顺序,后加载的覆盖先加载的(源码 LoadCfg 的合并顺序):

  1. 内置默认值:编译在二进制里的默认配置(见第三节总览表)。
  2. SQLite 数据库中的站点配置:数据库文件已存在时,读取其中保存的前端站点设置(站点名称、背景等,即界面「设置」里改的内容)。
  3. 配置文件:-c 参数指定的文件,可传多个、按顺序合并;按扩展名解析(.json/.yml/.yaml,其他扩展名直接报错)。
  4. 命令行参数:-h/--host、-p/--port、-d/--db(数据库路径),非空时覆盖前面的值。
  5. 环境变量:仅 4 个——DEFAULTADMIN、DEFAULTADMINPWD、TOKENSECRET、PORT。其中 PORT 在服务构造的最后阶段才覆盖端口,是全链路优先级最高的端口配置。

一个典型启动命令:

/opt/quickshare/bin/quickshare -c /opt/quickshare/config.json

2.2 修改配置的四种方式

方式一:配置文件(推荐)。 JSON 或 YAML 皆可,键名用小驼峰(searchResultLimit)。0.11.4 改用 Go 的 JSON 解析,键名大小写不敏感——实测配置文件里写 PascalCase("Port": 8130)同样生效;但官方模板均为小驼峰,建议从众,避免与 0.10.x 时代的大写键格式混淆(见排障实录 6.6)。

方式二:命令行参数。 适合临时验证:./quickshare -c config.json -p 9000 临时换端口启动,不落盘。

方式三:环境变量。 仅 4 个,且各自只在特定时机读取(详见 4.5 节),不是通用配置通道。

方式四:界面/站点动态配置。 登录后在「设置」里修改站点名称、描述、背景,实际写入 SQLite。这类配置只影响前端展示(siteName、siteDesc、背景图等),不涉及端口、限速等服务端参数。

2.3 如何确认修改已生效

配置修改后必须重启服务进程(站点动态配置除外)。重启后三步确认:

# 1. 确认新进程已在跑(旧进程退出需要 1~2 秒,见排障实录 7.2)
pgrep -af quickshare

# 2. 确认监听端口符合预期
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8129/v1/settings/health

# 3. 查看日志确认启动参数(数据目录下 quickshare.log 亦有同样记录)

启动成功时日志会输出监听地址(JSON 格式,实测节选):

{"level":"info","msg":"quickshare is starting","hostname:port":"0.0.0.0:8130"}

若端口没变,大概率是改错了文件(-c 没指向它)或被环境变量 PORT 抢占(见 4.5 节)。

三、参数总览

0.11.4 配置分六组(server/users/fs/secrets/workers/db),全部键与默认值如下表(源自程序内置默认值,并经实测核对):

组键类型默认值说明
serverdebugboolfalse调试模式(开启后 gin 输出详细日志)
serverhoststring0.0.0.0监听地址
serverportint8686监听端口(可被环境变量 PORT 覆盖)
serverreadTimeoutint2000(毫秒)读超时
serverwriteTimeoutint86400000(毫秒,1 天)写超时;同时决定文件读取器的缓存时长
servermaxHeaderBytesint512HTTP 头大小上限(实测行为见 5.1)
serverdynamic.clientCfg.siteNamestringQuickshare站点名称(界面显示)
serverdynamic.clientCfg.siteDescstringQuick and simple file sharing站点描述
serverdynamic.clientCfg.bgobject空背景图(url/repeat/position/align/bgColor)
serverdynamic.clientCfg.allowSetBgboolfalse是否允许普通用户设置背景
serverdynamic.clientCfg.autoThemebooltrue自动主题
usersenableAuthbooltrue认证开关,关闭后所有请求按管理员处理(危险,见 5.2)
userscookieTTLint604800(秒,7 天)登录 cookie 有效期
userscookieSecureboolfalsecookie 仅 HTTPS 传输(公网 HTTPS 部署应开启)
userscookieHttpOnlybooltruecookie 禁止 JS 读取(防 XSS 偷 token)
usersminUserNameLenint3用户名最小长度
usersminPwdLenint8密码最小长度
userscaptchaEnabledbooltrue登录验证码开关
userscaptchaWidth / captchaHeightint256 / 60验证码图片尺寸(像素)
usersuploadSpeedLimitint1048576(B/s,1 MB/s)新用户默认上传限速
usersdownloadSpeedLimitint1048576(B/s,1 MB/s)新用户默认下载限速;低于 102400 启动直接失败
usersspaceLimitint104857600(100 MB)新用户默认空间配额
userslimiterCapacity / limiterCycint1000 / 1000(毫秒)请求限流窗口(窗口内最多 1000 次请求)
userspredefinedUsersarray[]预置用户列表(name/role/pwd)
fsrootstringquickshare数据根目录(相对启动目录或绝对路径)
fsopensLimitint1024文件句柄池上限
fsopenTTLint60(秒)句柄空闲回收时间
fspublicPathstringstatic/public匿名可访问的公共目录
fssearchResultLimitint16搜索结果数上限
fsinitFileIndexbooltrue启动时初始化文件搜索索引
secretstokenSecretstring空实测为无效配置(见 4.6,勿依赖)
workersqueueSizeint1024后台任务队列长度
workerssleepCycint1工作协轮询间隔
workersworkerCountint2后台工作协程数
dbdbPathstringquickshare.sqlite数据库文件名(相对 fs.root 拼接)

💡 技术拓展:QuickShare 的配置体系由作者自研的 gocfg 库驱动,特点是「多层合并、按路径取值」——所有键最终都扁平化成 组.键 形式(如 Fs.Root),配置文件、命令行、环境变量都只是往这张扁平表里写值,谁后写谁生效。这也是「环境变量优先级可以压过一切」的根源:它不是在启动时读一次,而是在真正使用该值的那一刻才读。

四、核心参数分类详解

4.1 server 组:监听与超时

port(默认 8686)。本文实测将其改为 8130:配置文件写入 {"server": {"port": 8130}},重启后 curl http://localhost:8130/v1/settings/health 立即返回正常,旧端口 8686 不再监听——修改直接生效。

host(默认 0.0.0.0):监听所有网卡。仅本机使用可改为 127.0.0.1,配合反向代理暴露。

readTimeout / writeTimeout(毫秒):默认 2 秒 / 1 天。writeTimeout 有个隐蔽联动——它同时决定文件读取器的缓存时长(源码将 writeTimeout/1000 作为 reader TTL 传入文件系统层),大文件慢速下载场景不要调小这个值。

maxHeaderBytes(默认 512):HTTP 头大小上限。实测这个值的行为比较特殊——用 Python 对服务端发不同大小的自定义请求头(详见 4.1 节实测数据)。

pad=2100B -> HTTP 200
pad=3000B -> HTTP 200
pad=4096B -> HTTP 200
pad=5000B -> HTTP 431

即实际生效的上限约在 4 KB~5 KB 之间,并非字面的 512 字节(登录 cookie 本身就有约 200 字节,日常请求不受影响)。反向代理场景若遇到 431 错误,可调大此值后实测验证。

4.2 users 组:认证、验证码与配额

enableAuth(默认 true):认证总开关。生产环境严禁设为 false——关闭后所有请求(包括未登录的匿名请求)都按管理员身份处理,等于向全网开放管理员权限。它只适合纯内网临时调试。

captchaEnabled(默认 true):登录验证码。实测关闭方式——配置 {"users": {"captchaEnabled": false}} 后重启,登录请求不再携带验证码字段即可通过:

curl -s -c cookie.txt -X POST http://localhost:8130/v1/users/login \
  -H 'Content-Type: application/json' \
  -d '{"user":"admin","pwd":"q1w2e3r4"}'
# 输出:{"msg":"OK"}

若开启验证码,登录前需先 GET /v1/captchas/ 获取验证码 ID 与图片。公网部署建议保持开启。

minPwdLen(默认 8):新建用户时校验密码长度,短于 8 位会被拒绝。

uploadSpeedLimit / downloadSpeedLimit / spaceLimit:新用户的默认配额(已存在用户的配额存在数据库里,改配置不影响他们)。三者的默认值是 1 MB/s / 1 MB/s / 100 MB。实测一台初始化完成的服务上,管理员账号的实际配额为 1 GB 空间、50 MB/s 上传下载(管理员配额在数据库初始化时单独设定):

{"id":"0","name":"admin","role":"admin","usedSpace":"0",
 "quota":{"spaceLimit":"1073741824","uploadSpeedLimit":52428800,"downloadSpeedLimit":52428800}}

注意 downloadSpeedLimit 有启动期校验:低于 102400(100 KB/s)时服务启动直接失败,因为下载按 100 KB 分块读取,限速低于块大小会阻塞。

limiterCapacity / limiterCyc(默认 1000 次 / 1000 毫秒):接口限流窗口——每个用户 1 秒内最多 1000 次请求,超限返回 429。防止脚本爆破登录或爬接口。

predefinedUsers:数组,可在首次初始化时批量创建用户,元素含 name/role/pwd。仅数据库不存在(首次启动)时生效。

4.3 fs 组:存储根目录与搜索

root(默认 quickshare):所有用户文件与数据库的根目录。相对路径相对启动时的工作目录解析。两个实测要点:

  1. 目录会在启动时自动创建(权限 0760),无需手动 mkdir;
  2. 目录名不能与工作目录下的同名文件冲突,典型翻车是把二进制命名为 quickshare 放在数据目录同级(见排障实录 6.1)。

建议用绝对路径写死,如 {"fs": {"root": "/opt/quickshare/quickshare"}}。

searchResultLimit(默认 16):搜索结果上限。实测将配置文件设为 5 后,创建 6 个名称含 f1~f6 的文件,搜索行为如下(搜索按名称匹配,多个 k 参数为「与」关系):

curl -s -b cookie.txt 'http://localhost:8130/v1/fs/search?k=f1'
# 输出:{"results":["admin/files/srch/f1.txt"]}

curl -s -b cookie.txt 'http://localhost:8130/v1/fs/search?k=f1&k=f2'
# 输出:{"results":[]}

即该参数控制的是单次搜索最多返回的条目数;改小它可以让搜索在大量文件下更快返回。

initFileIndex(默认 true):启动时构建/加载文件名索引(持久化在数据目录 fileindex.jsonl)。关闭后搜索不可用。手动重建索引可调用 PUT /v1/fs/reindex。

opensLimit / openTTL:文件句柄池——高并发上传下载时可调大 opensLimit(默认 1024)。

4.4 workers 与 db 组

workerCount(默认 2)/ queueSize(默认 1024):后台任务协程数与队列长度。QuickShare 的空间用量重算等操作走异步任务队列,多用户高负载时可把 workerCount 调到 4~8。

dbPath(默认 quickshare.sqlite):数据库文件名,相对 fs.root 拼接——实测数据库实际位于数据目录内(<fs.root>/quickshare.sqlite),写绝对路径 d 参数(命令行 -d)可挪到别处。备份数据时需同时备份数据目录下的 SQLite 文件与用户文件。

4.5 环境变量:四个特殊参数

环境变量读取时机实测行为
PORT服务构造的最后阶段优先级最高,覆盖配置文件与 -p;只影响监听端口
DEFAULTADMIN仅数据库不存在(首次初始化)时初始管理员用户名;数据库已存在则完全忽略
DEFAULTADMINPWD同上初始管理员密码;未设置时随机生成并打印到控制台
TOKENSECRET服务启动构建 JWT 模块时实测不产生实际安全效果(见 4.6)

前两个变量配合可做到「首次启动全自动初始化管理员」,这正是部署指南中 Docker 方案的玩法:首次启动注入 DEFAULTADMIN=admin、DEFAULTADMINPWD=q1w2e3r4,之后数据库落盘,再重启时这两个变量即被忽略(改密码请走登录后的「修改密码」接口,而不是改环境变量)。

4.6 secrets.tokenSecret 与 TOKENSECRET 实测真相

这是本文实测中最重要的一个发现,请务必读完。

配置文件里有一组 secrets.tokenSecret,注释声称「留空则自动生成」;环境变量里有 TOKENSECRET。按直觉,它应该是登录令牌(JWT)的签名密钥:设置它可以让登录态跨重启保持有效。实测结论:两者在 0.11.4 中都不起实际作用。

实验一:改变 TOKENSECRET,旧登录态仍然有效。 同一台服务,先正常启动并登录得到 cookie,随后带上 TOKENSECRET=envsec123 重启,再用旧 cookie 访问管理员接口:

# 重启前登录并保存 cookie
curl -s -c r4a.cookie -X POST http://localhost:8130/v1/users/login \
  -H 'Content-Type: application/json' -d '{"user":"admin","pwd":"q1w2e3r4"}'
# 输出:{"msg":"OK"}

# 带 TOKENSECRET=envsec123 重启后,旧 cookie 依然有效:
curl -s -o /dev/null -w '%{http_code}\n' -b r4a.cookie http://localhost:8130/v1/users/list
# 输出:200   (按理应因签名密钥变化而失效)

实验二:完全伪造的管理员令牌直接被接受。 取一个真实 token,保持头部与签名不动、仅篡改载荷中的角色字段;再构造一个签名完全随意、但载荷声明自己是管理员的 token:

A.baseline(原始 token)            : 200
B.篡改 expire 为过去时间           : {"error":"token is expired"} [401]
C.篡改 role 为 visitor             : {"error":"access denied"} [403]
D.完全伪造的 admin token(假签名) : 200
E.不带任何 cookie                  : {"error":"access denied"} [403]

D 行意味着:任何人按 {uid, user, role, expire} 四个字段的格式拼一个载荷,签名随便填,就能以管理员身份调用接口。B/C 两行进一步说明服务端读到的是篡改后的值(过期检查、角色判断都基于被篡改的载荷),签名校验根本没有发生。

根因(源码核验):QuickShare 使用的 JWT 库 robbert229/jwt v2.0.0 提供了两个方法——Decode(仅解码载荷,不验签)和 DecodeAndValidate(验签)。QuickShare 的令牌校验代码只调用了前者。签名密钥确实参与了签发,但验证环节把它漏掉了,于是密钥是什么、改没改,都不影响结果。

给使用者的建议:

  1. 不要依赖 0.11.4 的登录令牌做防伪——暴露面管理才是真正的安全边界:不要把服务直接暴露公网,务必置于反向代理 + 访问控制(IP 白名单、VPN、认证网关)之后;
  2. enableAuth 保持 true、captchaEnabled 保持 true,抬高爆破成本;
  3. secrets.tokenSecret 与 TOKENSECRET 写不写都行,写了也无副作用(未来版本修复验签后它们会真正生效,届时不改配置即可平滑过渡);
  4. 关注上游版本更新,升级后重新按实验二验证一次。

五、生产配置模板

5.1 内网小团队模板(JSON,1~10 人,机械盘即可)

{
  "server": {
    "port": 8686,
    "writeTimeout": 86400000
  },
  "users": {
    "captchaEnabled": false,
    "uploadSpeedLimit": 10485760,
    "downloadSpeedLimit": 10485760,
    "spaceLimit": 1073741824
  },
  "fs": {
    "root": "/opt/quickshare/quickshare",
    "searchResultLimit": 16
  },
  "db": {
    "dbPath": "quickshare.sqlite"
  }
}

要点:内网受信环境可关验证码换取登录便捷;限速放宽到 10 MB/s;每人 1 GB 空间;数据目录用绝对路径避免工作目录漂移。磁盘占用 ≈ 实际文件总量 × 1.1(SQLite 与索引体积很小),内存常驻约 30~60 MB。

5.2 公网/半公网模板(YAML,置于反向代理之后)

server:
  port: 8686
  writeTimeout: 86400000
  maxHeaderBytes: 512
users:
  enableAuth: true
  captchaEnabled: true
  cookieSecure: true
  cookieHttpOnly: true
  cookieTTL: 86400
  minPwdLen: 10
  uploadSpeedLimit: 1048576
  downloadSpeedLimit: 1048576
  spaceLimit: 524288000
  limiterCapacity: 300
  limiterCyc: 1000
fs:
  root: /opt/quickshare/quickshare
  searchResultLimit: 8

要点:验证码必开;cookieSecure: true 配合 HTTPS;cookie 有效期缩到 1 天;限流收紧到每秒 300 次防爆破;minPwdLen 提到 10。**再次强调:0.11.4 的令牌不防伪造,公网暴露前必须叠加反向代理层的访问控制。**限速 1 MB/s 时 1 GB 文件约 17 分钟传完,按需调整。

六、常见问题与排障实录

6.1 启动即退出:can not create quickshare folder

现象:把二进制重命名为 quickshare 后直接启动,进程秒退(退出码 1),日志只有一行:

{"level":"fatal","ts":1793504896.9892006,"msg":"can not create quickshare folder: there is a file with same name"}

根因:默认数据目录名恰好也是 quickshare(fs.root 默认值)。启动时程序检查根目录,发现工作目录下已有一个同名文件(就是二进制自己),创建目录失败即 fatal。

解决:二进制改名(如 /opt/quickshare/bin/quickshare 配合不同的工作目录),或显式配置 fs.root 指向别的路径。推荐后者,一劳永逸。

6.2 重启失败:address already in use

现象:改完配置立即重启,新进程报监听失败:

listen error: listen tcp 0.0.0.0:8130: bind: address already in use

根因:QuickShare 收到终止信号后要完成收尾(持久化文件索引、停后台任务、关数据库),实测优雅退出耗时 1~2 秒;旧进程还没释放端口,新进程就抢跑了。旧进程退出阶段的实测现象还包括后台任务打印的收尾日志,此处不赘述。

解决:重启脚本里先确认进程消失再启动:

pkill -f 'quickshare -c' ; sleep 3
pgrep -af quickshare || /opt/quickshare/bin/quickshare -c /opt/quickshare/config.json

6.3 改了配置却不生效的排查清单

按命中率排序:

  1. 进程唯一性:pgrep -af quickshare 确认没有旧进程还挂在旧端口上(本人在实验中两次因残留旧实例而误判「配置未生效」);
  2. -c 指向:启动命令里的配置文件路径是否就是刚编辑的那份(多个 -c 时后面的覆盖前面的);
  3. 环境变量 PORT:若系统服务单元里设了 PORT,它会覆盖配置文件里的端口;
  4. 键名拼错:0.11.4 用分层小驼峰(searchResultLimit),不是 0.10 的大写键(SearchResultLimit)。虽然 JSON 键大小写不敏感,但层级写错(把 searchResultLimit 放到顶层而非 fs 组下)一定无效;
  5. 确认手段:改完重启后按 2.3 节三步走,别凭感觉。

6.4 secrets.tokenSecret 写了没反应

现象:配置文件里设置 "secrets": {"tokenSecret": "changed-secret-c1"},重启后预期「旧登录态全部失效」——实际旧 cookie 照样能用。

根因:同 4.6 节——签名验证环节缺失,密钥根本没参与校验;而且即便验签逻辑正常,该配置键也只被存储、不被启动代码读取(程序只读环境变量 TOKENSECRET)。

解决:无需处理,也不要依赖它做任何安全决策。升级新版本后重新验证。

6.5 删除文件报 500:used space can not be negative

现象:删除文件返回 500 {"error":"used space can not be negative"},且文件实际已被删除。

根因:每个用户有「已用空间」计数(SQLite 里),删除文件时会扣减该计数,若计数比文件实际大小还小(历史漂移,例如曾绕过接口直接删过文件、或早期版本 bug),扣减结果为负即报错。实测中计数为 12 时删除 30 字节文件稳定复现。

解决:调用管理员接口触发重算,让程序扫描实际目录重建计数(请求体为字符串格式的用户 ID):

curl -s -b cookie.txt -X PUT http://localhost:8130/v1/fs/used-space \
  -H 'Content-Type: application/json' -d '{"userID":"0"}'
# 输出:{"msg":"OK"}   (异步重算,稍后查询 usedSpace 已恢复正确)

6.6 从 0.10.x 升级后配置全部失效

现象:沿用旧版单层大写键的 config.json(如 "Root": "quickshare"),0.11.x 启动后一切按默认值跑。

根因:0.10.x 与 0.11.x 的配置结构是两代格式——旧版是单层大写键,0.11.x 改为六组分层小驼峰,旧文件里的键在新版对应不上(JSON 键大小写不敏感救不了「层级不同」的问题),全部被当作未知键忽略。

解决:按第三节总览表重写配置文件;数据库与文件目录结构是兼容的,只需迁移配置。

七、参考链接

QuickShare 0.11.4 配置参数详解 - Quzuo