Deploying Sub2API: Pooling Subscription Quota Behind Your Own Gateway, and Where the Line Is

1 viewsSub2APIAI GatewaySelf-HostingDocker ComposeAccount Pool

Sub2API is an open-source gateway that turns Claude, OpenAI and Gemini subscriptions into a single API entry point. This is a full v0.2.0 install from scratch: the Docker Compose and binary routes, the four-step setup wizard, the compliance phrase you must type before the console opens, how the account pool and groups fit together, and why the author put a ban warning in the first paragraph of the README.

The most important sentence goes first: the author of Sub2API states, in the very first section of the README, that using the project may violate the terms of service of Anthropic and other upstream providers, and that the risk is borne entirely by the user. That is not a disclaimer I added; it is the project's own text. A line further down adds that no individual or organisation has ever been authorised to run any commercial operation based on it.

I lead with that because in the Chinese-language discussion around this project, words like "carpooling" and "splitting the cost" show up far more often than the risk warning, which makes it easy to assume installing it is free money. What it actually is: a [gateway](/wiki/ai-gateway) that converts AI product subscription quota into API quota and distributes it — technically well built, with a boundary of use you have to draw yourself.

This is a record of getting v0.2.0 (released 2026-09-02) from nothing to a working console. The repository, Wei-Shaw/sub2api, is LGPL-3.0, with a Go + Gin + Ent backend and a Vue 3 + Vite frontend, requiring PostgreSQL 15+ and Redis 7+. It had roughly 40,000 stars when this was checked.

How it differs from an ordinary AI gateway

Member A key GW Member B key Internal service Schedulergroups · sticky sessions · concurrency and rate limits Account pool Claude subscription OpenAI account Gemini account PostgreSQL usage and billingRedis sessions and limits

Figure 1: The request path. Downstream holds a key issued by the gateway; upstream accounts go into a pool that the scheduler picks from, and token usage per forward is written to PostgreSQL.

Compared with an application-facing gateway such as LiteLLM, Sub2API leans heavily toward operating a service: it has a user system, group plans, redeem codes, promo codes and built-in payments (EasyPay, Alipay, WeChat Pay, Stripe). The admin menu has more top-up-related entries than model-related ones. For a single person that is pure overhead; for someone standing up an internal service it is all already there.

The other key difference is the account pool with sticky sessions. Upstreams here are subscription accounts rather than API keys, and swapping accounts mid-conversation corrupts the context — so the scheduler has to pin a session to one account while still moving off an account that gets rate-limited. That is the genuinely hard part of a project like this.

Two deployment routes

Four installation methods are documented; two are worth considering.

RouteSuitsCost
Docker ComposeMost situations — one script brings up PostgreSQL and Redis tooNeeds to be able to pull Docker Hub images
Binary + systemdYou already run PG/Redis, or images will not pullYou provide the database and Redis
Apple containerThe native container stack on macOS 26No supervisor; bring it back up manually after a reboot
Build from sourceYou want to change the codeThe full Go 1.27 + pnpm toolchain

Route one: Docker Compose

mkdir -p sub2api-deploy && cd sub2api-deploy
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash

The script downloads docker-compose.local.yml and .env.example, generates JWT_SECRET, TOTP_ENCRYPTION_KEY and POSTGRES_PASSWORD into .env, and creates the data directories. Save the credentials it prints, especially the database password.

Piping a remote script into a shell is the kind of thing worth doing in two steps:

curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh -o docker-deploy.sh
less docker-deploy.sh
chmod +x docker-deploy.sh && ./docker-deploy.sh

Then start it:

docker compose -f docker-compose.local.yml up -d
docker compose -f docker-compose.local.yml logs -f sub2api

Why `docker-compose.local.yml` rather than `docker-compose.yml`: the former keeps data in data/, postgres_data/ and redis_data/ in the current directory, so migrating is a tar of one folder; the latter uses Docker named volumes and requires docker commands to move. The project recommends the former too.

If you did not set ADMIN_PASSWORD, the admin password is generated and printed to the log:

docker compose -f docker-compose.local.yml logs sub2api | grep "admin password"

Route two: the binary

One line on a Linux server:

curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash
sudo systemctl enable --now sub2api

The script detects the architecture, pulls the release, installs into /opt/sub2api and writes a systemd unit. It assumes PostgreSQL 15+ and Redis 7+ are already running.

The releases page also ships darwin_arm64 and darwin_amd64 builds, which is what I used on macOS — a workable escape route when Docker Hub images will not pull:

