diff --git a/README.md b/README.md index 16c405a..9ca2f70 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ cd web && npm run build && rm -rf internal/httpapi/dist && cp -r web/dist intern ```bash 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 ``` @@ -96,7 +96,7 @@ sudo systemctl restart webui4frpc ```bash 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 ``` @@ -152,12 +152,19 @@ sha256sum -c SHA256SUMS --ignore-missing ./webui4frpc -addr 127.0.0.1:7500 -user admin -password admin123 -workdir ./data ``` +或者用配置文件(推荐,口令不必出现在命令行与进程列表里): + +```bash +./webui4frpc -config ./config.json +``` + 打开 ,输入账号密码进入画布。首次使用可到「设置」页一键安装 frpc(或手动指定路径),然后回到画布创建 local / remote 并连线、保存。 ### 参数 | 参数 | 默认 | 说明 | | --- | --- | --- | +| `-config` | `/config.json`(或 `$W4F_CONFIG`) | 配置文件路径;文件不存在不算错误 | | `-addr` | `127.0.0.1:7500` | 监听地址 | | `-user` / `-password` | `admin` / `admin` | Basic 认证(自动同步为 system 管理员账号) | | `-workdir` | `./webui-frpc` | 数据目录(db / 配置 / 日志 / bin) | @@ -168,6 +175,104 @@ sha256sum -c SHA256SUMS --ignore-missing 环境变量 `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` → `/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=`、`join-key=`),`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 +``` + ### 负载均衡参数 每节点独立生效;集群页的开关**优先于**这里的默认值(在页面上选过就以页面为准,重启不丢)。