Skip to content

Latest commit

 

History

369 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📦⚡️ Casbin Gateway

An open-source gateway for the AI coding agents and the web traffic on your machine, developed by Go and React.

Lint Build Go Reference GitHub Release

license GitHub issues GitHub stars GitHub forks Discord

English | 中文

Run it

One command. No database, no Go, no Node, no configuration.

On Linux and macOS:

curl -fsSL https://raw.githubusercontent.com/apache/casbin-gateway/master/scripts/install.sh | bash

On Windows, in PowerShell:

irm https://raw.githubusercontent.com/apache/casbin-gateway/master/scripts/install.ps1 | iex

Either one downloads the build for this machine, unpacks it into ~/.local/share/casbin-gateway (%LOCALAPPDATA%\casbin-gateway on Windows), puts a casbin-gateway command on your PATH, and starts it. Then open:

http://localhost:17000 — sign in as admin with the password 123, and change it from My Account.

That is the whole installation. Gateway keeps its data in a SQLite file inside its own directory, and signs you in against its own user table.

What to do next

Page What you get What it needs
Agents Every AI coding agent installed on this machine — Claude Code, Codex CLI, Cursor and more. Click Patch on one and its activity streams into the page live. Nothing
Skills & MCP Every skill and MCP server of every agent in one table. Add an MCP server to one agent or to several at once, open one, delete it, or copy it into another agent. Nothing
Providers One endpoint in front of your model vendors. Gateway holds the API key, so the agents never have it — or forwards the agent's own sign-in and holds nothing. A vendor API key, or nothing at all
LLM Records Every request an agent relayed: the full system prompt, every message and tool call, the schema of every tool the model was offered, plus tokens and cost. A provider, and llmRecordMode — see Recording prompts
Advanced → Sites The reverse-proxy WAF: per-site routing, rules, certificates and analytics. Turning the proxy on — see Turning the WAF proxy on

Agents are found by reading the user accounts, home directories and install paths of the machine Gateway runs on, so run it on the machine whose agents you want to watch.

Send an agent's traffic through Gateway

This is what fills LLM Records, and what lets Gateway keep the vendor key instead of the agent.

  1. ProvidersAdd: pick the type (OpenAI- or Anthropic-compatible), paste the vendor base URL and API key, and list the models it serves.
  2. Agents → open an agent → pick that provider.
  3. Copy the environment snippet the page shows, and start the agent from a shell that has it:
export ANTHROPIC_BASE_URL="http://localhost:17000/v1/agents/claude-code"
export ANTHROPIC_AUTH_TOKEN="casbin-gateway"

The token is a placeholder — the agent refuses to start without one, and Gateway authenticates upstream with the provider's own key.

No API key: keep the sign-in the agent already has

An agent signed in with a ChatGPT or Claude subscription has no API key to paste. Set the provider's Authentication to the caller's own login and it needs none: the base URL points at the vendor, and every request is forwarded with the credentials the agent itself sent, so it keeps its own sign-in. Leave Models empty and the provider accepts any model name.

The environment snippet for such a provider sets the base URL and nothing else — a token there would replace the sign-in the agent already has. Gateway records and routes the traffic exactly as it does for a provider with a key; it just never sees one.

Codex is the exception: its ChatGPT sign-in talks to a different API than the chat completions Gateway relays, so a Codex CLI still needs a provider with an API key.

Stopping, upgrading, removing

  • Stop: Ctrl-C. Start again: casbin-gateway, from any directory — the command is a wrapper that always starts Gateway in its install directory, where its data lives.
  • Upgrade: run the install command again. Your database and settings are untouched.
  • Remove: delete ~/.local/share/casbin-gateway and ~/.local/bin/casbin-gateway (on Windows, %LOCALAPPDATA%\casbin-gateway and its PATH entry).

Set INSTALL_DIR to install somewhere else, or NO_START=1 to install without starting.

