github-actions[bot] commited on
Commit
34d56f8
·
0 Parent(s):

Deploy HF adapter from 81228e7b28a9d511f79b2f59b1c00ef60bcc9374

Browse files
Files changed (4) hide show
  1. .env.example +17 -0
  2. Dockerfile +70 -0
  3. README.md +59 -0
  4. start.sh +101 -0
.env.example ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Space runtime example for official Go Grok2API
2
+ #
3
+ # 用法:
4
+ # 1. 写入 HF Storage:/data/config.yaml(推荐)
5
+ # 2. 或用下面环境变量在首次启动时注入密钥
6
+ # 3. 不要把真实密钥提交到 Git
7
+
8
+ DATA_DIR=/data
9
+ SERVER_PORT=7860
10
+ GROK2API_CONFIG_SOURCE=/data/config.yaml
11
+
12
+ # 首次 seed 配置时可选注入(之后以 /data/config.yaml 为准)
13
+ # GROK2API_JWT_SECRET= # openssl rand -hex 32
14
+ # GROK2API_CREDENTIAL_ENCRYPTION_KEY= # openssl rand -base64 32
15
+ # GROK2API_ADMIN_USERNAME=admin
16
+ # GROK2API_ADMIN_PASSWORD=replace_me
17
+ # GROK2API_SECURE_COOKIES=true
Dockerfile ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Hugging Face Space adapter for official chenyme/grok2api (Go + React rewrite).
2
+ # Build always clones upstream; this Space repo only ships the adapter layer.
3
+
4
+ ARG NODE_VERSION=22
5
+ ARG GO_VERSION=1.26
6
+ ARG ALPINE_VERSION=3.23
7
+ ARG GROK2API_REPO=https://github.com/chenyme/grok2api.git
8
+ ARG GROK2API_REF=main
9
+
10
+ FROM alpine:${ALPINE_VERSION} AS src
11
+ ARG GROK2API_REPO
12
+ ARG GROK2API_REF
13
+ RUN apk add --no-cache git ca-certificates \
14
+ && git clone --depth 1 --branch "${GROK2API_REF}" "${GROK2API_REPO}" /src \
15
+ && test -f /src/backend/go.mod \
16
+ && test -f /src/frontend/package.json \
17
+ && test -f /src/config.example.yaml \
18
+ && test -f /src/docker/entrypoint.sh
19
+
20
+ FROM --platform=$BUILDPLATFORM node:${NODE_VERSION}-alpine AS frontend-builder
21
+ WORKDIR /src/frontend
22
+ RUN corepack enable
23
+ COPY --from=src /src/frontend/package.json /src/frontend/pnpm-lock.yaml ./
24
+ RUN pnpm config set store-dir /pnpm/store \
25
+ && pnpm fetch --frozen-lockfile \
26
+ && pnpm install --offline --frozen-lockfile
27
+ COPY --from=src /src/frontend/index.html /src/frontend/vite.config.ts /src/frontend/tsconfig.json /src/frontend/tsconfig.app.json /src/frontend/tsconfig.node.json ./
28
+ COPY --from=src /src/frontend/public ./public
29
+ COPY --from=src /src/frontend/src ./src
30
+ RUN pnpm build
31
+
32
+ FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine AS backend-builder
33
+ ARG TARGETOS
34
+ ARG TARGETARCH
35
+ WORKDIR /src/backend
36
+ RUN apk add --no-cache ca-certificates git
37
+ COPY --from=src /src/backend/go.mod /src/backend/go.sum ./
38
+ RUN go mod download
39
+ COPY --from=src /src/backend/cmd ./cmd
40
+ COPY --from=src /src/backend/internal ./internal
41
+ COPY --from=src /src/backend/docs/docs.go ./docs/docs.go
42
+ RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH:-amd64} \
43
+ go build -buildvcs=false -trimpath -ldflags="-s -w" -o /out/grok2api ./cmd/grok2api
44
+
45
+ FROM alpine:${ALPINE_VERSION}
46
+
47
+ ENV TZ=Asia/Shanghai \
48
+ GROK2API_CONFIG_SOURCE=/data/config.yaml \
49
+ SERVER_PORT=7860
50
+
51
+ RUN apk add --no-cache ca-certificates su-exec tzdata wget \
52
+ && addgroup -S -g 10001 grok2api \
53
+ && adduser -S -D -H -u 10001 -G grok2api grok2api \
54
+ && mkdir -p /app/data /app/frontend/dist /data /data/media /run/grok2api \
55
+ && chown -R grok2api:grok2api /app/data /data /run/grok2api
56
+
57
+ WORKDIR /app
58
+
59
+ COPY --from=backend-builder --chmod=0755 /out/grok2api /app/grok2api
60
+ COPY --from=frontend-builder /src/frontend/dist /app/frontend/dist
61
+ COPY --from=src /src/config.example.yaml /app/config.example.yaml
62
+ COPY --chmod=0755 start.sh /usr/local/bin/hf-start.sh
63
+
64
+ EXPOSE 7860
65
+
66
+ HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
67
+ CMD wget -qO- "http://127.0.0.1:${SERVER_PORT}/healthz" >/dev/null || exit 1
68
+
69
+ ENTRYPOINT ["/usr/local/bin/hf-start.sh"]
70
+ CMD ["/app/grok2api", "--config", "/app/config.yaml", "--listen", "0.0.0.0:7860"]
README.md ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Grok2Api
3
+ emoji: 🚀
4
+ colorFrom: indigo
5
+ colorTo: blue
6
+ sdk: docker
7
+ app_port: 7860
8
+ pinned: false
9
+ ---
10
+
11
+ # Grok2Api on Hugging Face Spaces
12
+
13
+ Runs the official [chenyme/grok2api](https://github.com/chenyme/grok2api) **Go + React** gateway.
14
+
15
+ ## Build model
16
+
17
+ - This Space repository only contains the HF adapter (`Dockerfile`, `start.sh`, this README, `.env.example`)
18
+ - Docker build **clones upstream** `https://github.com/chenyme/grok2api` (`main`) and builds frontend + backend from that source
19
+ - Local Python-era fork code is **not** used
20
+
21
+ ## Persistent storage
22
+
23
+ Mount HF Storage (e.g. `DanielleNguyen/Grok2Api-storage`) to **`/data`**.
24
+
25
+ | Path | Purpose |
26
+ | --- | --- |
27
+ | `/data/config.yaml` | Runtime config (seeded from upstream `config.example.yaml` on first boot) |
28
+ | `/data/backend.db` | SQLite database |
29
+ | `/data/media` | Local media files |
30
+ | `/data/.env` | Optional env file loaded at start |
31
+
32
+ ## First boot secrets
33
+
34
+ Edit `/data/config.yaml` (or set env vars **before** first seed):
35
+
36
+ | Field / env | Notes |
37
+ | --- | --- |
38
+ | `secrets.jwtSecret` / `GROK2API_JWT_SECRET` | `openssl rand -hex 32` |
39
+ | `secrets.credentialEncryptionKey` / `GROK2API_CREDENTIAL_ENCRYPTION_KEY` | `openssl rand -base64 32` (keep forever) |
40
+ | `bootstrapAdmin.password` / `GROK2API_ADMIN_PASSWORD` | Strong admin password |
41
+ | `auth.secureCookies` / `GROK2API_SECURE_COOKIES` | Prefer `true` on HTTPS Space |
42
+
43
+ Service refuses insecure defaults if secrets are not replaced.
44
+
45
+ ## Service
46
+
47
+ - Port: `7860` (Spaces requirement)
48
+ - Health: `/healthz`
49
+ - Admin UI: `/` (same origin as API)
50
+ - API: `/v1/*` with `Authorization: Bearer g2a_...`
51
+
52
+ ## Deploy from GitHub
53
+
54
+ Workflow `.github/workflows/deploy-hf.yml` syncs only `huggingface/*` to this Space.
55
+
56
+ GitHub secrets:
57
+
58
+ - `HF_TOKEN`
59
+ - `HF_SPACE_ID` (e.g. `DanielleNguyen/Grok2Api`)
start.sh ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/sh
2
+ set -eu
3
+
4
+ umask 077
5
+
6
+ DATA_DIR="${DATA_DIR:-/data}"
7
+ CONFIG_SOURCE="${GROK2API_CONFIG_SOURCE:-$DATA_DIR/config.yaml}"
8
+ EXAMPLE_CONFIG="/app/config.example.yaml"
9
+ APP_CONFIG="/app/config.yaml"
10
+ LISTEN_ADDR="0.0.0.0:${SERVER_PORT:-7860}"
11
+
12
+ mkdir -p "$DATA_DIR" "$DATA_DIR/media" /run/grok2api
13
+
14
+ # Load optional env file first so secrets are available for seed/override.
15
+ if [ -f "$DATA_DIR/.env" ]; then
16
+ set -a
17
+ # shellcheck disable=SC1090
18
+ . "$DATA_DIR/.env"
19
+ set +a
20
+ fi
21
+
22
+ apply_secret_overrides() {
23
+ target="$1"
24
+ [ -f "$target" ] || return 0
25
+
26
+ if [ -n "${GROK2API_JWT_SECRET:-}" ]; then
27
+ sed -i "s|jwtSecret: \".*\"|jwtSecret: \"${GROK2API_JWT_SECRET}\"|" "$target"
28
+ fi
29
+ if [ -n "${GROK2API_CREDENTIAL_ENCRYPTION_KEY:-}" ]; then
30
+ sed -i "s|credentialEncryptionKey: \".*\"|credentialEncryptionKey: \"${GROK2API_CREDENTIAL_ENCRYPTION_KEY}\"|" "$target"
31
+ fi
32
+ if [ -n "${GROK2API_ADMIN_USERNAME:-}" ]; then
33
+ sed -i "s|username: \".*\"|username: \"${GROK2API_ADMIN_USERNAME}\"|" "$target"
34
+ fi
35
+ if [ -n "${GROK2API_ADMIN_PASSWORD:-}" ]; then
36
+ sed -i "s|password: \".*\"|password: \"${GROK2API_ADMIN_PASSWORD}\"|" "$target"
37
+ fi
38
+ if [ -n "${GROK2API_SECURE_COOKIES:-}" ]; then
39
+ sed -i "s|secureCookies: .*|secureCookies: ${GROK2API_SECURE_COOKIES}|" "$target"
40
+ fi
41
+ }
42
+
43
+ seed_config() {
44
+ cp "$EXAMPLE_CONFIG" "$CONFIG_SOURCE"
45
+
46
+ sed -i \
47
+ -e 's|listen: "127.0.0.1:8000"|listen: "0.0.0.0:7860"|' \
48
+ -e 's|staticPath: "./frontend/dist"|staticPath: "/app/frontend/dist"|' \
49
+ -e 's|path: "./data/backend.db"|path: "'"$DATA_DIR"'/backend.db"|' \
50
+ -e 's|path: "./data/media"|path: "'"$DATA_DIR"'/media"|' \
51
+ "$CONFIG_SOURCE"
52
+
53
+ apply_secret_overrides "$CONFIG_SOURCE"
54
+ echo "Initialized HF runtime config at $CONFIG_SOURCE"
55
+ }
56
+
57
+ if [ ! -f "$CONFIG_SOURCE" ]; then
58
+ if [ ! -f "$EXAMPLE_CONFIG" ]; then
59
+ echo "missing example config: $EXAMPLE_CONFIG" >&2
60
+ exit 1
61
+ fi
62
+ seed_config
63
+ else
64
+ # Re-apply Space secrets every boot so placeholder configs can be fixed without rebuild.
65
+ apply_secret_overrides "$CONFIG_SOURCE"
66
+ fi
67
+
68
+ # Fail fast with clear guidance if placeholders remain.
69
+ if grep -q 'replace-with-at-least-32-characters' "$CONFIG_SOURCE" \
70
+ || grep -q 'replace-with-base64-key' "$CONFIG_SOURCE" \
71
+ || grep -q 'replace-with-a-strong-password' "$CONFIG_SOURCE"; then
72
+ cat >&2 <<'EOF'
73
+ ERROR: /data/config.yaml still contains example secrets.
74
+
75
+ Fix one of:
76
+ 1) Edit HF Storage file: /data/config.yaml
77
+ - secrets.jwtSecret
78
+ - secrets.credentialEncryptionKey
79
+ - bootstrapAdmin.password
80
+ 2) Or set Space Secrets, then restart:
81
+ - GROK2API_JWT_SECRET (openssl rand -hex 32)
82
+ - GROK2API_CREDENTIAL_ENCRYPTION_KEY (openssl rand -base64 32)
83
+ - GROK2API_ADMIN_PASSWORD
84
+ EOF
85
+ exit 1
86
+ fi
87
+
88
+ cp "$CONFIG_SOURCE" "$APP_CONFIG"
89
+ chown grok2api:grok2api "$APP_CONFIG" 2>/dev/null || true
90
+ chmod 0600 "$APP_CONFIG" || true
91
+ chown -R grok2api:grok2api "$DATA_DIR" 2>/dev/null || true
92
+
93
+ if ! printf '%s' "$*" | grep -q -- '--listen'; then
94
+ set -- "$@" --listen "$LISTEN_ADDR"
95
+ fi
96
+
97
+ if command -v su-exec >/dev/null 2>&1 && id grok2api >/dev/null 2>&1; then
98
+ exec su-exec grok2api:grok2api "$@"
99
+ fi
100
+
101
+ exec "$@"