docs(readme): 补「从配置文件启动」章节与优先级说明

- 新增「从配置文件启动」小节:优先级(显式 flag > 配置文件 > 内置默认值)
  及其判定方式(flag.Visit,附回归测试名)、字段与 flag 对照表、
  ${VAR} 与 file: 两种口令写法、未知键/坏 JSON/未定义变量的失败语义、
  可直接抄的 config.json 与 systemd 片段。
- 安装与运行示例改为配置文件启动;参数表补 -config。
- 说明「未配口令」时保持旧行为但会打 WARNING。
This commit is contained in:
JianFeeeee
2026-10-23 09:12:34 +08:00
parent ee46b758fa
commit 1eeffd8434

109
README.md
View File

@ -88,7 +88,7 @@ cd web && npm run build && rm -rf internal/httpapi/dist && cp -r web/dist intern
```bash ```bash
sudo dpkg -i webui4frpc-0.1.4-linux-amd64.deb # 或 linux-arm64.deb sudo dpkg -i webui4frpc-0.1.4-linux-amd64.deb # 或 linux-arm64.deb
sudo nano /etc/webui4frpc/webui4frpc.env # 改掉默认密码 sudo nano /etc/webui4frpc/config.json # 改掉默认密码(见「从配置文件启动」)
sudo systemctl restart webui4frpc sudo systemctl restart webui4frpc
``` ```
@ -96,7 +96,7 @@ sudo systemctl restart webui4frpc
```bash ```bash
sudo rpm -i webui4frpc-0.1.4-linux-x86_64.rpm sudo rpm -i webui4frpc-0.1.4-linux-x86_64.rpm
sudo vi /etc/webui4frpc/webui4frpc.env sudo vi /etc/webui4frpc/config.json
sudo systemctl enable --now webui4frpc sudo systemctl enable --now webui4frpc
``` ```
@ -152,12 +152,19 @@ sha256sum -c SHA256SUMS --ignore-missing
./webui4frpc -addr 127.0.0.1:7500 -user admin -password admin123 -workdir ./data ./webui4frpc -addr 127.0.0.1:7500 -user admin -password admin123 -workdir ./data
``` ```
或者用配置文件(推荐,口令不必出现在命令行与进程列表里):
```bash
./webui4frpc -config ./config.json
```
打开 <http://127.0.0.1:7500/> ,输入账号密码进入画布。首次使用可到「设置」页一键安装 frpc(或手动指定路径),然后回到画布创建 local / remote 并连线、保存。 打开 <http://127.0.0.1:7500/> ,输入账号密码进入画布。首次使用可到「设置」页一键安装 frpc(或手动指定路径),然后回到画布创建 local / remote 并连线、保存。
### 参数 ### 参数
| 参数 | 默认 | 说明 | | 参数 | 默认 | 说明 |
| --- | --- | --- | | --- | --- | --- |
| `-config` | `<workdir>/config.json`(或 `$W4F_CONFIG`) | 配置文件路径;文件不存在不算错误 |
| `-addr` | `127.0.0.1:7500` | 监听地址 | | `-addr` | `127.0.0.1:7500` | 监听地址 |
| `-user` / `-password` | `admin` / `admin` | Basic 认证(自动同步为 system 管理员账号) | | `-user` / `-password` | `admin` / `admin` | Basic 认证(自动同步为 system 管理员账号) |
| `-workdir` | `./webui-frpc` | 数据目录(db / 配置 / 日志 / bin) | | `-workdir` | `./webui-frpc` | 数据目录(db / 配置 / 日志 / bin) |
@ -168,6 +175,104 @@ sha256sum -c SHA256SUMS --ignore-missing
环境变量 `W4F_HOST` 可覆盖节点对外可达的主机名(Docker DNS / 通配监听场景用)。 环境变量 `W4F_HOST` 可覆盖节点对外可达的主机名(Docker DNS / 通配监听场景用)。
## 从配置文件启动
除了命令行 flag,也可以用 JSON 配置文件启动。**推荐用它承载口令**:命令行参数会出现在
`ps` 输出、systemd 单元文件与 shell history 里,配置文件可以把口令放到只 root 可读的地方。
### 优先级
```
命令行 flag > 配置文件 > 内置默认值
```
- **只有显式传入的 flag 才会覆盖配置文件**。实现上用 `flag.Visit` 判断某个 flag 是否真的
被写在命令行上 —— Go 的 `flag` 包会先把默认值塞进变量,若直接读变量,默认值会无条件
压过配置文件。这是这套逻辑里唯一容易出错的地方,已有回归测试守着
(`internal/appconfig` 的 `TestResolveFileBeatsFlagDefaults`)。
- 配置文件里**没写**或留空的字段,才回落到内置默认值。
- `-peer` 特殊:显式传了 `-peer` 就用命令行的列表**整体替换**配置文件里的 `peers`,
而不是追加 —— 否则在命令行上删掉的对端会被配置文件复活。
- `-join-key` 的内置默认是 `$W4F_JOIN_KEY`;未显式传 flag 时,配置文件里的 `join_key`
只在环境变量为空时才生效。
- `-config` 未传时的查找顺序:`$W4F_CONFIG` → `<workdir>/config.json`。
注意 `workdir` 用的是 **flag 值**(显式或默认):配置文件必须先能被找到,才谈得上
读取它里面的 `workdir`。
- 文件**不存在不算错误**(回到旧的纯 flag 行为);文件存在但 JSON 解析失败、出现未知键
(例如把 `password` 拼成 `passwd`)、或引用了未定义的环境变量,都会**立即报错退出**,
不会静默忽略 —— 静默回落到 `admin/admin` 才是真正的安全问题。
### 字段
字段与 flag 一一对应,全部可选:
| 字段 | 对应 flag | 说明 |
| --- | --- | --- |
| `addr` | `-addr` | 监听地址 |
| `user` | `-user` | Basic 认证用户名 |
| `password` | `-password` | Basic 认证口令(推荐用 `${VAR}` 或 `file:`) |
| `workdir` | `-workdir` | 数据目录 |
| `bin` | `-bin` | 初始 frpc 二进制路径 |
| `frpc` | `-frpc` | worker 默认 frpc 路径 |
| `peers` | `-peer` | 集群对端 `host:port` 数组 |
| `join_key` | `-join-key` | 集群准入密钥(也接受 `joinKey` 写法) |
### 口令的两种写法
所有字符串字段都支持这两种展开形式,不只是 `password`:
```json
{ "password": "${W4F_PASSWORD}" }
```
```json
{ "password": "file:/etc/webui4frpc/secret/password" }
```
- `${VAR}` 取环境变量;变量**未定义或是空值**会报错退出(而不是展开成空口令)。
想写字面量 `$` 用 `$$`。
- `file:/path` 只取文件的**第一行**(去掉行尾换行),适合 `chmod 600` 的 secrets 文件。
文件读不到会报错退出。
- 展开后的值**不会**出现在任何日志里:启动横幅只打印「字段来源」与脱敏摘要
(`password=<redacted>`、`join-key=<redacted>`),`Values` 的 `String()` 也做了脱敏,
所以连手滑 `log.Printf("%v", ...)` 都不会漏。
### 示例
```json
{
"addr": "0.0.0.0:7500",
"user": "jianf",
"password": "file:/etc/webui4frpc/secret/password",
"workdir": "/var/lib/webui4frpc",
"frpc": "/usr/local/bin/frpc",
"peers": ["10.0.0.2:7500", "10.0.0.3:7500"],
"join_key": "${W4F_JOIN_KEY}"
}
```
对应的 systemd 单元不再需要把口令写进 `ExecStart`:
```ini
[Service]
User=webui4frpc
Group=webui4frpc
EnvironmentFile=-/etc/webui4frpc/webui4frpc.env
ExecStart=/usr/bin/webui4frpc -config /etc/webui4frpc/config.json
ReadWritePaths=/var/lib/webui4frpc
```
`packaging/common/` 里带了一份可直接抄的单元模板与 `config.json` 示例。
### 关于「没配口令」
配置文件里没写 `password`、命令行也没给时,**行为与旧版一致**(回落到内置默认值),
但启动日志会打一行明确警告:
```
WARNING: no password configured (neither -password nor the config file); using the built-in default — change it before exposing this node
```
### 负载均衡参数 ### 负载均衡参数
每节点独立生效;集群页的开关**优先于**这里的默认值(在页面上选过就以页面为准,重启不丢)。 每节点独立生效;集群页的开关**优先于**这里的默认值(在页面上选过就以页面为准,重启不丢)。