docs: document BGFILTER_AUTH_TOKEN auth and despill-off default

DEPLOY.md / DEPLOY_ZH.md:
- add BGFILTER_AUTH_TOKEN to the env-var table
- new "Authentication" subsection under §10: opt-in token via the
  X-Genarrative-Image-Token header (401 on missing/wrong), fail-open when
  unset (proxy handles it), /healthz always open; drop the stale "no
  authentication" line
- note that despill is off by default (same-hue false-positive)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-11 08:56:39 +00:00
parent 4d34c96bed
commit 1861cb0199
2 changed files with 57 additions and 8 deletions
+32 -4
View File
@@ -202,6 +202,7 @@ redirect back to `huggingface.co`, which recent `huggingface_hub` rejects with
| `BGFILTER_MAX_IMAGE_PIXELS` | `4194304` | Reject larger inputs with `413` (~4 MP) |
| `BGFILTER_PRELOAD` | `1` | Load default models at startup (first request isn't cold) |
| `BGFILTER_CROSS_CHECK` | config (`on`) | Force the cross-check veto on/off (`0` disables; needs `BiRefNet_HR-matting`) |
| `BGFILTER_AUTH_TOKEN` | — | If set, `/remove-background` requires header `X-Genarrative-Image-Token` to equal it (constant-time; `401` otherwise). Unset = **open** (auth left to a fronting proxy). `/healthz` stays open. See §10. |
| `BGFILTER_WEIGHTS_DIR` | `models` | Where local weight folders are looked up (Option B) |
| `HF_HOME` | — | HF cache location (Option A) |
| `HF_HUB_OFFLINE` / `TRANSFORMERS_OFFLINE` | — | Set to `1` in production once weights are cached |
@@ -233,6 +234,12 @@ Two model knobs live in the **config file** (`model:` section), not env vars:
| `model.precision` | `fp32` | `fp32` or `bf16`. bf16 is used **only** on hardware with native kernels (CUDA, or a CPU with AVX512-BF16/AMX); otherwise it warns and falls back to fp32. Also settable per model under `segmentation:` / `cross_check:`. |
| `model.attn_query_chunk` | `2048` | Query-row chunk for ViTMatte's global attention. Smaller (e.g. `512`) caps the O(N²) memory transient for a few % more compute; output is bit-for-bit identical. `0` disables chunking (stock one-shot attention). |
> **Despill is off by default** (all lanes, cpu-fast included). It pulls foreground
> chroma along the background-hue axis with no positional/semantic guard, so a subject
> sharing the background's hue (e.g. a blue suit on a blue backdrop) gets desaturated /
> hue-shifted (~ΔE 35). Re-enable per-config with `despill: {enabled: true}` only when
> edge-spill removal matters more than same-hue fidelity.
## 7. Run the service
```bash
@@ -308,13 +315,34 @@ curl -sS -F "file=@input.png" -F "screen_color=#CFEFFF" \
## 10. Exposing the service
The unit binds `127.0.0.1` — intended to be called by a co-located client (e.g. the
Genarrative Rust BFF via `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL`). The
service has **no authentication**. To reach it from other hosts:
Genarrative Rust BFF via `GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL`). To reach
it from other hosts:
- **Reverse proxy (recommended):** put nginx/caddy in front, terminate TLS, add
auth/rate-limiting, and forward to `127.0.0.1:18083`.
rate-limiting, and forward to `127.0.0.1:18083`.
- **Direct:** change `--host` to `0.0.0.0` and restrict source IPs with a firewall.
Do not expose it unauthenticated to the public internet.
Do not expose it to the public internet without authentication (below).
### Authentication
App-level token auth is **opt-in** via `BGFILTER_AUTH_TOKEN`:
- **Set it** → `/remove-background` requires header `X-Genarrative-Image-Token: <token>`
(constant-time compare); missing or wrong returns `401`. `/healthz` stays open. Use
this whenever the app is reachable directly — `--host 0.0.0.0`, or a cloud port
mapping with no proxy in front.
- **Leave it unset** → the app is **open** (fail-open) and logs a startup WARNING.
Correct only when a fronting proxy already authenticates — e.g. the production nginx
checks `X-Genarrative-Image-Token` itself, so the app behind it needs no token.
The header name matches the nginx layer, so a caller only swaps the base URL + token
value — no request-shape change:
```bash
curl -H "X-Genarrative-Image-Token: <token>" \
-F "file=@input.png" \
https://<host>/remove-background -o out.png
```
## 11. Capacity & performance
+25 -4
View File
@@ -188,6 +188,7 @@ export HF_HUB_DISABLE_XET=1 # 这些 repo 是 Xet 存储;强
| `BGFILTER_MAX_IMAGE_PIXELS` | `4194304` | 超过则返回 `413`(约 4 MP)|
| `BGFILTER_PRELOAD` | `1` | 启动时预加载默认模型(首个请求不用冷加载)|
| `BGFILTER_CROSS_CHECK` | 配置(`on`)| 强制开/关 cross-check 否决(`0` 关闭;需 `BiRefNet_HR-matting`)|
| `BGFILTER_AUTH_TOKEN` | — | 若设置,`/remove-background` 要求 header `X-Genarrative-Image-Token` 等于它(常量时间比较;否则 `401`)。不设 = **开放**(鉴权交给前置代理)。`/healthz` 始终开放。见 §10。 |
| `BGFILTER_WEIGHTS_DIR` | `models` | 本地权重文件夹的查找目录(方案 B)|
| `HF_HOME` | — | HF 缓存位置(方案 A)|
| `HF_HUB_OFFLINE` / `TRANSFORMERS_OFFLINE` | — | 权重缓存好后,生产设为 `1` |
@@ -216,6 +217,8 @@ export HF_HUB_DISABLE_XET=1 # 这些 repo 是 Xet 存储;强
| `model.precision` | `fp32` | `fp32` 或 `bf16`。bf16 **仅**在有原生内核的硬件上启用(CUDA,或带 AVX512-BF16/AMX 的 CPU);否则告警并回退 fp32。也可在 `segmentation:` / `cross_check:` 下按模型单独设。 |
| `model.attn_query_chunk` | `2048` | ViTMatte 全局注意力的 query 行分块。调小(如 `512`)以几个百分点的额外算力换掉 O(N²) 内存瞬时尖峰;输出逐比特相同。设 `0` 关闭分块(走原始一次性注意力)。 |
> **despill 默认关闭**(所有 lane,含 cpu-fast)。它沿背景色调方向压前景色度,没有位置/语义护栏,所以主体与背景**同色相**时(如蓝背景前的蓝西装)会被褪色/偏色(约 ΔE 35)。仅当"去边缘溢色"比"同色系保真"更重要时,才在配置里 `despill: {enabled: true}` 单独开启。
## 7. 运行服务
```bash
@@ -288,13 +291,31 @@ curl -sS -F "file=@input.png" -F "screen_color=#CFEFFF" \
## 10. 对外暴露
单元里绑的是 `127.0.0.1`——面向同机调用方(例如 Genarrative Rust BFF,通过
`GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL` 调用)。服务本身**没有鉴权**。
要从其它主机访问:
`GENARRATIVE_EDITOR_BACKGROUND_REMOVAL_BASE_URL` 调用)。要从其它主机访问:
- **反向代理(推荐):** 前面放 nginx/caddy,终止 TLS、加鉴权/限流,转发到
- **反向代理(推荐):** 前面放 nginx/caddy,终止 TLS、加限流,转发到
`127.0.0.1:18083`。
- **直接暴露:** 把 `--host` 改成 `0.0.0.0`,并用防火墙限制来源 IP。
切勿把无鉴权的服务裸暴露到公网。
切勿把无鉴权的服务裸暴露到公网(见下方鉴权)。
### 鉴权
app 层 token 鉴权是**可选开启**,由 `BGFILTER_AUTH_TOKEN` 控制:
- **设置它** → `/remove-background` 要求 header `X-Genarrative-Image-Token: <token>`
(常量时间比较);缺失或错误返回 `401`。`/healthz` 保持开放。**当 app 被直接暴露**
(`--host 0.0.0.0`、或云端端口映射无代理)时用这个。
- **不设置** → app **开放**(fail-open),并在启动时打一条 WARNING。仅当前置代理
已经鉴权时才可这样——例如生产机 nginx 自己校验 `X-Genarrative-Image-Token`,
其后的 app 就无需 token。
header 名和 nginx 层一致,所以调用方只换 base URL + token 值,请求结构不变:
```bash
curl -H "X-Genarrative-Image-Token: <token>" \
-F "file=@input.png" \
https://<host>/remove-background -o out.png
```
## 11. 容量与性能