tar xzf sub2api_0.2.0_darwin_arm64.tar.gz
./sub2api -version
# Sub2API 0.2.0 (commit: aa236488..., built: 2026-09-02T03:13:57Z)
./sub2api

With no configuration file present, the first start enters wizard mode:

First run detected, starting setup wizard...
Setup wizard available at http://127.0.0.1:8080

The four-step setup wizard

Step one of the Sub2API setup wizard, with Database Configuration, Redis Configuration, Admin Account and Ready to Install shown as steps across the top, a form for host, port, username, password, database name and SSL mode, and a Test Connection button at the bottom

Step one of the Sub2API setup wizard, with Database Configuration, Redis Configuration, Admin Account and Ready to Install shown as steps across the top, a form for host, port, username, password, database name and SSL mode, and a Test Connection button at the bottom

Figure 2: Step one of the wizard. Each step has its own connectivity test — do not skip Test Connection; failing here is far cheaper than debugging after installation.

The four steps are database, Redis, admin account and confirm, and the buttons map to three endpoints: /setup/test-db, /setup/test-redis and /setup/install. Confirming creates tables, runs migrations, writes config.yaml, and reports that the service will restart automatically.

One behaviour appears only outside Linux. The log prints:

Service restart via exit only works on Linux with systemd

In other words, on macOS it does not actually restart — press Ctrl-C and start it again. On Linux with systemd, systemd handles it.

The trap in the official README is real

Anyone building from source or preparing configuration by hand walks straight into this: if you copy `config.example.yaml` to `config.yaml` before the first start, the wizard is skipped. The program sees an existing config, boots into normal mode with an empty users table, and the first login inevitably returns invalid email or password.

The default.admin_email and default.admin_password fields in config.yaml are historical leftovers and are not used to create the administrator. The fix is to move the config aside and let the wizard run once:

mv config.yaml config.yaml.bak
./sub2api          # the wizard writes a fresh config.yaml when it finishes
# Ctrl-C to stop
mv config.yaml.bak config.yaml
./sub2api          # log in with the admin you just created

The Docker route avoids this entirely, because the compose file sets AUTO_SETUP=true and initialisation is automatic.

Before the console opens, you type a sentence

Logging in does not land you in the console. A compliance gate comes first:

The Sub2API deployment and operation compliance acknowledgment page, with a yellow warning bar, a requirement to type a confirmation phrase exactly, and a welcome dialog describing core features overlaid in the centre

The Sub2API deployment and operation compliance acknowledgment page, with a yellow warning bar, a requirement to type a confirmation phrase exactly, and a welcome dialog describing core features overlaid in the centre

Figure 3: The compliance gate in front of the console. You must type the phrase exactly to get through, and a new version of the document requires acknowledging again. The dialog in the centre is a skippable feature tour.

You have to enter one sentence word for word before "Acknowledge and Continue" becomes active. This design deserves credit: it is not a checkbox, it forces you to read the text at least once. When the document version changes (the page shows v2026.06.10), every console user re-acknowledges.

From the author's side this is risk isolation. From yours the message is unambiguous — compliance responsibility for this project sits with whoever deploys it, not with whoever wrote it.

What the console manages

The Sub2API admin dashboard, with a row of stat cards for API Keys, Accounts, Today Requests, Users, Today Tokens, Total Tokens, Performance and Avg Response, and hourly usage charts below, all at zero because the instance is brand new

The Sub2API admin dashboard, with a row of stat cards for API Keys, Accounts, Today Requests, Users, Today Tokens, Total Tokens, Performance and Avg Response, and hourly usage charts below, all at zero because the instance is brand new

Figure 4: The admin dashboard on a fresh instance. The left-hand menu runs from Dashboard, Users, Groups and Channels all the way to Redeem Codes, Promo Codes and Audit Logs — operations features take up more than half of it.

What you actually need to understand is a three-layer data model:

  • Accounts: the upstream subscriptions or API keys. This is where cost comes from.
  • Groups: the plan layer. Bundle accounts into a group, set price, rate limits and available models, then assign users to groups. VIP groups get the good accounts, trial groups get the cheap ones — that is what this layer is for.
  • Users / API Keys: downstream. Every user gets their own key, with usage and quota tracked per person.

To skip the whole SaaS apparatus there is a switch:

RUN_MODE=simple
SIMPLE_MODE_CONFIRM=true   # required alongside it in production, or startup refuses

Simple Mode hides billing and plans and keeps just the gateway. For personal use or a small internal team, that is the cleaner starting point.

Adding an account: platform and connection method are two axes

