Skip to content

feat: multi-account load balancing, mandatory Bearer auth, Linux/systemd deployment guide#22

Open
GoNNoTDa wants to merge 1 commit into
Sophomoresty:mainfrom
GoNNoTDa:main
Open

feat: multi-account load balancing, mandatory Bearer auth, Linux/systemd deployment guide#22
GoNNoTDa wants to merge 1 commit into
Sophomoresty:mainfrom
GoNNoTDa:main

Conversation

@GoNNoTDa

@GoNNoTDa GoNNoTDa commented Jun 2, 2026

Copy link
Copy Markdown

Summary

This PR adds two major features and a comprehensive deployment guide:

  1. Multi-account load balancing — distribute requests across multiple Google accounts via round-robin
  2. Mandatory Bearer token authentication — the server now requires api_keys to be configured and rejects all requests without a valid token
  3. Linux/systemd deployment guide — step-by-step instructions for running the server as a persistent service on a Linux machine, including HTTPS via nginx + Certbot

Changes

New file: gemini_web2api/accounts.py

Introduces two classes:

  • Account — wraps a single Google session (cookie file, auth_user, per-account proxy, XSRF token). Cookie files are reloaded automatically on change via mtime caching, so you can rotate cookies without restarting the server.
  • AccountPool — thread-safe pool with round-robin selection. Each call to generate() or generate_stream() picks the next account in sequence.

Modified: gemini_web2api/gemini.py

generate() and generate_stream() now call POOL.next() to pick an account per request, instead of reading CONFIG globals directly. Each account carries its own headers, cookie, SAPISIDHASH, proxy, and URL prefix.

Modified: gemini_web2api/server.py

  • _authorized() now returns False (deny) when api_keys is empty, instead of True (allow). An unconfigured server no longer accepts all traffic.
  • Added _require_auth() helper — sends a 401 with a descriptive error and returns True so handlers can return immediately.
  • Auth is enforced on all endpoints: GET /v1/models, GET /v1beta/models, GET /, and all POST routes.
  • Health check (GET /) now reports account count and names.

Modified: gemini_web2api/config.py

  • Default host changed from 0.0.0.0 to 127.0.0.1 (localhost-only by default).
  • Added accounts: [] key with inline documentation.
  • api_keys documented as required.

Modified: gemini_web2api/__main__.py

  • Calls POOL.load_from_config(CONFIG) on startup.
  • Adds a startup safety check: prints a clear error message and exits with code 1 if api_keys is empty.
  • Startup banner now shows account count, account names, and number of configured API keys.
  • Accepts new --host CLI argument.

Modified: gemini_web2api.py (monolithic file)

All of the above changes mirrored into the standalone single-file version, so users who run python gemini_web2api.py directly get the same behaviour.

Modified: config.example.json

Updated to show the multi-account accounts list format, with comments explaining each field. Legacy flat fields documented as a fallback for single-account setups.

Modified: README.md

Rewritten to document all new features and add a full Linux server deployment guide. See details below.


README additions

  • Authentication section explaining the new mandatory token requirement, how to generate a secure token, and how to configure multiple keys.
  • Multi-account Setup section with a full example config, explanation of auth_user, and step-by-step cookie export instructions.
  • Linux Server Deployment — 10 detailed steps:
    • Creating a dedicated non-root gemini system user
    • Uploading files via scp or git clone
    • Setting 600 permissions on cookie files
    • Testing the server manually before installing the service
    • Creating /etc/systemd/system/gemini-web2api.service with security hardening directives (NoNewPrivileges, ProtectSystem=strict, PrivateTmp)
    • systemctl enable + start + status verification
    • Log inspection via journalctl
  • HTTPS with nginx + Certbot — optional section for exposing the API externally, including proxy_buffering off needed for SSE streaming.
  • Service Management quick-reference table (start, stop, restart, enable, disable, log commands).
  • Configuration Reference tables for all config keys and account object fields.

Backwards compatibility

  • Single-account users with a flat cookie_file / auth_user / proxy config continue to work without any changes — the pool falls back to a single account built from those fields.
  • The only breaking change is that servers with an empty api_keys list (the previous default) will now refuse all requests and refuse to start. This is intentional: an accidentally open server on 0.0.0.0 is a security risk. To restore the old open behaviour, the operator must explicitly set "host": "127.0.0.1" and accept that only local processes can reach it — or add API keys.

Testing

Tested with:

  • Single-account anonymous mode (no cookie)
  • Single-account with cookie via legacy flat config
  • Two-account round-robin with different auth_user indices
  • curl with and without Authorization: Bearer header (401 verified)
  • Streaming (gemini-3.5-flash) and non-streaming (gemini-3.5-flash-thinking) requests
  • python -m gemini_web2api (package) and python gemini_web2api.py (monolithic)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant