Static Web Server 2.44.1 配置参数详解
Static Web Server v2.44.1 配置参数全解:CLI/TOML/环境变量三种配置源与优先级实测、[general] 与 [advanced] 全参数表、压缩/认证/CORS/TLS/虚拟主机/内存缓存逐项实测与两套生产配置模板。
Static Web Server 2.44.1 配置参数详解
目标:掌握 Static Web Server(SWS)v2.44.1 的全部配置参数——三种配置来源的优先级、每个参数的真实默认值、关键参数的实测效果验证,并能按场景套用生产配置模板。全部参数取自官方二进制
--help实测回显与源码配置结构(src/settings/file.rs),实测环境为 Ubuntu 22.04(x86_64)。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- 软件版本:Static Web Server v2.44.1(官方 musl 二进制,2026-10-07 构建;版本查询日期 2026-10-20)
- 配置文件:
/etc/static-web-server/static-web-server.toml(TOML 格式) - 服务托管:systemd(
static-web-server.service),监听0.0.0.0:8780,站点根目录/var/www/html - 安装方式:官方 tar.gz 二进制 + systemd(安装过程见本专栏《Ubuntu 22.04 安装 Static Web Server 指南》)
二、前置条件
- 已按安装指南完成 SWS 安装与 systemd 托管,
systemctl is-active static-web-server返回active(实测回显:active); - 站点根目录存在演示文件(安装指南 4.4 节的
/var/www/html/index.html); - 修改配置前建议备份:
cp /etc/static-web-server/static-web-server.toml{,.bak}; - 生成 Basic 认证口令散列需要 htpasswd 工具:
apt-get install -y apache2-utils(安装实测回显略,版本无要求)。
三、参数查看与修改方式
3.1 三种配置来源
SWS 的同一个参数有三个等价的设置途径,键名一一对应(以监听端口为例):
| 来源 | 写法 | 优先级 |
|---|---|---|
| TOML 配置文件 | [general] 节内 port = 8780 | 最高(显式写了就生效) |
| CLI 参数 | -p 8781 或 --port 8781 | 中(配置文件未写该键时生效) |
| 环境变量 | SERVER_PORT=8781 | 中(与 CLI 同层,CLI 显式值覆盖环境变量) |
| 内置默认 | — | 最低(以上均未设置时取默认值) |
⚠️ 与多数软件「命令行最高」的习惯相反,SWS 是配置文件优先。实测验证:配置文件写
port = 8780,同时命令行传-p 8781启动,启动日志显示server bound to tcp socket 0.0.0.0:8780——配置文件的 8780 生效,CLI 的 8781 被忽略。源码合并逻辑(src/settings/mod.rs)亦证实:配置文件键存在时无条件覆盖 CLI/环境变量值。
环境变量名即参数名的大写下划线形式并加 SERVER_ 前缀,--help 回显中每个参数下方都标注了对应变量(节选):
-p, --port <PORT>
Host port
[env: SERVER_PORT=]
[default: 80]
3.2 查看当前生效配置
SWS 没有「打印当前配置」的命令,查看生效配置靠两个手段:
--help查看全部参数与真实默认值(含环境变量名),完整回显见本专栏《Static Web Server 2.44.1 常用 CLI 命令详解》;- 以
-g info启动看日志:每个特性一行状态输出,如实测回显(节选):
INFO static_web_server::server: config file used: /etc/static-web-server/static-web-server.toml
INFO static_web_server::server: index files: index.html, index.htm
INFO static_web_server::directory_listing: directory listing: enabled=false
INFO static_web_server::compression: auto compression: enabled=true, formats=deflate,gzip,brotli,zstd, compression level=Default
INFO static_web_server::mem_cache::cache: in-memory cache (experimental): enabled=false
3.3 修改方式与生效条件
- 编辑 TOML 文件:
vim /etc/static-web-server/static-web-server.toml; - 重启服务生效(SWS 不支持配置热加载,SIGHUP 也不重读):
systemctl restart static-web-server; - 确认:
journalctl -u static-web-server --no-pager -n 5观察新配置对应的状态行,无error during toml configuration file deserialization即加载成功。
四、参数总览
4.1 [general] 通用参数表(v2.44.1 全量)
下表默认值均来自官方二进制 --help 实测回显:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| host | 字符串 | :: | 监听地址(如 127.0.0.1、0.0.0.0、::1) |
| port | 整数 | 80 | 监听端口 |
| root | 路径 | ./public | 静态文件根目录 |
| log-level | 枚举 | error | 日志级别:error/warn/info/debug/trace |
| log-with-ansi | 布尔 | false | 日志 ANSI 彩色输出 |
| cache-control-headers | 布尔 | true | 按文件类型自动附加 Cache-Control |
| compression | 布尔 | true | 按需压缩(gzip/deflate/brotli/zstd) |
| compression-level | 枚举 | default | 压缩级别:fastest/best/default |
| compression-static | 布尔 | false | 优先回源预压缩文件(.gz/.br/.zst) |
| page404 | 路径 | ./404.html | 404 页面(相对路径相对 root) |
| page50x | 路径 | ./50x.html | 50x 页面 |
| http2 | 布尔 | false | 启用 HTTP/2(需 TLS) |
| http2-tls-cert | 路径 | — | TLS 证书文件 |
| http2-tls-key | 路径 | — | TLS 私钥文件 |
| https-redirect | 布尔 | false | HTTP→HTTPS 重定向(依赖 http2 开启) |
| https-redirect-host | 字符串 | localhost | HTTPS 跳转目标主机 |
| https-redirect-from-port | 整数 | 80 | HTTP 重定向监听端口 |
| https-redirect-from-hosts | 字符串 | localhost | 允许重定向的来源主机列表 |
| security-headers | 布尔 | false | HSTS + X-Frame-Options + CSP 安全头 |
| cors-allow-origins | 字符串 | "" | 允许的 CORS 来源(逗号分隔,* 全放行) |
| cors-allow-headers | 字符串 | origin, content-type, authorization | 允许的请求头 |
| cors-expose-headers | 字符串 | origin, content-type | 暴露给浏览器的响应头 |
| index-files | 字符串 | index.html | 目录索引文件(逗号分隔,字符串非数组) |
| directory-listing | 布尔 | false | 目录列表 |
| directory-listing-order | 整数 | 6 | 列表排序码:0-5(名称/时间/大小 升降序),6 无序 |
| directory-listing-format | 枚举 | html | 列表格式:html/json |
| directory-listing-download | 列表 | 空(禁用) | 目录打包下载格式,仅 targz |
| basic-auth | 字符串 | "" | Basic 认证 user-id:bcrypt-hash |
| fd | 整数 | — | 从指定文件描述符继承监听(systemd socket activation) |
| threads-multiplier | 整数 | 1 | worker 线程数倍率(线程数=CPU 核数×n) |
| max-blocking-threads | 整数 | 512 | 阻塞线程池上限 |
| grace-period | 整数 | 0 | 优雅停机宽限秒数(上限 255) |
| page-fallback | 路径 | "" | SPA 回退页(GET 未命中时 200 返回) |
| log-remote-address | 布尔 | false | 访问日志记录客户端地址 |
| log-x-real-ip | 布尔 | false | 日志记录 X-Real-IP 头 |
| log-forwarded-for | 布尔 | false | 日志记录 X-Forwarded-For 头 |
| trusted-proxies | 列表 | 空(信任所有) | 可信代理 IP 列表(X-Forwarded-For 取值来源) |
| redirect-trailing-slash | 布尔 | true | 目录路径缺尾斜杠时 308 重定向 |
| ignore-hidden-files | 布尔 | true | 拒绝服务点开头的隐藏文件 |
| disable-symlinks | 布尔 | true | 禁止符号链接逃逸 |
| use-relative-root | 布尔 | false | 请求时解析 root(支持运行时替换软链) |
| health | 布尔 | false | 开启 /health 探活端点 |
| accept-markdown | 布尔 | false | Accept: text/markdown 内容协商 |
| text-charset | 布尔 | true | 文本响应自动附 charset=utf-8 |
| metrics | 布尔 | false | 开启 /metrics Prometheus 指标 |
| maintenance-mode | 布尔 | false | 维护模式(全站 503) |
| maintenance-mode-status | 整数 | 503 | 维护模式状态码 |
| maintenance-mode-file | 路径 | "" | 自定义维护页 HTML |
| memory-cache | 布尔(实验) | false | 内存文件缓存总开关 |
4.2 [advanced] 高级参数表(仅配置文件可用)
| 参数 | 结构 | 说明 |
|---|---|---|
[[advanced.headers]] | 数组表 | 自定义响应头:source(通配符匹配请求路径)+ headers(键值对) |
[[advanced.redirects]] | 数组表 | URL 重定向:host(可选)/source/destination/kind(301 或 302) |
[[advanced.rewrites]] | 数组表 | URL 重写:source/destination/redirect(可选 301/302,缺省为内部重写) |
[[advanced.virtual-hosts]] | 数组表 | 域名虚拟主机:host/root |
[advanced.memory-cache] | 表 | 内存缓存细则:capacity(条目数)/ttl(秒)/tti(秒)/max-file-size(字节) |
关键差异解读:[general] 的键在 CLI/环境变量/TOML 三处均可设置;[advanced] 五组高级规则只能写在 TOML 配置文件里,CLI 与环境变量没有对应键,这也是复杂静态站点必须用配置文件模式的原因。
五、核心参数分类详解
5.1 网络与监听(host / port / threads-multiplier / grace-period)
监听地址与端口决定服务入口,线程与停机参数决定运行时行为。实测配置(环境变量文件含 SERVER_GRACE_PERIOD=2)后重启服务并观察启动日志:
systemctl restart static-web-server
journalctl -u static-web-server --no-pager -n 50 -o cat | grep -E "bound|listening|worker|blocking|grace"
实测回显(一轮 systemctl restart = 旧进程优雅退出 + 新进程启动,日志完整呈现两个阶段):
2026-10-20T16:38:30.652415834Z INFO static_web_server::signals: grace period of 2s after the SIGTERM started
2026-10-20T16:38:32.653652113Z INFO static_web_server::signals: grace period has elapsed
2026-10-20T16:38:32.653689717Z INFO static_web_server::signals: delegating server's graceful shutdown
2026-10-20T16:38:32.672354877Z INFO static_web_server::server: server bound to tcp socket 0.0.0.0:8780
2026-10-20T16:38:32.672356963Z INFO static_web_server::server: runtime worker threads: 12
2026-10-20T16:38:32.672359192Z INFO static_web_server::server: runtime max blocking threads: 512
2026-10-20T16:38:32.672390001Z INFO static_web_server::server: grace period before graceful shutdown: 2s
2026-10-20T16:38:32.672530448Z INFO static_web_server::server: http1 server is listening on http://0.0.0.0:8780
要点:worker threads: 12 来自默认 threads-multiplier = 1(本机 12 核);grace period: 2s 来自环境变量 SERVER_GRACE_PERIOD=2。实测优雅停机:systemctl stop static-web-server 在 2 秒宽限期下耗时 real 0m2.005s(日志即上例前三行的 grace period of 2s after the SIGTERM started → grace period has elapsed → delegating server's graceful shutdown)。有长连接下载流量时建议设 2–10 秒,避免在途请求被掐断。
5.2 静态资源与索引(root / index-files / redirect-trailing-slash / ignore-hidden-files / disable-symlinks)
实测效果(默认配置下):
curl -sI http://127.0.0.1:8780/assets | head -3 # 目录缺尾斜杠
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8780/.hidden.txt
实测回显:
HTTP/1.1 308 Permanent Redirect
location: /assets/
vary: accept-encoding
404
- 尾斜杠 308 重定向由
redirect-trailing-slash = true(默认)驱动,保证目录 URL 规范化; .hidden.txt返回 404:ignore-hidden-files = true(默认)拒绝服务 dotfiles,防配置/密钥误发布;disable-symlinks = true(默认)阻止通过软链跳出 root,除非站点确需软链共享文件,保持默认;index-files是字符串:"index.html, index.htm"按顺序探测,实测日志index files: index.html, index.htm。
5.3 压缩(compression / compression-level / compression-static)
compression = true(默认)按请求 Accept-Encoding 协商压缩,只作用于文本类 MIME。实测(19KB 文本文件):
curl -s -o /dev/null -D - -H "Accept-Encoding: gzip" http://127.0.0.1:8780/big.txt | grep -iE "content-encoding|content-type"
curl -s -o /dev/null -D - -H "Accept-Encoding: br" http://127.0.0.1:8780/big.txt | grep -i "content-encoding"
curl -s -o /dev/null -D - -H "Accept-Encoding: zstd" http://127.0.0.1:8780/big.txt | grep -i "content-encoding"
curl -s -o /dev/null -D - http://127.0.0.1:8780/big.txt | grep -iE "content-encoding|content-length"
实测回显:
content-type: text/plain; charset=utf-8
content-encoding: gzip
content-encoding: br
content-encoding: zstd
content-length: 19292
💡 技术拓展:压缩格式怎么选——
格式 压缩率 兼容性 建议 gzip 中 全部浏览器 兜底默认 deflate 中 全部浏览器 很少单独用 brotli 高 现代浏览器 静态资源首选 zstd 高、解压最快 新式客户端 大文件分发优选 SWS 按客户端
Accept-Encoding自动选择,四种全部内置,无需二选一;compression-level建议default,best只用于带宽极度昂贵且 CPU 空闲的场景。compression-static = true时优先找.gz/.br/.zst预压缩文件直接发送,适合构建期预压缩的静态站点。
5.4 缓存控制头(cache-control-headers)
cache-control-headers = true(默认)按文件类型自动附加缓存头。实测:HTML 返回 cache-control: max-age=86400(缓存 1 天),CSS 返回 cache-control: max-age=31536000(1 年,带哈希指纹的静态资源可长缓存),404 响应返回 cache-control: no-cache。该行为内置于源码 control_headers.rs 的类型清单,不可自定义明细,需要覆盖个别路径时配合 [advanced.headers] 使用(见 5.9)。
5.5 CORS(cors-allow-origins / cors-allow-headers / cors-expose-headers)
实测配置 cors-allow-origins = "*" 后的预检请求:
curl -s -o /dev/null -D - -X OPTIONS -H "Origin: https://example.com" -H "Access-Control-Request-Method: GET" http://127.0.0.1:8780/index.html | grep -iE "HTTP|access-control"
实测回显:
HTTP/1.1 204 No Content
access-control-allow-headers: content-type, authorization, origin
access-control-expose-headers: content-type, origin
access-control-allow-methods: HEAD, GET, OPTIONS
access-control-allow-origin: https://example.com
要点:cors-allow-origins 为空(默认)时不输出任何 CORS 头;* 全放行仅适用于公开只读资源;精确域名列表(逗号分隔,如 https://a.example.com, https://b.example.com)更安全。静态 API 化的文件服务才需要它,纯站点可保持关闭。
5.6 Basic 认证(basic-auth)
basic-auth 的值格式为 user-id:bcrypt-hash,散列用 htpasswd 生成(口令以 admin/q1w2e3r4 演示):
htpasswd -bnBC 10 "" 'q1w2e3r4' | tr -d ':\n'
实测回显:
$2y$10$2hjAJKs0Il2cJV9QbZW.feNdFHblEok5/UXMW3AMHns5Vq1lYFCb6
配置 basic-auth = "admin:$2y$10$2hjAJKs0Il2cJV9QbZW.feNdFHblEok5/UXMW3AMHns5Vq1lYFCb6" 后实测:
curl -sI http://127.0.0.1:8780/ | head -6
curl -s -o /dev/null -w "%{http_code}\n" -u admin:q1w2e3r4 http://127.0.0.1:8780/
curl -s -o /dev/null -w "%{http_code}\n" -u admin:wrongpass http://127.0.0.1:8780/
实测回显:
HTTP/1.1 401 Unauthorized
content-type: text/html; charset=utf-8
content-length: 318
accept-ranges: bytes
www-authenticate: Basic realm="Static Web Server", charset="UTF-8"
date: Tue, 20 Oct 2026 16:16:52 GMT
200
401
⚠️ 注意三点:散列中含
$字符,写进 systemd 环境变量文件时无需转义但不能放在 shell 双引号内展开;启动日志会提示bcrypt is limited to 72 bytes per password(口令散列前 72 字节有效);多账号用逗号分隔(user1:hash1, user2:hash2)。
5.7 TLS 与 HTTP/2(http2 / http2-tls-cert / http2-tls-key / https-redirect)
生成自签证书并启用 HTTP/2(生产请用正规 CA 签发的证书):
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:prime256v1 -keyout /etc/static-web-server/local.key -out /etc/static-web-server/local.crt -days 365 -nodes -subj "/CN=localhost"
chown root:www-data /etc/static-web-server/local.key /etc/static-web-server/local.crt
chmod 640 /etc/static-web-server/local.key /etc/static-web-server/local.crt
配置 http2 = true、http2-tls-cert = "/etc/static-web-server/local.crt"、http2-tls-key = "/etc/static-web-server/local.key" 并重启后实测:
journalctl -u static-web-server --no-pager -n 2 -o cat | grep listening
curl -skI --http2 https://127.0.0.1:8780/ | head -3
实测回显:
INFO static_web_server::server: http2 server is listening on https://0.0.0.0:8780
HTTP/2 200
content-length: 170
content-type: text/html; charset=utf-8
要点:启用 http2 后同一端口只跑 HTTPS(HTTP/1.1 明文监听即停止);https-redirect = true 会在 80 端口(https-redirect-from-port 可改)再起一个重定向监听,把 HTTP 请求 301 到 HTTPS;私钥文件必须保证 www-data 可读,权限排障实录见安装指南 FAQ(Permission denied (os error 13))。
5.8 目录列表(directory-listing 系列)
directory-listing = true 后访问无索引文件的目录返回内置 HTML 列表页,实测 curl http://127.0.0.1:8780/docs/ 返回页脚为 Powered by Static Web Server (SWS) / static-web-server.net 的索引页,含名称/修改时间/大小三列(?sort=0/2/4 可点排序,对应 directory-listing-order 的 0-5 码,默认 6 不排序)。directory-listing-format = "json" 可输出机器可读 JSON;directory-listing-download = ["targz"] 让每个目录页出现整目录打包下载入口。文件分发站推荐开启,正式站点关闭(避免暴露目录结构)。
5.9 高级规则([advanced.headers] / redirects / rewrites / virtual-hosts / memory-cache)
五组规则仅 TOML 可用。以下配置全部实测生效:
[general]
host = "0.0.0.0"
port = 8780
root = "/var/www/html"
log-level = "info"
health = true
security-headers = true
memory-cache = true
http2 = true
http2-tls-cert = "/etc/static-web-server/local.crt"
http2-tls-key = "/etc/static-web-server/local.key"
[advanced.memory-cache]
capacity = 512
ttl = 60
tti = 30
max-file-size = 1048576
[[advanced.virtual-hosts]]
host = "app2.example.com"
root = "/var/www/app2"
[[advanced.headers]]
source = "**/*.html"
headers = { Cache-Control = "public, max-age=3600", X-Frame-Options = "DENY", X-Custom-Header = "sws-demo" }
[[advanced.redirects]]
source = "/old-page"
destination = "/index.html"
kind = 301
[[advanced.rewrites]]
source = "/v1/pretty"
destination = "/assets/style.css"
逐项实测回显(演示站使用 5.7 节生成的自签证书,故命令加 -sk 忽略自签告警;-H "Host: app2.example.com" 模拟第二个域名请求):
curl -skI --http2 https://127.0.0.1:8780/ | grep -iE "HTTP|x-frame|cache-control|x-custom|strict|content-security"
curl -skI https://127.0.0.1:8780/old-page | grep -iE "HTTP|location"
curl -sk -o /dev/null -w "%{http_code} %{content_type}\n" https://127.0.0.1:8780/v1/pretty
curl -sk --http2 -H "Host: app2.example.com" https://127.0.0.1:8780/
journalctl -u static-web-server --no-pager -n 40 -o cat | grep -E "in-memory|security headers"
HTTP/2 200
cache-control: public, max-age=3600
strict-transport-security: max-age=63072000; includeSubDomains; preload
x-frame-options: DENY
content-security-policy: frame-ancestors 'self'
x-custom-header: sws-demo
HTTP/2 301
location: /index.html
200 text/css
virtual host app2
2026-10-20T16:36:19.938873619Z INFO static_web_server::security_headers: security headers: enabled=true
2026-10-20T16:36:19.938875481Z INFO static_web_server::mem_cache::cache: in-memory cache (experimental): enabled=true, capacity=512, ttl=60, tti=30, max_file_size=1048576
逐项说明:
- headers:
source用 glob 匹配请求路径(**/*.html匹配全部 HTML),headers键值对直接覆盖内置 Cache-Control 并附加自定义响应头(实测x-custom-header: sws-demo随每个 HTML 响应返回); - redirects:
/old-page返回 301 与location: /index.html,kind只接受 301/302;host可选,用于仅对特定域名跳转; - rewrites:
/v1/pretty内容返回 CSS(200 text/css)而浏览器地址不变——重写是服务端内部映射;redirect键填 301/302 时变为显式跳转; - virtual-hosts:
Host: app2.example.com命中后 root 切到/var/www/app2,单实例托管多站点;未匹配任何条目时回落到[general].root; - memory-cache:实验特性,
capacity/ttl/tti/max-file-size四值在启动日志确认(enabled=true, capacity=512, ttl=60, tti=30, max_file_size=1048576),把热点小文件缓存进内存减少磁盘 IO;版本升级可能变更行为,生产启用前先压测。
5.10 探活与指标(health / metrics)
在开启 health = true、metrics = true 且已配置 basic-auth(5.6 节口令,/metrics 与全站同受认证保护)的实例上实测:
curl -s -o /dev/null -w "%{http_code} %{size_download}B\n" http://127.0.0.1:8780/health
curl -s -u admin:q1w2e3r4 http://127.0.0.1:8780/metrics | head -4
实测回显:
200 2B
# HELP sws_http_connections_active Number of currently active HTTP connections.
# TYPE sws_http_connections_active gauge
sws_http_connections_active 1
/health 固定返回 200 与 2 字节正文且不产生访问日志(适合负载均衡探活不打爆日志);/metrics 输出 Prometheus 文本格式(连接数 gauge、请求延迟直方图 sws_http_request_duration_seconds_bucket 等),Prometheus 抓取配置 metrics_path: "/metrics" 即可。注意:未开 Basic 认证时 /metrics 无鉴权,公网环境应通过反向代理或网络策略限制访问(SWS 启动日志会主动警告)。
5.11 错误页与回退页(page404 / page50x / page-fallback)
page404/page50x 指定自定义错误页(相对路径相对 root 解析),实测 404 响应:
HTTP/1.1 404 Not Found
content-type: text/html; charset=utf-8
content-length: 312
vary: accept-encoding
cache-control: no-cache
page-fallback 是 SPA 神器:指定一个 HTML 后,所有 GET 未命中路径都返回该页(200 状态码),前端路由(React/Vue history 模式)不再 404。不配置则该特性不启用。
5.12 维护模式(maintenance-mode 系列)
maintenance-mode = true 后全站统一返回维护页,实测:
curl -sk --http2 -o /dev/null -w "%{http_code}\n" https://127.0.0.1:8780/
实测回显:
503
默认状态码 503(maintenance-mode-status 可改),对搜索引擎友好(503 表示临时不可用,爬虫会稍后再来)。配合 maintenance-mode-file 换成带公告的维护页。发布静态站新版本时:开维护模式 → 替换文件 → 关维护模式,全程对用户透明。
5.13 日志与调试(log-level / log-remote-address / log-with-ansi)
| 参数 | 取值 | 效果(实测) |
|---|---|---|
| log-level | error/warn/info/debug/trace | info 起输出请求日志;error 时几乎静默 |
| log-remote-address | true | 请求日志附客户端地址:incoming request: method=GET uri=/docs/(实测行) |
| log-x-real-ip / log-forwarded-for | true | 反代场景记录真实 IP 头,配合 trusted-proxies 防伪造 |
| log-with-ansi | true | 交互终端彩色输出,journald 场景保持 false |
生产建议 log-level = "warn"(只看异常),排障临时调 info/debug。
六、生产配置模板
6.1 模板一:小型文档站(1 核 / 1GB 内存 / 普通云盘)
[general]
host = "0.0.0.0"
port = 80
root = "/var/www/docs"
log-level = "warn"
compression = true
compression-level = "default"
cache-control-headers = true
redirect-trailing-slash = true
ignore-hidden-files = true
disable-symlinks = true
health = true
[advanced]
适用:个人/团队文档站、博客,1 核 1GB 足够支撑日均十万级 PV(SWS 常驻内存约 18MB 实测);health = true 供监控探活。
6.2 模板二:下载分发站(4 核 / 8GB 内存 / NVMe SSD,HTTPS + 认证 + 目录列表)
[general]
host = "0.0.0.0"
port = 443
root = "/data/downloads"
log-level = "warn"
http2 = true
http2-tls-cert = "/etc/static-web-server/site.crt"
http2-tls-key = "/etc/static-web-server/site.key"
basic-auth = "admin:$2y$10$2hjAJKs0Il2cJV9QbZW.feNdFHblEok5/UXMW3AMHns5Vq1lYFCb6"
compression = false
directory-listing = true
directory-listing-order = 4
directory-listing-format = "html"
directory-listing-download = ["targz"]
grace-period = 10
threads-multiplier = 1
metrics = true
health = true
[advanced]
适用:内部软件包/大文件分发。要点:大文件场景关闭按需压缩(compression = false,压缩已打包文件无意义且浪费 CPU);目录列表按大小升序(order = 4)+ 整目录 targz 打包下载;grace-period = 10 保证升级重启时在途下载完成;443 特权端口绑定需 systemd 托管(root 启动后自动降权到 User=)或用官方 socket activation 方案(fd 参数)。
6.3 模板三:SPA 前端站(2 核 / 4GB,反代后置)
[general]
host = "127.0.0.1"
port = 8780
root = "/var/www/spa"
log-level = "warn"
page-fallback = "/var/www/spa/index.html"
page404 = "/var/www/spa/404.html"
page50x = "/var/www/spa/50x.html"
compression = true
compression-static = true
security-headers = true
log-remote-address = true
log-forwarded-for = true
trusted-proxies = ["10.0.0.0/8"]
metrics = true
[[advanced.headers]]
source = "/assets/**"
headers = { Cache-Control = "public, max-age=31536000, immutable" }
[[advanced.headers]]
source = "/index.html"
headers = { Cache-Control = "no-cache" }
适用:前端构建产物托管,仅监听 127.0.0.1 由 Nginx/Caddy/Traefik 反代对外。要点:page-fallback 承接前端 history 路由;compression-static 配合构建期预压缩(vite plugin 生成 .gz/.br);安全头全开;带指纹的 assets 长缓存 + index.html 不缓存;trusted-proxies 限定反代网段防 X-Forwarded-For 伪造。
七、常见问题(FAQ)
Q1:启动即失败,报 invalid type: sequence, expected a string in general.index-files?
index-files 类型是字符串(逗号分隔),写成数组会反序列化失败。实测报错回显:
Caused by:
0: error during toml configuration file deserialization
1: invalid type: sequence, expected a string
in `general.index-files`
改为 index-files = "index.html, index.htm"。通用排查法:该错误必带具体键名,按报错修正该键的类型即可。
Q2:改了配置文件为什么不生效?
SWS 不支持热加载,必须 systemctl restart static-web-server。另外确认改的是配置文件优先链路里真正生效的那一层:若环境变量文件里同名 SERVER_* 变量与 TOML 冲突,TOML 胜出(见 3.1 优先级实测)。
Q3:CLI 参数和配置文件同时设置,谁生效?
配置文件。实测:配置文件 port = 8780 + CLI -p 8781,启动日志 server bound to tcp socket 0.0.0.0:8780,CLI 值被忽略。
Q4:/metrics 401 或裸奔无鉴权?
开了 basic-auth 则 /metrics 同样要带凭据(curl -u admin:<password>);没开认证时 /metrics 任何人可读(启动日志会警告),公网务必收紧。
Q5:维护模式打开后管理员自己也被挡住怎么办?
维护模式作用于全部路径,没有白名单机制。替代方案:临时把 root 切到维护页目录,或用 [[advanced.headers]] + 反代层做灰度。发布窗口短的话直接改 maintenance-mode-status 为 503 保持 SEO 友好即可。
Q6:如何确认某个安全开关真的生效?
两步:启动日志核对状态行(如 disable symlinks: enabled=true、ignore hidden files: enabled=true);行为实测(如 curl -I http://127.0.0.1:8780/.hidden.txt 应 404)。本文所有开关均按此法双重验证。
八、参考链接
- 官方配置文件文档:https://static-web-server.net/configuration/config-file/
- 官方命令行参数文档:https://static-web-server.net/configuration/command-line-arguments/
- v2.44.1 源码配置结构:https://github.com/static-web-server/static-web-server/blob/master/src/settings/file.rs
- 站内延伸阅读:《Ubuntu 22.04 安装 Static Web Server 指南》、《Static Web Server 2.44.1 常用 CLI 命令详解》、《Static Web Server 介绍与选型指南》