BirkhoffLee commited on
Commit
8bff983
·
unverified ·
0 Parent(s):
Files changed (7) hide show
  1. .cnb.yml +46 -0
  2. .gitattributes +35 -0
  3. .gitignore +1 -0
  4. Caddyfile +15 -0
  5. Dockerfile +29 -0
  6. README.md +46 -0
  7. entrypoint.sh +66 -0
.cnb.yml ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ $:
3
+ vscode:
4
+ - runner:
5
+ cpus: 4
6
+ tags: cnb:arch:amd64
7
+ docker:
8
+ image: cnbcool/default-dev-env:latest
9
+ imports:
10
+ - https://cnb.cool/maikebuke/Tools/Huggingface/AccessToken/-/blob/main/key.yml
11
+ env:
12
+ HF_SPACE_URL: "https://huggingface.co/spaces/ServiceX/Sublink"
13
+ services:
14
+ - vscode
15
+ - docker
16
+ stages:
17
+ - name: vscode go
18
+ type: vscode:go
19
+
20
+ main:
21
+ push:
22
+ - runner:
23
+ cpus: 1
24
+ imports:
25
+ - https://cnb.cool/maikebuke/Tools/Huggingface/AccessToken/-/blob/main/key.yml
26
+ env:
27
+ HF_SPACE_URL: "https://huggingface.co/spaces/ServiceX/Sublink"
28
+ stages:
29
+ - name: Force Push To Huggingface Spaces
30
+ script: |
31
+ # 从 HF_SPACE_URL 提取 owner/repo 路径用于构造带认证的 git remote
32
+ HF_REPO_PATH=$(echo "$HF_SPACE_URL" | sed 's|https://huggingface.co/spaces/||')
33
+ HF_REMOTE="https://user:${HF_TOKEN_FULL}@huggingface.co/spaces/${HF_REPO_PATH}"
34
+
35
+ # 删除 CI 文件,避免推送到目标仓库
36
+ rm -f .cnb.yml
37
+
38
+ git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
39
+ git config user.name "github-actions[bot]"
40
+
41
+ # 将删除操作提交(基于当前 HEAD)
42
+ git add -A
43
+ git diff --cached --quiet || git commit -m "ci: remove CI config before sync"
44
+
45
+ # 强制推送到 Huggingface Space
46
+ git push "$HF_REMOTE" HEAD:main --force
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ uv.lock
Caddyfile ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :7860 {
2
+ # 健康检查不需要认证
3
+ @health path /healthz
4
+ handle @health {
5
+ respond "ok" 200
6
+ }
7
+
8
+ # 其他请求走基础认证后转发到 pdf2zh_next
9
+ handle {
10
+ basic_auth {
11
+ import /etc/caddy/users.auth
12
+ }
13
+ reverse_proxy 127.0.0.1:7861
14
+ }
15
+ }
Dockerfile ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.12-slim-bookworm
2
+
3
+ # 安装基础依赖
4
+ RUN apt-get update && apt-get install -y --no-install-recommends \
5
+ ca-certificates \
6
+ bash \
7
+ && rm -rf /var/lib/apt/lists/*
8
+
9
+ # 从官方镜像直接复制 caddy 和 uv 二进制
10
+ COPY --from=caddy:latest /usr/bin/caddy /usr/local/bin/caddy
11
+ COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
12
+
13
+ ENV PATH="/root/.local/bin:${PATH}" \
14
+ PYTHONDONTWRITEBYTECODE=1 \
15
+ PYTHONUNBUFFERED=1 \
16
+ GRADIO_SERVER_NAME=127.0.0.1 \
17
+ GRADIO_SERVER_PORT=7861
18
+
19
+ # 安装 pdf2zh-next
20
+ RUN uv tool install --python 3.12 pdf2zh-next
21
+
22
+ # 复制并启用配置
23
+ COPY Caddyfile /etc/caddy/Caddyfile
24
+ COPY entrypoint.sh /entrypoint.sh
25
+ RUN chmod +x /entrypoint.sh
26
+
27
+ EXPOSE 7860
28
+
29
+ CMD ["/entrypoint.sh"]
README.md ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: PDFMathTranslate Next
3
+ emoji: 📄
4
+ colorFrom: blue
5
+ colorTo: green
6
+ sdk: docker
7
+ pinned: false
8
+ ---
9
+
10
+ ## PDFMathTranslate-next on HuggingFace Spaces
11
+
12
+ 这个仓库用于部署 `pdf2zh_next --gui`,并通过 Caddy BasicAuth 做访问门控。
13
+
14
+ ### 运行架构
15
+
16
+ 1. `pdf2zh_next --gui` 在容器内监听 `127.0.0.1:7861`
17
+ 2. Caddy 监听外部端口 `7860`
18
+ 3. 除 `/healthz` 外,所有请求都需要 BasicAuth
19
+ 4. 认证通过后,Caddy 反向代理到 `pdf2zh_next`
20
+
21
+ ### 必需 Secret
22
+
23
+ 在 HuggingFace Space 设置 `BASIC_AUTH_USERS`(多行文本):
24
+
25
+ ```text
26
+ alice:your_password_1
27
+ bob:your_password_2
28
+ ```
29
+
30
+ 规则:
31
+ - 每行一个账号,格式 `username:password`
32
+ - 空行和 `#` 开头行会被忽略
33
+ - 容器启动时会把明文密码转换为 bcrypt 哈希,仓库不保存真实密码
34
+
35
+ ### 健康检查
36
+
37
+ `/healthz` 无需认证,返回 `200 ok`。
38
+
39
+ ### 本地构建示例
40
+
41
+ ```bash
42
+ docker build -t pdf2zh-gated .
43
+ docker run --rm -p 7860:7860 \
44
+ -e BASIC_AUTH_USERS=$'alice:pass1\nbob:pass2' \
45
+ pdf2zh-gated
46
+ ```
entrypoint.sh ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # 解析 HF Secret,支持多行或 \n 形式
5
+ RAW_USERS="${BASIC_AUTH_USERS:-}"
6
+ if [[ -z "${RAW_USERS}" ]]; then
7
+ echo "[ERROR] BASIC_AUTH_USERS is required. Use one 'username:password' per line." >&2
8
+ exit 1
9
+ fi
10
+ RAW_USERS="${RAW_USERS//\\n/$'\n'}"
11
+
12
+ AUTH_FILE="/etc/caddy/users.auth"
13
+ > "${AUTH_FILE}"
14
+ chmod 600 "${AUTH_FILE}"
15
+
16
+ # 逐行生成 caddy 可用的哈希密码
17
+ while IFS= read -r line || [[ -n "${line}" ]]; do
18
+ line="${line%$'\r'}"
19
+ [[ -z "${line}" ]] && continue
20
+ [[ "${line}" == \#* ]] && continue
21
+
22
+ if [[ "${line}" != *:* ]]; then
23
+ echo "[ERROR] Invalid BASIC_AUTH_USERS line: '${line}'" >&2
24
+ exit 1
25
+ fi
26
+
27
+ user="${line%%:*}"
28
+ pass="${line#*:}"
29
+ if [[ -z "${user}" || -z "${pass}" ]]; then
30
+ echo "[ERROR] Empty username or password is not allowed: '${line}'" >&2
31
+ exit 1
32
+ fi
33
+
34
+ hash="$(caddy hash-password --plaintext "${pass}")"
35
+ printf "%s %s\n" "${user}" "${hash}" >> "${AUTH_FILE}"
36
+ done <<< "${RAW_USERS}"
37
+
38
+ if [[ ! -s "${AUTH_FILE}" ]]; then
39
+ echo "[ERROR] No valid user entries found in BASIC_AUTH_USERS." >&2
40
+ exit 1
41
+ fi
42
+
43
+ # 固定内部监听,确保只能经由 caddy 访问
44
+ export GRADIO_SERVER_NAME="${GRADIO_SERVER_NAME:-127.0.0.1}"
45
+ export GRADIO_SERVER_PORT="${GRADIO_SERVER_PORT:-7861}"
46
+
47
+ echo "[INFO] Starting pdf2zh_next on ${GRADIO_SERVER_NAME}:${GRADIO_SERVER_PORT}"
48
+ pdf2zh_next --gui &
49
+ PDF_PID=$!
50
+
51
+ echo "[INFO] Starting caddy on :7860"
52
+ caddy run --config /etc/caddy/Caddyfile &
53
+ CADDY_PID=$!
54
+
55
+ cleanup() {
56
+ kill "${PDF_PID}" "${CADDY_PID}" 2>/dev/null || true
57
+ }
58
+ trap cleanup INT TERM EXIT
59
+
60
+ # 任一进程退出都结束容器
61
+ set +e
62
+ wait -n "${PDF_PID}" "${CADDY_PID}"
63
+ EXIT_CODE=$?
64
+ set -e
65
+ echo "[ERROR] A service exited unexpectedly. Shutting down."
66
+ exit "${EXIT_CODE}"