This guide takes you from clone to a fully running local stack.

Prerequisites

  • Bun >= 1.3.5
  • Rust — latest stable
  • PostgreSQL 15+ (local or remote)
  • Docker & Docker Compose (optional, for one-command startup)

1. Clone and install dependencies

git clone https://github.com/xuerzong/openproxy.git
cd openproxy
bun install

2. Generate an RSA key pair

Provider API keys are stored RSA-encrypted in the database. Generate a key pair with:

bun scripts/generateRSAKey.ts

Keep the output — you'll need both values in the next step.

3. Configure environment variables

apps/server

cp apps/server/.env.example apps/server/.env

If you are following the Docker deployment flow, prefer cd docker && ./prepare.sh to generate docker/.env instead of filling Docker environment variables by hand.

Edit apps/server/.env with at minimum:

DATABASE_URL=postgres://user:password@localhost:5432/openproxy
BETTER_AUTH_SECRET=<random 32-byte base64 string>
BETTER_AUTH_URL=http://localhost:5173/api
# APP_DOMAIN is the apex domain (e.g. example.com; defaults to aiproxy.shop).
# It controls:
#   - trusted origins generated for *.APP_DOMAIN
#   - better-auth session cookie Domain (.APP_DOMAIN), so *.APP_DOMAIN
#     subdomains share the same login session (production only)
APP_DOMAIN=
# CLIENT_ORIGIN is the public origin of the tenant web app (scheme + host,
# no trailing slash, e.g. https://app.example.com). Used to build payment
# notify/return URLs and email verification links. Defaults to
# https://app.${APP_DOMAIN} in production and http://localhost:5173 in dev.
CLIENT_ORIGIN=
IS_OSS=true
ADMIN_EMAILS=owner@example.com
CRON_SECRET=
RSA_PRIVATE_KEY=<from step 2>
RSA_PUBLIC_KEY=<from step 2>

# Email — choose one
RESEND_API_KEY=         # Resend
SMTP_HOST=
SMTP_USER=
SMTP_PASS=
SMTP_FROM=

# Optional Alibaba Cloud SMS / captcha
ALIBABA_CLOUD_ACCESS_KEY_ID=
ALIBABA_CLOUD_ACCESS_KEY_SECRET=

`ADMIN_EMAILS` accepts a comma-separated list of admin emails. During self-hosted signup, users who register with one of these emails are promoted to `admin` automatically. This is the recommended admin bootstrap path.
ALI_CAPTCHA_API_KEY=

# Optional ZPayZ payment
ZPAYZ_CID=
ZPAYZ_PID=
ZPAYZ_PAY_KEY=
ZPAYZ_GATEWAY=https://zpayz.cn/submit.php

# Optional Redis
REDIS_URL=

# Optional: OAuth
GITHUB_CLIENT_ID=
GITHUB_CLIENT_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

apps/api

Create apps/api/.env:

DATABASE_URL=postgres://user:password@localhost:5432/openproxy
RSA_PRIVATE_KEY=<same private key as server>
PORT=5060

4. Run database migrations

cd apps/server
bun run migrate

This applies the SQL in apps/server/drizzle/ to your PostgreSQL instance.

5. Start all services

# From repo root — Turborepo starts everything in parallel
bun run dev

Or start each service individually:

cd apps/api    && cargo run                # Rust proxy on :5060
cd apps/server && bun run dev             # Bun backend on :3888
cd apps/web    && bun run dev:tenant      # Tenant UI on :5173
cd apps/web    && bun run dev:admin       # Admin UI on :5173

6. Verify the stack

# Proxy health check
curl http://localhost:5060/health

# Server health check
curl http://localhost:3888/api/health

Then open http://localhost:5173 in your browser to access the web interface.

Default ports

| Service | URL | | --- | --- | | Rust proxy | http://localhost:5060 | | Bun server | http://localhost:3888 | | Tenant web | http://localhost:5173 | | Admin web | http://localhost:5173 |

Common startup issues

Database connection failed

Verify DATABASE_URL is correct, PostgreSQL is running, and the user has CREATE privileges (needed for migration).

Auth callback issues

For local development, BETTER_AUTH_URL should usually stay aligned with the frontend origin as http://localhost:5173/api. Trusted origins are derived from the built-in localhost rules and APP_DOMAIN, so most setups do not need an extra auth origin environment variable.

API key decryption failed / RSA error

Ensure the RSA_PRIVATE_KEY in apps/api/.env is the same key used in apps/server/.env, and that the value is complete without broken line breaks or extra spaces. Always use values from a single run of bun scripts/generateRSAKey.ts.

Port already in use

Check if another process is using :5060 or :3888. Override with PORT=xxxx in the relevant .env file.