| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
A fully customizable data access governance layer.
BetweenRows is a SQL-aware proxy that enforces fine-grained access policies — masking, filtering, and blocking — in real-time. Works with PostgreSQL today; warehouses and lakehouses on the roadmap. Free to self-host. Source-available.
📖 Full documentation: docs.betweenrows.dev
Enforcement & audit
Fully customizable
Free and source-available
Built in Rust on DataFusion — low overhead, memory-safe, production-grade query rewriting.
BetweenRows ships as a single binary with two planes:
Data plane (port 5434) — PostgreSQL wire protocol proxy. Connect with any PostgreSQL client (psql, TablePlus, DBeaver, your app). Policies are enforced transparently on every query.
Management plane (port 5435) — Admin UI and REST API for managing users, data sources, roles, policies, and audit logs. Only admin users have access.
The two planes are independent — being an admin does not grant data access. All data access must be explicitly granted via data source assignments and policies.
psql / app
↓ PostgreSQL wire protocol (port 5434)
BetweenRows
├─ Authenticates user
├─ Checks data source access
├─ Applies policies:
│ row_filter — inject WHERE clauses
│ column_mask — replace column values
│ column_deny — hide columns
│ table_deny — hide tables
│ column_allow — allowlist columns
└─ Executes via DataFusion
↓
Upstream PostgreSQL
docker run -d \
-e BR_ADMIN_USER=admin \
-e BR_ADMIN_PASSWORD=changeme \
-p 5434:5434 -p 5435:5435 \
-v betweenrows_data:/data \
ghcr.io/getbetweenrows/betweenrows:latest # demo only — pin a specific tag for anything real| Variable | Required | Default | Description |
|---|---|---|---|
| BR_ADMIN_USER | No | admin | Username for the initial admin account. Change it now if you prefer a different name — the username cannot be changed after creation. You can always create additional admin users through the UI later. |
| BR_ADMIN_PASSWORD | Yes | — | Password for the initial admin account. Only used on first boot. You can change the password later through the UI. |
| -p 5434:5434 | Yes | — | SQL proxy port. Connect your SQL clients here. |
| -p 5435:5435 | Yes | — | Admin UI and REST API port. |
| -v betweenrows_data:/data | Yes | — | Persistent volume. Stores the SQLite database (users, data sources, policies, audit logs) and auto-generated encryption/JWT keys when BR_ENCRYPTION_KEY and BR_ADMIN_JWT_SECRET are not set. Do not omit — without it, all data and keys are lost when the container restarts. |
Change these values to your preference before the first run. See Configuration for all available options.
Open http://localhost:5435 and log in with your admin credentials.
psql "postgresql://alice:secret@localhost:5434/my-datasource"| Env var | Required | Default | Description |
|---|---|---|---|
| BR_ADMIN_PASSWORD | Yes (first boot) | — | Password for the initial admin account. Must be set when no users exist in DB. |
| BR_ADMIN_USER | No | admin | Username for the initial admin account. Only used on first boot. |
| BR_ENCRYPTION_KEY | No | (auto-persisted) | 64-char hex — AES-256-GCM key for secrets at rest. If unset, auto-generated and saved to /data/.betweenrows/encryption_key. Set explicitly in prod. If switching from auto-generated to explicit, copy the value from /data/.betweenrows/encryption_key — using a different key makes existing secrets unreadable. |
| BR_ADMIN_JWT_SECRET | No | (auto-persisted) | Any non-empty string — HMAC-SHA256 signing key for admin JWTs. If unset, auto-generated and saved to /data/.betweenrows/jwt_secret. Set explicitly in prod. |
| BR_ADMIN_JWT_EXPIRY_HOURS | No | 24 | JWT lifetime in hours. |
| BR_ADMIN_DATABASE_URL | No | sqlite://proxy_admin.db?mode=rwc | SeaORM connection URL (use postgres://… for shared backend). |
| BR_PROXY_BIND_ADDR | No | 127.0.0.1:5434 | Proxy listen address. Docker image defaults to 0.0.0.0:5434. |
| BR_ADMIN_BIND_ADDR | No | 127.0.0.1:5435 | Admin REST API listen address. Docker image defaults to 0.0.0.0:5435. |
| BR_IDLE_TIMEOUT_SECS | No | 900 (15 min) | Close idle proxy connections after this many seconds. Set to 0 to disable. |
| BR_CORS_ALLOWED_ORIGINS | No | (empty, same-origin only) | Comma-separated list of allowed CORS origins for the Admin API. |
| RUST_LOG | No | info | Log filter (standard Rust/tracing convention). |
BetweenRows speaks the PostgreSQL wire protocol — connect with any PostgreSQL client using the datasource name as the database:
psql "postgresql://<user>:<password>@127.0.0.1:5434/<datasource-name>"Tested with psql and TablePlus. Any tool that supports PostgreSQL or ODBC with a PostgreSQL driver should work — including DBeaver, DataGrip, BI tools, and application ORMs.
Note: Some SQL clients send additional metadata queries (e.g., for autocompletion or schema browsing) that BetweenRows may not support yet. If your client fails to connect, please open an issue.
BetweenRows supports five policy types:
| Type | What it does |
|---|---|
| row_filter | Injects a WHERE clause to filter rows (e.g., tenant = {user.tenant}) |
| column_mask | Replaces column values with an expression (e.g., '***@' || split_part(email, '@', 2)) |
| column_allow | Permits access to specific columns (required in policy_required mode) |
| column_deny | Hides columns from the user's schema entirely |
| table_deny | Hides entire tables from the user's schema |
Key concepts:
See docs-site/docs/concepts/policy-model.md for the full guide.
Before a data source is queryable through the proxy, its catalog must be saved. The UI wizard guides through four steps:
The catalog is an allowlist — the proxy can never expose tables or columns not explicitly saved. To detect schema drift after upstream changes, use "Sync Catalog" from the data source page.
BetweenRows includes a full REST API at http://localhost:5435/api/v1 for managing users, data sources, roles, policies, catalog discovery, and audit logs. All endpoints require JWT authentication (POST /auth/login to obtain a token).
Everything you can do in the admin UI can also be done via the API — useful for scripting, CI/CD integration, and automation.
Create users without the UI — useful for scripting and automation. If you're locked out of the admin UI, use --admin to create a new admin user to regain access. You can then change passwords through the UI. A forgot/reset password feature is on the roadmap:
# Docker
docker exec -it <container> proxy user create --username alice --password secret
docker exec -it <container> proxy user create --username rescue --password secret --admin
# From source
cargo run -p proxy -- user create --username alice --password secretSee docs-site/docs/about/roadmap.md for planned features including shadow mode, governance workflows, and more.
See CONTRIBUTING.md for architecture details, build instructions, and development setup.
| Back | FazBrowse Home | New Git URL |