The Sub2API Create Account dialog, step one: a Platform row listing Anthropic, OpenAI, Gemini, Antigravity, Grok, Kimi, Zhipu GLM and DeepSeek, an Account Type row listing Claude Code, Claude Console, AWS Bedrock and Vertex, and OAuth and Setup Token as the two add methods

The Sub2API Create Account dialog, step one: a Platform row listing Anthropic, OpenAI, Gemini, Antigravity, Grok, Kimi, Zhipu GLM and DeepSeek, an Account Type row listing Claude Code, Claude Console, AWS Bedrock and Vertex, and OAuth and Setup Token as the two add methods

Figure 5: Step one of adding an account. Picking a platform changes the Account Type row — within Anthropic alone, Claude Code subscriptions, a Claude Console API key, AWS Bedrock and Vertex are four different paths.

That dialog essentially maps the project's capability surface: platforms cover Anthropic, OpenAI, Gemini, Antigravity, Grok, Kimi, Zhipu GLM and DeepSeek, and the Anthropic side supports Claude Code OAuth and setup tokens, Claude Console API keys, AWS Bedrock and Vertex. Subscriptions come in through OAuth, standard APIs through a key — two entirely different credential types, which is exactly why groups exist to keep them apart.

Antigravity accounts get dedicated endpoints. Claude Code connects like this:

export ANTHROPIC_BASE_URL="http://localhost:8080/antigravity"
export ANTHROPIC_AUTH_TOKEN="sk-your-gateway-key"

The project warns explicitly that native Anthropic Claude and Antigravity Claude cannot be mixed within one conversation context; isolate them with groups or the session breaks.

Things to settle before production

Those WARN lines in the startup log are not noise. Each one is a task:

Warning: JWT secret auto-generated. Consider setting a fixed secret for production.
Warning: CORS allowed_origins not configured; cross-origin requests will be rejected.
Warning: server.trusted_proxies is not configured
payment encryption/signing key is not explicitly configured; set TOTP_ENCRYPTION_KEY

What to do about them:

  1. Pin `JWT_SECRET` and `TOTP_ENCRYPTION_KEY`. Auto-generated means regenerated on every restart — all users logged out, two-factor broken. Generate with openssl rand -hex 32 and put them in .env.
  2. Set `trusted_proxies` to match your reverse-proxy topology. Without it, rate limiting and audit logs record the proxy's IP, which invalidates every IP-based policy you have.
  3. Add `underscores_in_headers on;` to Nginx (in the http block). Nginx drops headers containing underscores by default, and multi-account sticky sessions depend on the session_id header — leave it out and Codex CLI sessions hop between accounts, a failure mode that is miserable to diagnose.
  4. Do not expose 8080 directly. Put a reverse proxy and HTTPS in front, and add another access control layer on the admin paths.
  5. `chmod 600 .env`. It holds the database password and every secret.

Who it suits, and who should walk away

A good fit: anyone who needs to manage several upstream accounts for a team or a small circle and wants usage attributed per person. The account-pool scheduling, sticky sessions, group pricing and audit logs would take real time to build yourself.

Should walk away:

  • Anyone using it alone — this is far too heavy. Installing PostgreSQL and Redis just to call an API yourself is poor value; see 9Router or LiteLLM.
  • Anyone planning to resell access or run a "carpool" business on it — the author has said no commercial operation is authorised, and upstream vendor terms broadly prohibit account sharing. That it runs does not mean it is consequence-free, and the account that gets banned is yours, not the repository author's.
  • Anyone inside a compliance-sensitive company — connecting employees' personal subscriptions into a company system is a decision that needs legal review first.

One more note: the README states that the project uses only the domains sub2api.org and pincc.ai, and that other sites trading on the name are unaffiliated. There are plenty of same-named forks on GitHub as well, so confirm the repository owner before installing.

Alternatives

  • [LiteLLM](/articles/litellm-gateway-deployment-guide): an application-facing gateway with more engineered virtual keys, budgets and routing policies, but no support for subscription OAuth as an upstream.
  • New API / One API: also has a user system and top-ups, with a mature Chinese-language ecosystem, and upstreams that are mostly standard API keys. See the relay station guide.
  • The vendors' own team plans: Anthropic and OpenAI both sell proper team and enterprise offerings. They cost more, but they carry no terms risk and nothing to operate. If this is genuinely for a team, price that option first.

Sources and how they were checked

The screenshots, startup logs and wizard flow come from a v0.2.0 install performed on 2026-09-04. Version numbers, the platform roster, the compliance document version and the environment variable list are all volatile — this project ships releases daily — so read the README of the build you downloaded before copying any command from this article.