These are nightly builds, rebuilt from master on every push and published as the nightly pre-release. They exist so that Gateway can be tried without a Go and Node toolchain; anything else should be built from a source release.

Running in Docker or Podman

A container cannot see the agents on your machine. Agents are discovered by reading the home directories and install paths of the machine Gateway runs on, and inside a container that is the container's own filesystem. Agents, Skills & MCP and agent monitoring therefore stay empty there, and the pages say so rather than pretending nothing is installed. Everything that does not depend on the host works normally: Providers, LLM Records and the reverse-proxy WAF.

So run the one-command install above on the machine whose agents you want to watch, and use a container when Gateway is only a model endpoint or a reverse proxy for other machines.

No image is published, so the compose file builds one from a checkout of this repository:

docker compose up -d

Podman reads the same file:

podman compose up -d

Either way the UI is on http://localhost:17000, the SQLite database lives in a named volume that survives down, and conf/app.conf is mounted from the repository, so the settings it seeds can be edited before the first start without rebuilding the image.

To serve the WAF proxy from a container, turn the reverse proxy on on the Settings page and publish its ports too, by adding them next to 17000:17000 in docker-compose.yml:

    ports:
      - "17000:17000"
      - "8080:80"
      - "8443:443"

Configuration

Everything is optional. Settings are changed on the Settings page of the web UI and stored in the database, so nothing has to be edited by hand and nothing has to be restarted. conf/app.conf, next to the executable, seeds them on the very first start and explains each one; the one-step install has no file beside it and seeds from the copy baked into the binary instead. Editing the file after that first start does nothing, except for the keys read before the database is open: httpport, driverName, dataSourceName, dbName and redisEndpoint. The settings people actually change:

Setting Default What it does
httpport 17000 Port of the web UI and the REST API
driverName / dataSourceName sqlite / ./data/casbin-gateway.db Where data is stored
gatewayEnabled false Turns the reverse-proxy WAF on
gatewayHttpPort / gatewayHttpsPort 80 / 443 Ports the proxy listens on
llmRecordMode off How much of each relayed LLM request is kept
apiKeyEncryptionKey empty Encrypts provider API keys at rest (AES-256-GCM)
casdoorEndpoint empty Switches sign-in over to Casdoor SSO

Gateway prints what it is actually doing when it starts, so the result can be checked instead of the file:

+----------------------------------------------------------------------------+
| Casbin Gateway                                                              |
+----------------+-----------------------------------------------------------+
| Management UI  | http://localhost:17000                                     |
| Settings       | Settings page, seeded from conf/app.conf                   |
| Web UI files   | web/build                                                  |
| Reverse proxy  | enabled                                                    |
| Gateway HTTP   | :8080                                                      |
| Gateway HTTPS  | :8443                                                      |
| Database       | sqlite, file "./data/casbin-gateway.db" (connected)        |
| Sign-in        | built-in user table, Casdoor is not configured             |
| App dir        | ./data/apps                                                |
+----------------+-----------------------------------------------------------+

If a port is taken, Gateway says which process holds it and stops, rather than starting half-configured.

Recording prompts

Nothing about a relayed request is stored until you ask for it, because a prompt can carry anything that was pasted into it. Record metadata and Record metadata and bodies, the buttons on the LLM Records page, turn it on for the next request; the Settings page holds the same choice and the limits around it, seeded from:

; "off" keeps nothing, "metadata" records who called which model with which
; outcome, "full" also stores the request body — which is what LLM Records needs
; to show prompts, messages and tool schemas.
llmRecordMode = "full"
llmRecordRetentionDays = 30
llmRecordMaxRecords = 10000
llmRecordMaxPayloadBytes = 1048576

Bodies are sanitized before they are stored: anything that looks like a credential is replaced, and the number of replacements is shown with the record. Request headers, which is where the inbound API key is, never reach a record at all. A body over llmRecordMaxPayloadBytes keeps its structure and loses only its longest strings, so a large conversation is still listed message by message.

