Skip to content

Repository files navigation

SluiceBase

Frontend Coverage

SluiceBase is a self-hosted database query gateway. It gives a team controlled, auditable access to databases — secured by OIDC authentication, per-user permissions, and an optional approval workflow for write operations.

Features

  • OIDC authentication — integrates with any OIDC provider (Keycloak, Auth0, Entra ID, etc.)
  • Permission model — assign read/write permissions per user and database
  • Write approval workflow — write requests require approval before execution
  • Query history — all queries are logged with results
  • Schema browser — explore table schemas directly in the UI
  • Customisable branding — app name, colour, logo, and favicon configurable at runtime

Architecture

A single Docker container runs the .NET 10 API which also serves the React frontend. The only external dependencies at runtime are a PostgreSQL database (metadata store) and an OIDC provider.

Browser → SluiceBase (React SPA + .NET 10 API) → PostgreSQL (metadata)
                                                 → Target databases
                                                 → OIDC provider

Quick start

Prerequisites

  • Docker
  • PostgreSQL 16+ (metadata store)
  • An OIDC provider with a confidential client configured (see OIDC setup)

Docker Compose

services:
  postgres:
    image: postgres:17-alpine
    environment:
      POSTGRES_USER: sluicebase
      POSTGRES_PASSWORD: changeme
      POSTGRES_DB: sluicebase
    volumes:
      - postgres-data:/var/lib/postgresql/data

  app:
    image: ghcr.io/yeongjonglim/sluice-base:latest
    ports:
      - "8080:8080"
    environment:
      ConnectionStrings__Metadata: "Host=postgres;Database=sluicebase;Username=sluicebase;Password=changeme"
      Oidc__Authority: "https://your-keycloak/realms/your-realm"
      Oidc__ClientId: "sluicebase"
      Oidc__ClientSecret: "your-client-secret"
      Permissions__Bootstrap__Admins__0: "admin@your-company.com"
    depends_on:
      - postgres

volumes:
  postgres-data:

Run the container directly

docker run -p 8080:8080 \
  -e ConnectionStrings__Metadata="Host=...;Database=sluicebase;Username=...;Password=..." \
  -e Oidc__Authority="https://your-keycloak/realms/your-realm" \
  -e Oidc__ClientId="sluicebase" \
  -e Oidc__ClientSecret="your-client-secret" \
  ghcr.io/yeongjonglim/sluice-base:latest

The app is available at http://localhost:8080.

HTTPS: deploy behind a reverse proxy (nginx, Caddy, Traefik) that terminates TLS. The container listens on HTTP only.

Environment variables

