Multi-account Ollama Cloud reverse proxy
Find a file
Atte149 c8974d9998 docs: document openlama launcher and NO_PROXY requirement
- openlama wrapper at ~/.local/bin/openlama sets NO_PROXY and execs opencode
- Documents that opencode does not auto-fetch /v1/models (models must be listed)
- Documents the NO_PROXY fix for Bun runtime + HTTP_PROXY conflict
2026-06-19 14:08:28 +03:00
internal feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
systemd feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
.gitignore feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
AGENTS.md docs: document openlama launcher and NO_PROXY requirement 2026-06-19 14:08:28 +03:00
go.mod feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
go.sum feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
main.go feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
Makefile feat: ollama-proxy — multi-account Ollama Cloud reverse proxy 2026-06-19 13:58:13 +03:00
README.md docs: document openlama launcher and NO_PROXY requirement 2026-06-19 14:08:28 +03:00

ollama-proxy

Multi-account reverse proxy for Ollama Cloud. Round-robin load balancing across multiple API keys with automatic failover on 429 (rate limit) and 5xx errors. Streaming (SSE + NDJSON) is passed through without buffering.

Listens on 127.0.0.1:11435 by default; exposes both the native Ollama API (/api/*) and the OpenAI-compatible API (/v1/*) that ollama.com serves natively. Designed to sit in front of OpenCode, ollama CLI, or any OpenAI-compatible client.

Build

make build

Produces ./ollama-proxy. Requires Go 1.21+ (uses log/slog).

Install

sudo make install
sudo systemctl enable --now ollama-proxy

This installs the binary to /usr/local/bin/ollama-proxy and the systemd unit to /etc/systemd/system/ollama-proxy.service, then reloads systemd.

Configure accounts

Accounts are stored in ~/.config/ollama-proxy/accounts.json (chmod 0600). Manage them via the CLI:

# Add an account (prompts for the key with echo disabled if not given on the CLI)
ollama-proxy accounts add --name work
ollama-proxy accounts add sk-xxxx-... --name personal

# List accounts (keys are masked)
ollama-proxy accounts list

# Remove by name or id prefix
ollama-proxy accounts remove work
ollama-proxy accounts remove 3e94140f

# Override the default upstream (rarely needed; default is https://ollama.com)
ollama-proxy accounts set-base-url https://ollama.com

API keys are created at https://ollama.com/settings/keys.

Run as a service

The systemd unit runs the proxy on 127.0.0.1:11435 and restarts on crash. Logs go to journald:

journalctl -u ollama-proxy -f

Configuration flags can be overridden via environment variables in the unit (or in a drop-in):

Variable Default Description
OLLAMA_PROXY_ADDR 127.0.0.1:11435 listen address
OLLAMA_PROXY_BASE_URL https://ollama.com upstream root
OLLAMA_PROXY_COOLDOWN 60s per-account 429 cooldown window
OLLAMA_PROXY_RETRIES 3 max failover attempts
OLLAMA_PROXY_LOG_LEVEL info debug | info | warn | error

Use with OpenCode

Add a custom provider to ~/.config/opencode/opencode.json:

"ocp": {
  "npm": "@ai-sdk/openai-compatible",
  "name": "Ollama Cloud (pool)",
  "options": {
    "baseURL": "http://127.0.0.1:11435/v1",
    "apiKey": "proxy"
  },
  "models": {
    "gpt-oss:20b": { "name": "gpt-oss:20b" },
    "gpt-oss:120b": { "name": "gpt-oss:120b" },
    "kimi-k2.6": { "name": "kimi-k2.6" }
  }
}

apiKey: "proxy" is a placeholder — the proxy ignores the client's Authorization header and substitutes the selected account's key. You must list models explicitly — opencode does not auto-fetch /v1/models for @ai-sdk/openai-compatible providers. To get the full list:

curl -sS http://127.0.0.1:11435/v1/models | jq -r '.data[].id'

NO_PROXY (important)

If your environment has HTTP_PROXY/HTTPS_PROXY set (e.g. http://127.0.0.1:2080), opencode's Bun runtime will route requests to the proxy through the HTTP proxy, resulting in 502 Bad Gateway. Exclude localhost from proxying:

# ~/.config/environment.d/no-proxy-local.conf
NO_PROXY=127.0.0.1,localhost,::1
no_proxy=127.0.0.1,localhost,::1

Or launch opencode with NO_PROXY=127.0.0.1,localhost opencode.

openlama launcher

A convenience wrapper is installed at ~/.local/bin/openlama. It sets NO_PROXY/no_proxy for localhost, tries to start ollama-proxy if it's down, and execs opencode with all forwarded args:

openlama                                   # TUI with ocp available as a provider
openlama run -m ocp/gpt-oss:120b "hello"   # non-interactive, specific model

Run /models in the OpenCode TUI to pick a model from the pool, then chat as usual.

Use with the ollama CLI

OLLAMA_HOST=127.0.0.1:11435 ollama run gpt-oss:20b

Endpoints

The proxy forwards (passthrough) any of these paths to ollama.com:

  • Native Ollama: /api/chat, /api/generate, /api/tags, /api/show, /api/ps, /api/version, /api/delete
  • OpenAI-compatible: /v1/chat/completions, /v1/completions, /v1/models, /v1/embeddings, /v1/files/*

Anything else returns 404.

How failover works

  1. For each request, the balancer picks the next account round-robin.
  2. If the upstream returns 429 before any bytes are sent to the client, the account is put in cooldown (default 60s) and the next account is tried, up to --retries attempts.
  3. If the upstream returns 5xx, the next account is tried without cooldown (5xx may be transient).
  4. Once a 2xx response has started streaming to the client, the request is committed: mid-stream upstream errors are surfaced as-is (a truncated response). The proxy never restarts a streamed request on a different account, because the client would see duplicated output.
  5. If every account is in cooldown, the client receives 429 {"error":{"message":"all accounts rate-limited"}}.
  6. If every account fails for non-429 reasons (network, 5xx), the client receives 502 {"error":{"message":"all accounts failed: …"}}.

Tests

go test ./...      # unit + integration
go vet ./...
gofmt -l .

The integration tests build the binary and exercise the full HTTP stack against an httptest upstream.

License

MIT.