This document is the single source of truth for how to run SIN-Code WebUI v2 locally, on a dev machine, and in production.
Last verified against:
a718702(post PR #18) + deploy work in PR #34.
┌───────────────────────────────────────────────────────────┐
│ Public Internet (browser, phone, share-link) │
└──────────────────────┬────────────────────────────────────┘
│ https (Cloudflare Tunnel OR domain)
▼
┌───────────────────────────────────────────────────────────┐
│ Cloudflare edge (free tier) │
│ ├─ *.trycloudflare.com (quick tunnel, dev) │
│ └─ sin-code.example.com (named tunnel, prod) │
└──────────────────────┬────────────────────────────────────┘
│ TLS
▼
┌───────────────────────────────────────────────────────────┐
│ caddy :80 / :443 (reverse proxy + auto-HTTPS) │
│ → webui:3000 (Next.js standalone) │
└──────────────────────┬────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────┐
│ webui (Next.js 16, standalone) │
│ ├─ /api/chat → streamText → LLM gateway │
│ ├─ /api/sin/status → reads status from sin-code binary │
│ └─ lib/sin/{client,mcp}.ts → execFile/spawns │
│ │ │
│ ▼ │
│ sin-code binary (BUNDLED INSIDE THE IMAGE) │
│ ├─ 32 subcommands (CLI) │
│ └─ 44 MCP tools (sin_*) │
└───────────────────────────────────────────────────────────┘
The sin-code Go binary is bundled inside the webui image
(downloaded in the Dockerfile's sin-code stage from the official
SIN-Code-Bundle release). The webui spawns it via execFile /
StdioMCPTransport — same process tree, no extra service to manage.
If you need a dedicated sin-code service (e.g. to share one
across multiple webui replicas), enable the tools profile:
orb compose --profile tools up -dThis starts the ghcr.io/opensin-code/sin-code:v2.5.0 image on
port 8090 and the webui can be pointed at it via SIN_CODE_BIN env
pointing at the host's port.
Why OrbStack, not Docker Desktop? Per the repo AGENTS.md, Docker Desktop on macOS is unstable. OrbStack provides a Docker- compatible engine (the plain
dockercommand works — verified viadocker context showreturningorbstack) backed by native macOS virtualization. Theorbbinary itself is for managing Linux machines, not containers — container commands usedockerdirectly. See~/.config/opencode/AGENTS.md.
# 1. Install OrbStack
brew install orbstack
# 2. Install cloudflared (for public URLs)
brew install cloudflared
# 3. Clone the repo + install deps
cd ~/dev
git clone https://github.com/OpenSIN-Code/SIN-Code-WebUI-v2
cd SIN-Code-WebUI-v2
pnpm install
# 4. Fill in secrets
cp .env.example .env
# → edit .env, set AI_GATEWAY_API_KEY=vck_…# Start the stack (uses `docker`, backed by OrbStack on macOS)
./scripts/orb-up.sh
# → builds the image, starts 3 containers, prints endpoints
# Open the UI
open http://localhost:8080
# Make it public (optional — get a trycloudflare.com URL)
./scripts/tunnel-up.sh
# → prints https://<random>.trycloudflare.com (Ctrl-C to stop)
# Tail logs
docker compose logs -f webui
# Stop everything
./scripts/orb-down.sh # keep volumes
./scripts/orb-down.sh --volumes # nuke caddy certs too| Port | Service | Public? |
|---|---|---|
| 8080 | caddy (HTTP) → webui | yes (or via tunnel) |
| 3000 | webui (Next.js) | no — internal only |
| 8090 | sin-code stdio bridge (optional profile) | no — internal only |
Same commands, but orb is unavailable. The scripts auto-fall-back
to plain docker:
docker compose up -d
docker compose logs -f webuiThe same
docker-compose.ymlruns unchanged on any Linux VPS with Docker installed. The VPS becomes a one-command install.
# 1. SSH in
ssh root@your-vps
# 2. Install Docker + clone
curl -fsSL https://get.docker.com | sh
apt install -y docker-compose-plugin
git clone https://github.com/OpenSIN-Code/SIN-Code-WebUI-v2
cd SIN-Code-WebUI-v2
# 3. Fill in secrets
cp .env.example .env
nano .env # set AI_GATEWAY_API_KEY, TUNNEL_TOKEN (if using named tunnel)
# 4. (Optional but recommended) named Cloudflare tunnel
# See: https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/
cloudflared tunnel login
cloudflared tunnel create sin-code-webui
cloudflared tunnel token sin-code-webui # paste into .env as TUNNEL_TOKEN
# 5. Start
./scripts/orb-up.sh # works with `docker` fallback on Linux
# 6. (If not using cloudflared) point a real domain at the VPS
# and Caddy will auto-issue a Let's Encrypt cert.- No firewall holes — the VPS doesn't expose 80/443 to the world
- Free TLS — Cloudflare terminates TLS at the edge
- DDoS protection — built-in
- DDoS-aware origin — the tunnel is outbound, so attackers can't reach the VPS directly
- One domain per stack — bind
sin-code.example.comwithout changing VPS firewall
Next.js 16 produces a self-contained Node.js server in
.next/standalone/ that includes only the files actually used by
your app (no node_modules for unused packages). The Dockerfile
copies that + the .next/static/ folder + public/ into a slim
node:22-slim image. Result: ~250 MB image, no pnpm install
at runtime, no 1 GB node_modules in the container.
The Dockerfile has a sin-code build stage that downloads the
official release tarball from
https://github.com/OpenSIN-Code/SIN-Code-Bundle/releases.
Override with --build-arg SIN_CODE_VERSION=v2.5.1.
If the release URL changes, the Dockerfile falls back to
/releases/latest/download/. The binary is verified with
--version at build time so a broken download fails the build.
- Buildx cache is enabled via
cache-from: type=ghaandcache-to: type=gha,mode=maxin the GH workflow - Local builds with OrbStack are similarly cached by default
| Variable | Default | Where | Purpose |
|---|---|---|---|
AI_GATEWAY_API_KEY |
(required) | .env | Vercel AI Gateway key (or any OpenAI/Anthropic compat key) |
SIN_CHAT_MODEL |
openai/gpt-5-mini |
.env | Model id passed to streamText |
SIN_CODE_BIN |
/usr/local/bin/sin-code |
Dockerfile | Path to the bundled binary |
WEBUI_PORT |
8080 |
.env | Host port for caddy |
SIN_CODE_PORT |
8090 |
.env | Host port for the optional sin-code service |
TUNNEL_NAME |
sin-code-webui |
.env | Cloudflare tunnel name |
TUNNEL_TOKEN |
(empty → no tunnel) | .env | Cloudflare tunnel auth token |
| Symptom | Cause | Fix |
|---|---|---|
orb not found |
OrbStack not installed | brew install orbstack |
docker compose config errors |
compose file syntax | run docker compose config to see error |
webui unhealthy |
bad AI_GATEWAY_API_KEY |
check container logs, fix .env, restart |
caddy exits immediately |
port 80 already in use | change WEBUI_PORT=8080 to WEBUI_PORT=8888 |
| Cloudflare tunnel says "no such host" | cloudflared not authenticated |
cloudflared tunnel login |
sin-code binary not running |
missing in PATH inside container | check Dockerfile's sin-code stage, re-build |
CORS errors from /api/* |
browser hitting wrong origin | access via http://localhost:8080, not http://localhost:3000 directly |
# Soft: keep data, stop containers
./scripts/orb-down.sh
# Hard: nuke data too
./scripts/orb-down.sh --volumes
docker system prune -a # also cleans up dangling images-
.envhas a realAI_GATEWAY_API_KEY -
TUNNEL_TOKENset (if using Cloudflare tunnel) - Caddy logs show no startup errors:
docker compose logs caddy - WebUI is reachable:
curl -s localhost:8080/api/sin/status | jq - Cloudflare tunnel URL responds to HTTPS
- Auto-restart works:
docker compose restartand checkdocker compose ps - Disk usage sane:
docker system df(<5 GB expected)
PLAN_MIGRATION.md— the sin-code backend integration planREADME.md— project overview, setup, scripts- SIN-Code-Bundle releases
- OrbStack docs
- Cloudflare Tunnel docs