freebucks-proxy
Multi-account OpenAI-compatible gateway for coding models. Pooled keys, session lifecycle, TLS stealth, embedded admin dashboard. No ads, no CLI, just /v1/chat/completions.
Links
README
From the repo.
freebucks-proxy
freebucks-proxy is a Go wire gateway in front of the upstream service: pooled multi-account OpenAI-compatible and Anthropic-compatible endpoints, an embedded Svelte dashboard, optional browser-like TLS stealth, and automatic session lifecycle.
What it is
- Speaks OpenAI chat (
POST /v1/chat/completions,GET /v1/models) and an Anthropic-compatible layer, then translates to the upstream wire protocol. - Runs in pooled, bridge, or hybrid mode (
EffectiveMode):- Pooled —
AUTH_TOKENSset +BRIDGE_ENABLED=0; pool only. - Bridge —
AUTH_TOKENSempty; each request carries its own token. - Hybrid (default with
AUTH_TOKENS) —API_KEYScredential uses the pool, any other credential relays upstream as a bridge token.
- Pooled —
- Dashboard at
/admin(Svelte SPA embedded in the binary). - Credit metering follows the wire
pricesmap (upstream credits, wire fieldsfreebucks*): charged once per session-hour at session start, refunded on earlyDELETE, and refilled at the daily reset the server advertises (resetTimeZone/resetAtin the session payload — the account's own local midnight; Pacific midnight only on servers that omit the zone). The proxy's own counters (per-day requests, spend buckets, IP re-admit caps) keep bucketing on the Pacific day (pool/spend.go:bucketStart).
Quickstart
cp .env.example .env # then edit: AUTH_TOKENS, ADMIN_TOKEN, ...
task build # frontend bundle + gateway binary (output in bin/)
task dev # run the gateway from source
Both tasks are defined in Taskfile.yml. With plain Go instead of a Task
runner, go build ./backend/... compiles everything and the gateway's main
package lives under backend/cmd/.
Run from GHCR (release image, no local build):
cp .env.example .env # then edit: AUTH_TOKENS, ADMIN_TOKEN, ...
export VERSION="$(gh release view --json tagName -q .tagName)"
docker compose pull
docker compose up -d
That resolves the newest release tag (prereleases excluded); pin VERSION to it
for a reproducible deploy, or leave VERSION unset to follow the latest image.
gh resolves the repository from the checkout — pass --repo <owner>/<name> if
you run it elsewhere. Verify GET /healthz → 200, and note /admin sits behind
the login gate (redirects to /admin/login).
Then:
GET http://localhost:3457/healthz→ 200GET http://localhost:3457/v1/models→ live model listhttp://localhost:3457/admin→ dashboard
Defaults that matter (.env.example): SAFE_MODE=true (anti-ban preset),
COST_MODE=free. The per-day/per-minute request caps are gone — upstream quota
and 429s are the enforcement — and per-IP rate limiting is off by default
(RATE_LIMIT_PER_IP=0; set it and RATE_LIMIT_BURST to enable).
Configuration persistence: the first boot imports the effective config
(process env wins over .env over defaults) into the dashboard DB
(DB_PATH, a SQLite file under data/, mode 0600) as config: overlay rows
plus a config:migrated_env_v1 marker — later boots are no-ops via the marker.
The DB is then the persisted home the dashboard saves write to, secrets
included (AUTH_TOKENS, ADMIN_TOKEN, API_KEYS, WEBHOOK_URL rows);
keep its 0600 mode on copies/backups. Explicit process env still wins at
runtime, so a migrated row never overrides the environment.
Update safety (read before every recreate)
Two-path layout: the live store is the DB_PATH file on the db_data named
volume (compose pins it under /app/data — an overlay row can never repoint
the open file), while the host checkout bind (.:/app/state, the working
directory) holds .env, logs, and the pre-volume bind DB under ./data/.
A fresh volume auto-imports that bind DB on first boot — display history plus
the full operator state (settings overlay with secrets, pages, sessions,
tokens, pool blobs), per-table, idempotent, secrets as opaque DB values — then
later boots are strict no-ops. Legacy files are never deleted. Never copy a
live DB with plain cp of the .db/-wal/-shm trio; stop first or use the
backup script.
Every update runs three commands (any trip = roll back, never cut traffic):
docker compose stop # whole stack, incl. the optional https front
scripts/backup-state.sh # snapshot + count manifest
docker compose up -d --build # recreate on the same volume
ADMIN_TOKEN="$ADMIN_TOKEN" scripts/verify-state.sh # healthz + 401 probe + migrate.noop + manifest counts
The gate requires /healthz 200, a wrong-token login 401, a strict no-op
boot (migrate.fresh=false, migrate.noop=true, applied=[]), and live
row counts matching the backup manifest (operator tables exact,
pool_state anti-stranding, history grow-only). First-ever volume adoption
boots fresh=true while it carries the bind DB — confirm the
carried legacy state log line against the manifest, restart once, then
the gate goes green.
One-time: the freebucks-proxy rename
The project was renamed from freebuff-proxy (repository, binary, compose
service, container, image). Two things need care exactly once:
git remote set-url origin https://github.com/trefeon/freebucks-proxy.git
docker compose down --remove-orphans # clears the pre-rename container
--remove-orphansmatters: the service was renamed, so the old container is no longer part of the stack — leaving it running means two gateways sharing one account pool, which burns quota twice and supersedes sessions.- The image path follows the repository name (
ghcr.io/trefeon/freebucks-proxy), so it exists only once a release is published after the rename. Until then, pinVERSIONto a tag from the previous image path or wait for that release. - The DB filename and session-state filename are deliberately unchanged
(
DB_PATH,SESSION_STATE_FILE): the live volume keeps its store, and pointing either at a new name on an existing volume would open an empty DB. - Installed as a background service? Its unit/task name and install paths
changed too. Uninstall the old one before installing the new: run the old
binary with
-uninstall-service(pre-rename systemd unitfreebuff-proxy.service, launchdcom.freebuff-proxy, or thefreebuff-proxyscheduled task), then move your.envfrom the old config directory to the new one — the renamed installer writesfreebucks-proxypaths, so the old service would otherwise keep serving from the same account pool while the new one starts empty.
Layout
backend/— gateway source.frontend/— dashboard SPA source.scripts/— upstream sync / drift tooling, plus the client tool-name corpus generator (extract-tool-calls.sh).docs/— client-compatibility recipes, upstream CLI notes, and architecture decisions (docs/decisions/).
Contributing
Protected main: branch → PR → green CI → squash merge, Conventional Commits.
See AGENTS.md for the full operating guide. Never commit secrets.
Collected info
- ★ 296 stars
- ⎇ 64 forks
- Language: Go
- Source updated: 9/24/2026
Config for your environment
Replace {MCP_ENDPOINT_URL} with this MCP’s endpoint URL (from its repo or docs above). No API key — you connect directly.
Tool
OS
Config file: ~/.cursor/mcp.json
{
"mcpServers": {
"mcp-server": {
"url": "{MCP_ENDPOINT_URL}"
}
}
}Paste into mcpServers in the config file. Restart Cursor after saving.
If this MCP is also published on mcpchannel.ai, you can subscribe from Browse and use the gateway config there instead.