Spaces:
Runtime error
Runtime error
akashyadav758 Claude Opus 4.8 (1M context) commited on
Commit Β·
8ea09fa
1
Parent(s): 4a66c44
Add HOWTOUSE.md and docs/ for fast, error-free new setup
Browse filesHOWTOUSE.md: per-service API endpoints + correct payloads + curl examples (key as
placeholder, never the real value). docs/: architecture, persistence, api-gateway,
deployment, troubleshooting β documents everything added on top of the base image so a
fresh HF or Docker deploy doesn't hit the errors we already solved.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- HOWTOUSE.md +93 -0
- docs/README.md +24 -0
- docs/api-gateway.md +37 -0
- docs/architecture.md +44 -0
- docs/deployment.md +46 -0
- docs/persistence.md +37 -0
- docs/troubleshooting.md +41 -0
HOWTOUSE.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# How to use the API
|
| 2 |
+
|
| 3 |
+
One base URL fronts all three services. Every `/gpt`, `/gemini`, `/flow` call needs the
|
| 4 |
+
`API_KEY` as a Bearer token. The monitor UI (`/`) needs no key.
|
| 5 |
+
|
| 6 |
+
- **Base URL:** `https://akash1313-selfapi.hf.space`
|
| 7 |
+
- **Auth header:** `Authorization: Bearer YOUR_API_KEY` *(your real key is in the gitignored `./api-key`)*
|
| 8 |
+
|
| 9 |
+
> β οΈ **You must be logged in** to ChatGPT / Gemini / Flow inside the browser
|
| 10 |
+
> (`https://akash1313-selfapi.hf.space/`) for real responses. The servers reply even when
|
| 11 |
+
> logged out, but with `extensionConnected:false` / empty data. Check first:
|
| 12 |
+
> ```bash
|
| 13 |
+
> curl -H "Authorization: Bearer YOUR_API_KEY" https://akash1313-selfapi.hf.space/gpt/health
|
| 14 |
+
> ```
|
| 15 |
+
> `extensionConnected:true` = ready.
|
| 16 |
+
|
| 17 |
+
---
|
| 18 |
+
|
| 19 |
+
## ChatGPT β `/gpt`
|
| 20 |
+
|
| 21 |
+
| Endpoint | Method | Body |
|
| 22 |
+
|----------|--------|------|
|
| 23 |
+
| `/gpt/health` | GET | β |
|
| 24 |
+
| `/gpt/api/chat` | POST | `{"prompt": "...", "wait_for_response": true}` |
|
| 25 |
+
| `/gpt/api/chat/bulk` | POST | `{"prompts": ["...","..."], "delay_seconds": 2}` |
|
| 26 |
+
| `/gpt/v1/chat/completions` | POST | OpenAI-compatible (see below) |
|
| 27 |
+
|
| 28 |
+
```bash
|
| 29 |
+
# Simple chat
|
| 30 |
+
curl -X POST https://akash1313-selfapi.hf.space/gpt/api/chat \
|
| 31 |
+
-H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
|
| 32 |
+
-d '{"prompt":"Write a haiku about the sea","wait_for_response":true}'
|
| 33 |
+
|
| 34 |
+
# OpenAI-compatible (drop-in for OpenAI SDKs β set base_url=.../gpt/v1)
|
| 35 |
+
curl -X POST https://akash1313-selfapi.hf.space/gpt/v1/chat/completions \
|
| 36 |
+
-H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
|
| 37 |
+
-d '{"model":"gpt-5","messages":[{"role":"user","content":"hello"}],"stream":false}'
|
| 38 |
+
```
|
| 39 |
+
Optional fields: `"model"`, `"thinking_effort"`, `"conversation_id"` (continue a thread).
|
| 40 |
+
|
| 41 |
+
---
|
| 42 |
+
|
| 43 |
+
## Gemini β `/gemini` (form-encoded, not JSON)
|
| 44 |
+
|
| 45 |
+
| Endpoint | Method | Body |
|
| 46 |
+
|----------|--------|------|
|
| 47 |
+
| `/gemini/status` | GET | β |
|
| 48 |
+
| `/gemini/chat` | POST (form) | `prompt`, `user_id`, `new_chat`, `stream` |
|
| 49 |
+
| `/gemini/music` | POST (form) | `prompt` |
|
| 50 |
+
| `/gemini/reset` | POST | β |
|
| 51 |
+
| `/gemini/output/<file>` | GET | β (generated media) |
|
| 52 |
+
|
| 53 |
+
```bash
|
| 54 |
+
curl -X POST https://akash1313-selfapi.hf.space/gemini/chat \
|
| 55 |
+
-H "Authorization: Bearer YOUR_API_KEY" \
|
| 56 |
+
-d "prompt=Explain quantum entanglement simply&new_chat=true"
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
---
|
| 60 |
+
|
| 61 |
+
## Flow (video / image) β `/flow` (JSON)
|
| 62 |
+
|
| 63 |
+
| Endpoint | Method | Body |
|
| 64 |
+
|----------|--------|------|
|
| 65 |
+
| `/flow/health` | GET | β |
|
| 66 |
+
| `/flow/generate/video` | POST | `{"prompt":"...","aspect":"portrait","duration":10,"count":1}` |
|
| 67 |
+
| `/flow/generate/image` | POST | `{"prompt":"...","aspect":"portrait","count":1}` |
|
| 68 |
+
| `/flow/upload/image` Β· `/flow/upload/video` | POST | multipart file |
|
| 69 |
+
| `/flow/download/<filename>` | GET | β |
|
| 70 |
+
|
| 71 |
+
```bash
|
| 72 |
+
# Text-to-video (aspect: portrait|landscape ; duration: 4,6,8,10)
|
| 73 |
+
curl -X POST https://akash1313-selfapi.hf.space/flow/generate/video \
|
| 74 |
+
-H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
|
| 75 |
+
-d '{"prompt":"a cat surfing a wave, cinematic","aspect":"landscape","duration":8}'
|
| 76 |
+
|
| 77 |
+
# Text-to-image
|
| 78 |
+
curl -X POST https://akash1313-selfapi.hf.space/flow/generate/image \
|
| 79 |
+
-H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
|
| 80 |
+
-d '{"prompt":"neon city at night","aspect":"square"}'
|
| 81 |
+
```
|
| 82 |
+
|
| 83 |
+
---
|
| 84 |
+
|
| 85 |
+
## Auth errors
|
| 86 |
+
|
| 87 |
+
| Code | Meaning |
|
| 88 |
+
|------|---------|
|
| 89 |
+
| `401` | Missing/wrong key |
|
| 90 |
+
| `503` | `API_KEY` not set on the server (gateway disabled, fail-closed) |
|
| 91 |
+
| `502` | Backend server not reachable (still booting / crashed β check `/chrome.log`) |
|
| 92 |
+
|
| 93 |
+
Rotate the key anytime: change the `API_KEY` secret in the Space settings (auto-restarts).
|
docs/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# docs/ β what's new & how to set it up fast
|
| 2 |
+
|
| 3 |
+
Reference for everything added on top of the base Chrome Space, so a fresh deploy (HF **or**
|
| 4 |
+
Docker) goes quick and error-free. Read in order:
|
| 5 |
+
|
| 6 |
+
| File | Covers |
|
| 7 |
+
|------|--------|
|
| 8 |
+
| [architecture.md](architecture.md) | One container: Chrome + extensions + monitor/gateway + 3 servers. Ports. |
|
| 9 |
+
| [persistence.md](persistence.md) | Staying logged in: Neon Postgres (HF) vs Docker volume (self-host). |
|
| 10 |
+
| [api-gateway.md](api-gateway.md) | The single gateway, `/gpt /gemini /flow` routing, `API_KEY` auth. |
|
| 11 |
+
| [deployment.md](deployment.md) | Deploy steps, required secrets, HF tokens, Docker build stages. |
|
| 12 |
+
| [troubleshooting.md](troubleshooting.md) | Every error we hit and its fix. **Check here first.** |
|
| 13 |
+
|
| 14 |
+
For **calling** the API see [`../HOWTOUSE.md`](../HOWTOUSE.md). For a quick start see
|
| 15 |
+
[`../SETUP.md`](../SETUP.md).
|
| 16 |
+
|
| 17 |
+
## Required secrets (set these or things silently break)
|
| 18 |
+
|
| 19 |
+
| Secret | Where | Without it |
|
| 20 |
+
|--------|-------|-----------|
|
| 21 |
+
| `DATABASE_URL` | HF only (Neon Postgres) | Logins lost on every restart |
|
| 22 |
+
| `API_KEY` | HF + Docker `.env` | All `/gpt /gemini /flow` return `503` |
|
| 23 |
+
|
| 24 |
+
Local credential notes live in gitignored files: `hf-token`, `neon-db`, `api-key`.
|
docs/api-gateway.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# API gateway
|
| 2 |
+
|
| 3 |
+
The `monitor` Go binary (port 3001) is also a reverse-proxy gateway. HF exposes only one public
|
| 4 |
+
port, so all three backend APIs are reached under one base URL by path prefix.
|
| 5 |
+
|
| 6 |
+
## Routing (`monitor/main.go`)
|
| 7 |
+
|
| 8 |
+
| Public prefix | β forwards to | Prefix stripped |
|
| 9 |
+
|---------------|---------------|-----------------|
|
| 10 |
+
| `/gpt/β¦` | `127.0.0.1:9225` | `/gpt/api/chat` β `/api/chat` |
|
| 11 |
+
| `/gemini/β¦` | `127.0.0.1:8000` | `/gemini/chat` β `/chat` |
|
| 12 |
+
| `/flow/β¦` | `127.0.0.1:8101` | `/flow/generate/video` β `/generate/video` |
|
| 13 |
+
|
| 14 |
+
`gatewayHandler(prefix, target)` builds one `httputil.ReverseProxy` whose `Director` rewrites the
|
| 15 |
+
host and strips the prefix. The monitor's own routes (`/`, `/api/*`, `/chrome.log`) are untouched.
|
| 16 |
+
|
| 17 |
+
## Auth β `API_KEY` (fail-closed)
|
| 18 |
+
|
| 19 |
+
`authOK()` gates the three prefixes:
|
| 20 |
+
- Reads `API_KEY` from env once at startup.
|
| 21 |
+
- Requires `Authorization: Bearer <API_KEY>` (also accepts `?key=`).
|
| 22 |
+
- **Unset `API_KEY` β every gateway call returns `503`** (so accounts are never accidentally open).
|
| 23 |
+
- Wrong/missing key β `401`.
|
| 24 |
+
- The monitor UI stays open (no key) so the live view keeps working.
|
| 25 |
+
|
| 26 |
+
Set it: HF secret `API_KEY` (Settings) or Docker `.env` `API_KEY=β¦`. Use a long random string,
|
| 27 |
+
e.g. `openssl rand -hex 24`.
|
| 28 |
+
|
| 29 |
+
## Why not a separate Space for the servers?
|
| 30 |
+
The extensions dial `ws://127.0.0.1:9225/9226/9227` β hardcoded localhost
|
| 31 |
+
(`*/background.js`). A second Space is a different machine with a different `127.0.0.1`, so its
|
| 32 |
+
servers could never receive the extension connections. Hence: one container, gateway out front.
|
| 33 |
+
|
| 34 |
+
## Adding a new route
|
| 35 |
+
1. Server listens on a new localhost port inside the container.
|
| 36 |
+
2. Launch it in `start_hf.sh` (step 6a).
|
| 37 |
+
3. Add `http.HandleFunc("/x/", gatewayHandler("/x", "http://127.0.0.1:PORT"))` in `monitor/main.go`.
|
docs/architecture.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Architecture β one container, everything inside
|
| 2 |
+
|
| 3 |
+
Everything runs in **one container** built from the root `Dockerfile`. The extensions inside
|
| 4 |
+
Chrome dial their servers on hardcoded `127.0.0.1` ports, so the servers **must** share Chrome's
|
| 5 |
+
localhost β a separate machine/Space can never reach them. That's why there's a single image, not
|
| 6 |
+
microservices.
|
| 7 |
+
|
| 8 |
+
```
|
| 9 |
+
https://β¦hf.space (only port 3001 is public)
|
| 10 |
+
β
|
| 11 |
+
ββββββββββΌββββββββββ
|
| 12 |
+
β monitor :3001 β UI + API gateway (one Go binary)
|
| 13 |
+
β / /chrome.log β (open, no key)
|
| 14 |
+
β /gpt /gemini /flowβ (API-key gated β localhost)
|
| 15 |
+
ββββ¬βββββββ¬βββββββ¬βββ
|
| 16 |
+
9225 ββββ 8000β ββββ 8101
|
| 17 |
+
(chatgpt) (gemini) (flow)
|
| 18 |
+
β β β
|
| 19 |
+
ws 9225 ws 9226 ws 9227 βββ extensions dial in (localhost)
|
| 20 |
+
βββββββββ Chrome (headless) + 3 unpacked extensions βββββββββ
|
| 21 |
+
CDP 9222 Β· socat proxy 9223 Β· profile in /home/chrome/data
|
| 22 |
+
```
|
| 23 |
+
|
| 24 |
+
## Port map (all on the container's 127.0.0.1)
|
| 25 |
+
|
| 26 |
+
| Port | Who | Purpose |
|
| 27 |
+
|------|-----|---------|
|
| 28 |
+
| 3001 | monitor | UI + API gateway (**only published port**) |
|
| 29 |
+
| 9222 | Chrome | DevTools Protocol (CDP) |
|
| 30 |
+
| 9223 | socat | CDP proxied for external tools |
|
| 31 |
+
| 9225 | chatgpt server | HTTP API **and** extension WS (same port) |
|
| 32 |
+
| 8000 / 9226 | gemini server | HTTP API / extension cookie-WS |
|
| 33 |
+
| 8101 / 8100 / 9227 | flow server | HTTP API / ext-callback / extension WS |
|
| 34 |
+
|
| 35 |
+
## What starts it
|
| 36 |
+
`start_hf.sh` (the container entrypoint) in order: restore profile from Postgres β clean profile β
|
| 37 |
+
start monitor (3001) β CDP proxy β **start the 3 backend servers** (step 6a) β launch Chrome with
|
| 38 |
+
the 3 extensions. Each server logs to `/home/chrome/{chatgpt,gemini,flow}.log`.
|
| 39 |
+
|
| 40 |
+
## Components added on top of the base image
|
| 41 |
+
- `monitor/` β Go UI, now also the **reverse-proxy gateway** (`gatewayHandler`, `authOK`).
|
| 42 |
+
- `profilesync/` β Go tool, Chrome profile β Postgres snapshot.
|
| 43 |
+
- `chatgpt-free-api/`, `free-gemini-api/` (Go) + `flow-agent/` (Python/FastAPI) β the 3 servers,
|
| 44 |
+
built/installed into the image by the `Dockerfile`.
|
docs/deployment.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deployment
|
| 2 |
+
|
| 3 |
+
## Hugging Face (this repo == the Space)
|
| 4 |
+
|
| 5 |
+
1. **Push** to `main` β HF auto-rebuilds:
|
| 6 |
+
```bash
|
| 7 |
+
git push origin main
|
| 8 |
+
```
|
| 9 |
+
2. **Set secrets** once (Settings β Variables and secrets):
|
| 10 |
+
- `DATABASE_URL` β Neon Postgres (persistence). See [persistence.md](persistence.md).
|
| 11 |
+
- `API_KEY` β gateway auth. See [api-gateway.md](api-gateway.md).
|
| 12 |
+
3. After build β **log in** to ChatGPT/Gemini/Flow in the monitor UI once.
|
| 13 |
+
|
| 14 |
+
### HF git auth (important)
|
| 15 |
+
The `origin` remote embeds a token: `https://<user>:<hf_token>@huggingface.co/spaces/<user>/<space>`.
|
| 16 |
+
- The token **must belong to the Space owner** (`akash1313`) with `repo.write`. A token from a
|
| 17 |
+
different account β `pre-receive hook declined: You are not authorized to push`.
|
| 18 |
+
- Rotate/replace the token in the URL with:
|
| 19 |
+
`git remote set-url origin https://akash1313:<NEW_TOKEN>@huggingface.co/spaces/akash1313/selfapi`
|
| 20 |
+
- Local token files (`hf-token`, `neon-db`, `api-key`) are gitignored β never commit them.
|
| 21 |
+
|
| 22 |
+
### Watch the build
|
| 23 |
+
```bash
|
| 24 |
+
curl -s -H "Authorization: Bearer <hf_token>" \
|
| 25 |
+
https://huggingface.co/api/spaces/akash1313/selfapi/runtime
|
| 26 |
+
# stage: RUNNING_BUILDING β RUNNING_APP_STARTING β RUNNING (errors: BUILD_ERROR / RUNTIME_ERROR)
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
## Self-host Docker
|
| 30 |
+
```bash
|
| 31 |
+
echo "API_KEY=$(openssl rand -hex 24)" > .env # gateway auth (DATABASE_URL not needed)
|
| 32 |
+
docker compose up --build -d
|
| 33 |
+
```
|
| 34 |
+
Only the `chrome` service exists β it bakes in all 3 servers. Open `http://localhost:3001`.
|
| 35 |
+
|
| 36 |
+
## Dockerfile build stages (what gets built)
|
| 37 |
+
| Stage | Image | Output |
|
| 38 |
+
|-------|-------|--------|
|
| 39 |
+
| `monitor-build` | golang:1.22 | `/monitor` (UI + gateway) |
|
| 40 |
+
| `profilesync-build` | golang:1.22 | `/profilesync` |
|
| 41 |
+
| `chatgpt-build` | golang:1.26 | `/agent` (+ `config.json`) |
|
| 42 |
+
| `gemini-build` | golang:1.26 | `/free-gemini-api` |
|
| 43 |
+
| final (on `akashyadav758/chrome`) | β | copies binaries, `pip install` flow deps, installs Chrome-for-Testing, perms |
|
| 44 |
+
|
| 45 |
+
> If you bump a server's `go.mod` Go version, bump its build-stage image too, or the build pulls a
|
| 46 |
+
> toolchain at build time.
|
docs/persistence.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Persistence β staying logged in
|
| 2 |
+
|
| 3 |
+
The Chrome profile (cookies/logins) lives in `/home/chrome/data`. How it survives a restart
|
| 4 |
+
depends on where you run.
|
| 5 |
+
|
| 6 |
+
## Hugging Face β Neon Postgres (required)
|
| 7 |
+
|
| 8 |
+
HF free `cpu-basic` Spaces have **no persistent disk** β the filesystem is wiped on every
|
| 9 |
+
restart/rebuild. So the profile is snapshotted to an external Postgres DB by the `profilesync` tool:
|
| 10 |
+
|
| 11 |
+
- **Boot:** `profilesync restore` pulls the last snapshot.
|
| 12 |
+
- **Every 5 min + on shutdown:** `profilesync backup` saves it.
|
| 13 |
+
- Stored as one row: `chrome_profile(id, updated_at, data bytea)` (auto-created).
|
| 14 |
+
- **Gated on `DATABASE_URL`.** Not set β restore/backup skipped β logins lost on restart.
|
| 15 |
+
|
| 16 |
+
### Setup
|
| 17 |
+
1. Free DB at [neon.tech](https://neon.tech) β copy the connection string
|
| 18 |
+
(`postgresql://user:pass@host.neon.tech/db?sslmode=require`).
|
| 19 |
+
2. HF Space β Settings β Variables and secrets β secret **`DATABASE_URL`** = that string.
|
| 20 |
+
3. Saving auto-restarts the Space. **Log in once** after that β first backup within 5 min β survives
|
| 21 |
+
all future restarts.
|
| 22 |
+
|
| 23 |
+
### Verify a backup landed
|
| 24 |
+
```sql
|
| 25 |
+
SELECT id, updated_at, octet_length(data) FROM chrome_profile;
|
| 26 |
+
```
|
| 27 |
+
A row with non-zero size = persisted. (Profile stays small β junk/cache is stripped each boot;
|
| 28 |
+
typically 0.5β2 MB. Neon free = 512 MB, so it's ~0.1% used.)
|
| 29 |
+
|
| 30 |
+
## Self-host Docker β named volume (no DB needed)
|
| 31 |
+
|
| 32 |
+
`docker-compose.yml` mounts the `chrome-profile` named volume at `/home/chrome/data`, so logins
|
| 33 |
+
survive `docker compose down/up` and reboots automatically. **`DATABASE_URL` is not needed** for
|
| 34 |
+
Docker. To wipe the profile: `docker compose down -v`.
|
| 35 |
+
|
| 36 |
+
> Important: setting a new secret on HF forces a restart. If you log in *before* `DATABASE_URL` is
|
| 37 |
+
> set, that login is lost on the restart the secret triggers β log in again afterward.
|
docs/troubleshooting.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Troubleshooting β check here first
|
| 2 |
+
|
| 3 |
+
Every issue we actually hit, and the fix.
|
| 4 |
+
|
| 5 |
+
## Deploy / build
|
| 6 |
+
|
| 7 |
+
| Symptom | Cause β Fix |
|
| 8 |
+
|---------|-------------|
|
| 9 |
+
| `pre-receive hook declined: You are not authorized to push` | The token in the `origin` URL isn't the Space owner's. Use an `akash1313` token with `repo.write` (see [deployment.md](deployment.md)). |
|
| 10 |
+
| `Repository not found` on push | Remote points to a Space that doesn't exist. `git remote -v` and fix the name (we deploy to `akash1313/selfapi`). |
|
| 11 |
+
| Build `BUILD_ERROR` after bumping a server | `go.mod` Go version > build-stage image. Raise the `FROM golang:X` in the Dockerfile. |
|
| 12 |
+
| Python `externally-managed-environment` during pip | Debian 12 PEP-668. We use `pip3 install --break-system-packages` (already in Dockerfile). |
|
| 13 |
+
| Frequent restarts | Normal: **every `git push` and every secret change rebuilds.** Batch edits into one push. Not a CPU/RAM issue (cpu-basic = 2 vCPU / 16 GB; usage ~1β2 GB). |
|
| 14 |
+
|
| 15 |
+
## API gateway
|
| 16 |
+
|
| 17 |
+
| Symptom | Cause β Fix |
|
| 18 |
+
|---------|-------------|
|
| 19 |
+
| All `/gpt /gemini /flow` return `503` | `API_KEY` not set on the server. Set the secret (fail-closed by design). |
|
| 20 |
+
| `401` | Missing/wrong `Authorization: Bearer <key>`. |
|
| 21 |
+
| `502 backend unavailable` | That server is still booting or crashed. Check its log `/home/chrome/{chatgpt,gemini,flow}.log`. |
|
| 22 |
+
| `404` through the gateway | Path forwarded but wrong on the backend β check the route in [../HOWTOUSE.md](../HOWTOUSE.md). |
|
| 23 |
+
|
| 24 |
+
## Runtime / browser
|
| 25 |
+
|
| 26 |
+
| Symptom | Cause β Fix |
|
| 27 |
+
|---------|-------------|
|
| 28 |
+
| Login lost after restart | `DATABASE_URL` unset or DB unreachable (HF). Set the Neon secret; verify a row in `chrome_profile`. |
|
| 29 |
+
| ChatGPT Cloudflare "verify you are human" loops | UA/OS mismatch. The UA **must be Linux** (the Space runs Linux) β it's set in `start_hf.sh` and `chatgpt-free-api/cookies.go` (Chrome 145). If it still loops, it's the datacenter IP (HF=AWS) β use a residential `--proxy-server`. |
|
| 30 |
+
| `extensionConnected:false` / `has_flow_key:false` on `/β¦/health` | The in-Chrome extension hasn't connected to its server yet. It connects when (a) Chrome has loaded the extension and (b) **you're logged in** to that service. Open the monitor UI, log in, wait. Extensions auto-retry (~5 s reconnect alarm). |
|
| 31 |
+
| `chrome://extensions/` empty, no error | Branded Chrome ignoring `--load-extension` β must use Chrome for Testing (already in Dockerfile). |
|
| 32 |
+
| `Failed to connect to the bus` / `DidStartWorkerFail` in `chrome.log` | Harmless container warnings β not a crash. |
|
| 33 |
+
| "Restore pages?" popup | Handled by the `exit_type=Normal` Preferences injection in `start_hf.sh`. |
|
| 34 |
+
|
| 35 |
+
## Self-host Docker
|
| 36 |
+
|
| 37 |
+
| Symptom | Cause β Fix |
|
| 38 |
+
|---------|-------------|
|
| 39 |
+
| Port collision on 9225/8000/8101 | Don't add separate server containers β the `chrome` image already runs all 3. `docker-compose.yml` has only the `chrome` service by design. |
|
| 40 |
+
| APIs return `503` locally | Add `API_KEY=β¦` to `.env` (compose passes it to the chrome service). |
|
| 41 |
+
| Profile not persisting | Don't use `down -v` (that deletes the `chrome-profile` volume). |
|