The cost next to each record uses built-in list prices, which vendors change and resellers do not follow. Point llmPricingFile at a JSON file of your own rates to correct them.

Turning the WAF proxy on

The reverse proxy is off by default, so installing Gateway does not take over ports 80 and 443. To use it:

  1. Advanced → Sites → Add. Set Domain to the hostname clients will use (test.example.com), Host and Port to where the traffic goes (127.0.0.1 and 8000), and Mode to HTTPHTTPS Only, the default, redirects plain HTTP away before it reaches the backend.
  2. Flip Reverse proxy, the switch at the top of the Sites page. It takes effect at once and is remembered across restarts. Ports 80 and 443 need root on Linux and macOS, so for a first try set the gateway HTTP port to 8080 on the Settings page.
  3. Start anything on the backend port, e.g. python -m http.server 8000, then ask for the site by Host header — the gateway routes on it, so no DNS or hosts entry is needed:
curl -H "Host: test.example.com" http://127.0.0.1:8080/

You should get your backend's response. A site not found for host reply means the request reached Gateway but no site matches that Host value.

Connecting Casdoor

Casdoor is optional and takes over member management. Create an organization and an application for Gateway in a Casdoor instance, then fill in the five fields of Settings → Sign-in. Sign-in redirects to Casdoor as soon as casdoorEndpoint is set, which also enables OAuth logins, health-check alerts, the CAPTCHA rule action, per-site SSO and cloud file storage.

Development

Prerequisites

Go 1.20+, and Node.js with Yarn.

Run from source

The backend serves the compiled frontend out of web/build, so build it once first:

cd web && yarn install && yarn build
go run main.go

Then open http://localhost:17000 and sign in as admin with the password 123, same as an installed Gateway. The SQLite database is created on first start; there is no database server to install.

Frontend development

cd web && yarn dev

That serves the UI on http://localhost:16002 with hot reload and proxies API calls to the backend on port 17000, so both have to be running.

Using MySQL instead of SQLite

XORM is used, so every database it supports works. Point Gateway at your server and it creates dbName on first start if it does not exist:

driverName = mysql
dataSourceName = root:123@tcp(localhost:3306)/
dbName = casbin_gateway

Building a single binary

Gateway normally reads three things from disk: conf/app.conf, the compiled UI in web/build, and the IP location database ip/17monipdb.dat. The embed build tag bakes all three into the executable, which is what the install scripts ship:

cd web && yarn install && yarn build
go build -tags embed -o casbin-gateway .

Build the frontend first — everything under web/build goes into the binary, so go build -tags embed fails to compile while that directory is missing.

Files on disk always win over the embedded copies, so a single binary can still be configured and developed against without rebuilding it:

Embedded asset Overridden by
conf/app.conf conf/app.conf in the working directory, or next to the executable
web/build web/build/index.html in the working directory, which then serves the whole UI
ip/17monipdb.dat ip/17monipdb.dat in the working directory

The startup summary reports which source each one came from.

Where the data goes

Being self-contained is about startup, not about staying read-only. A running Gateway writes ./data (the SQLite database, deployed apps, agent patch state), ./logs and ./tmp relative to its working directory — which is why the installed casbin-gateway command is a wrapper that always starts it in its install directory. Running the executable directly from somewhere else gives you a second, empty installation there.

Architecture

Casbin Gateway contains 2 parts:

Name Description Language Source code
Frontend Web frontend UI for Casbin Gateway TypeScript + React + shadcn/ui https://github.com/apache/casbin-gateway/tree/master/web
Backend RESTful API backend for Casbin Gateway Golang + Beego + XORM https://github.com/apache/casbin-gateway

Online demo

https://ai.casbin.com

Documentation

https://caswaf.org

Contribute

If you have any questions, open an issue, or start a pull request directly — though we recommend opening an issue first to talk it through with the community.

License

Apache-2.0

Releases

Packages

Used by

Contributors

Languages