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
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.
| Route | Suits | Cost |
|---|---|---|
| Docker Compose | Most situations — one script brings up PostgreSQL and Redis too | Needs to be able to pull Docker Hub images |
| Binary + systemd | You already run PG/Redis, or images will not pull | You provide the database and Redis |
| Apple container | The native container stack on macOS 26 | No supervisor; bring it back up manually after a reboot |
| Build from source | You want to change the code | The 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 | bashThe 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.shThen start it:
docker compose -f docker-compose.local.yml up -d
docker compose -f docker-compose.local.yml logs -f sub2apiWhy `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 sub2apiThe 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)
./sub2apiWith 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:8080The four-step setup wizard
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 systemdIn 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 createdThe 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:
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
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 refusesSimple 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
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_KEYWhat to do about them:
- 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 32and put them in.env. - 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.
- Add `underscores_in_headers on;` to Nginx (in the
httpblock). Nginx drops headers containing underscores by default, and multi-account sticky sessions depend on thesession_idheader — leave it out and Codex CLI sessions hop between accounts, a failure mode that is miserable to diagnose. - Do not expose 8080 directly. Put a reverse proxy and HTTPS in front, and add another access control layer on the admin paths.
- `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
- Wei-Shaw/sub2api repository — feature list, tech stack, Nginx and Simple Mode notes, and the terms-of-service warning.
- deploy/README.md in the repository — deployment comparison, environment variable table, migration and troubleshooting commands.
- GitHub Releases — version numbers, build timestamps and per-platform binaries.
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.