Variable Required Default Description
ConnectionStrings__Metadata ✓ — PostgreSQL connection string for the SluiceBase metadata database
Oidc__Authority ✓ — OIDC authority URL (e.g. https://keycloak/realms/myrealm)
Oidc__ClientId ✓ — OIDC client ID
Oidc__ClientSecret ✓ — OIDC client secret
Migrations__AutoApply true Apply pending DB migrations on startup
Permissions__Bootstrap__Admins__0 — Email of the first admin (granted full permissions on first login)
Branding__AppName SluiceBase Application name shown in the UI
Branding__PrimaryColor teal Mantine colour — see supported values
Branding__LogoUrl — URL to a custom logo image — see using local files
Branding__FaviconUrl — URL to a custom favicon — see using local files
Query__TimeoutSeconds 30 Maximum query execution time in seconds
Mcp__Enabled true Enable the MCP server and its OAuth endpoints (see Connecting AI tools)
Mcp__ServerName sluicebase Client alias shown in connect snippets (letters, digits, -, _; falls back to sluicebase if invalid)
Mcp__AccessTokenMinutes 60 Lifetime of an MCP access token in minutes
Mcp__RefreshTokenDays 30 Lifetime of an MCP refresh token in days
Mcp__AuthCodeSeconds 120 Lifetime of an MCP OAuth authorization code in seconds

Branding colours

Branding__PrimaryColor accepts any Mantine built-in colour name:

dark gray red pink grape violet indigo blue cyan teal green lime yellow orange

Using local branding files

Mount a directory into /app/wwwroot/branding/ inside the container and set LogoUrl/FaviconUrl to the corresponding relative paths. The files are served natively as static assets.

# docker-compose.yml
services:
  app:
    image: ghcr.io/yeongjonglim/sluice-base:latest
    volumes:
      - ./branding:/app/wwwroot/branding:ro
    environment:
      - Branding__LogoUrl=/branding/logo.png
      - Branding__FaviconUrl=/branding/favicon.ico

Place logo.png and favicon.ico in a local ./branding/ directory. Both LogoUrl and FaviconUrl also accept remote http(s):// URLs if the assets are hosted externally — in that case no volume mount is needed.

Database migrations

Migrations are applied automatically on startup by default. Set Migrations__AutoApply=false to disable this behaviour.

To apply migrations manually using the .NET CLI:

dotnet ef database update \
  --project src/SluiceBase.Api \
  --connection "Host=...;Database=sluicebase;Username=...;Password=..."

OIDC setup

Register a confidential OIDC client with these settings:

Setting Value
Client type Confidential (authorization code + PKCE)
Redirect URI https://your-domain/signin-oidc
Post-logout redirect URI https://your-domain/signout-callback-oidc
Scopes openid, profile, email

The ID token must include the sub, email, and name claims.

Keycloak: create a realm, add a client with the settings above, and point Oidc__Authority to https://your-keycloak/realms/your-realm.

Connecting AI tools (MCP)

SluiceBase exposes a Model Context Protocol server so AI coding tools (Claude Code, Codex) can list databases, browse schema, and run read-only queries as the authenticated user — reusing the same per-database permissions, sensitive-column screening, and audit logging as the web UI.

The MCP endpoint is served at https://your-domain/mcp (streamable HTTP). Authentication uses OAuth 2.1: SluiceBase acts as the authorization server and brokers login to your existing OIDC provider, so users sign in with the same login page they already use — no extra credentials, and tokens are user-scoped and revocable.

Signed-in users can also open Connect AI tools (the ✨ icon in the app header) for copy-ready, per-client setup snippets pre-filled with this instance's URL and server name.

Claude Code

claude mcp add --transport http sluicebase https://your-domain/mcp

Then in Claude Code, run /mcp, select sluicebase → Authenticate. A browser opens to your OIDC provider's login page; after signing in you're returned to the client and the tools become available.

Codex

Add a remote MCP server pointing at the same URL in your Codex MCP configuration:

[mcp_servers.sluicebase]
transport = "http"
url = "https://your-domain/mcp"

Codex runs the same OAuth flow on first use.

Tools

Tool Description
list_databases Lists the databases the user can query, grouped by server
get_schema Returns a database's table/column schema (sensitive columns flagged)
run_query Executes a read-only SQL query (subject to the user's query:execute permission, sensitive-column blocking, and audit logging — MCP-origin queries are tagged in the history)

Set Mcp__Enabled=false to disable the MCP server and its OAuth endpoints entirely.

Development setup

SluiceBase uses .NET Aspire to orchestrate all services locally, including Keycloak and PostgreSQL.

Prerequisites: .NET 10 SDK, Node.js 24, Docker

git clone https://github.com/yeongjonglim/sluice-base.git
cd sluice-base

dotnet run --project src/AppHost

The Aspire dashboard opens at https://localhost:15888. Once all services are healthy, use the Seed Server Registry command on the Metadata database resource to populate sample target databases.

The local stack runs behind a YARP gateway at https://localhost:5443 (Keycloak login, the SPA, and the API are all reached through it). Dev users are seeded in Keycloak: alice@example.com / dev (bootstrap admin) and bob@example.com / dev.

Testing the MCP server locally

The MCP endpoint is served through the gateway at https://localhost:5443/mcp.

  1. Trust the dev HTTPS certificate so an MCP client accepts the localhost TLS connection:

    dotnet dev-certs https --trust
  2. Start the stack (dotnet run --project src/AppHost) and run the Seed Server Registry command from the dashboard.

  3. Sign in to https://localhost:5443 once as alice@example.com / dev to bootstrap the admin user. Alice has server:manage, so list_databases works immediately. To exercise the permission path with a non-admin, sign in as bob@example.com and grant him query:execute on a database via the Access admin page.

  4. Connect a client:

    MCP Inspector (quickest way to drive the OAuth flow and call tools):

    NODE_TLS_REJECT_UNAUTHORIZED=0 npx @modelcontextprotocol/inspector

    Set Transport to Streamable HTTP, URL to https://localhost:5443/mcp, and connect. (NODE_TLS_REJECT_UNAUTHORIZED=0 is only needed to accept the local dev certificate.)

    Claude Code:

    claude mcp add --transport http sluicebase https://localhost:5443/mcp

    Then run /mcp, select sluicebase → Authenticate, and sign in via the Keycloak page.

  5. Smoke-test the OAuth discovery without a client (no auth required):

    curl -k https://localhost:5443/.well-known/oauth-protected-resource
    curl -k -i https://localhost:5443/mcp   # expect 401 + WWW-Authenticate: Bearer resource_metadata=...

The OAuth + tool round-trip is also covered by the integration tests:

dotnet test tests/IntegrationTests --filter "McpTokenServiceTests|OAuthFlowTests|McpToolsTests"

License

MIT

About

Self-hosted SQL console with OIDC login, controlled read/write paths, and an approval workflow.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages