Apache 2.0 · self-hosted · bring your own model

DeepSQL documentation

Everything you need to run the database agent for Postgres and MySQL inside your own infrastructure — in about fifteen minutes.

Introduction

DeepSQL is an open-source database agent. Point it at PostgreSQL or MySQL and ask questions in plain English: schema exploration, query generation, slow query analysis, index recommendations, generated dashboards.

You bring the model. DeepSQL ships with no model provider of its own and no vendor account to sign up for. Point it at OpenAI, Azure OpenAI, Anthropic, a LiteLLM proxy, or a model running on your own hardware. Everything else runs in your environment: database credentials are encrypted in a local vault, and nothing leaves the machines you control except the prompts you send to the endpoint you chose.

Source: github.com/DeepSQLAI/deepsql. Architecture and design rationale live in the white paper.

Set up with an AI agent

These docs are published in a machine-readable form so Claude, Codex, Cursor or any other coding agent can install DeepSQL end to end for you. Give the agent your model endpoint and API key, paste the prompt below, and let it run.

Read https://deepsql.ai/llms-full.txt and set up DeepSQL on this machine
end to end, following it exactly. Use my model provider:
  endpoint: <your endpoint>
  model:    <your model>
  API key:  <your key>
Run every verification step and stop and ask me if any of them fails.
URLWhat it is
/llms.txtShort index of every page an agent should know about.
/llms-full.txtThe full runbook: preflight, .env, install, verification commands, troubleshooting.

The runbook is written as ordered steps with copy-runnable commands, explicit verification after each stage, and a troubleshooting table keyed to the actual failure messages — so an agent can self-correct instead of guessing. The only things it will ask you for are the model key/endpoint, the embedding key/endpoint, and the first admin account.

Once the stack is up, connect your coding agent to the running instance over MCP so it can query schemas and validate migrations against the brain.

Requirements

  • Docker Engine with Compose v2 and buildx — verify with docker compose version and docker buildx version. Compose delegates builds to buildx and refuses anything older than 0.17.0.
  • git, curl and openssl
  • ~4 GB of memory available to Docker. The backend JVM is configured with a 3 GB max heap; a smaller allocation fails in ways that look unrelated.
  • An API key for a model provider — you need this before you start, not after.

On a fresh server, one command does all of that:

sudo ./scripts/self-host/bootstrap-server.sh

It handles Debian/Ubuntu and Amazon Linux 2023 / RHEL, installs whatever is missing, and verifies the result before exiting. Worth running even where Docker is already present: a stock dnf install docker on Amazon Linux 2023 ships neither the Compose plugin nor a buildx new enough to build.

Install

There are no prebuilt images and no container registry. Compose builds the backend and frontend from your checkout.

git clone https://github.com/DeepSQLAI/deepsql.git
cd deepsql
cp .env.example .env

Set your model in .env (see Models), then run the installer:

./scripts/self-host/install.sh

The installer generates your JWT secret, the credential-vault encryption key, the vault DB password and the DeepSQL Agent provision secret; prompts for the first admin account; builds the backend, frontend and Agent images; starts the stack; and verifies pgvector is live. The Agent tab and AI dashboard generation are served by the deepsql-agent Compose service — no host-side agent install is required.

The first build takes several minutes — it compiles the Spring Boot backend with Maven inside the container and bundles the frontend with Vite. It has not hung. Later builds reuse the Docker layer cache.

Driving Compose yourself

.env.example ships two values empty on purpose — they are validated secrets, and the backend refuses to start without them.

printf 'SECURITY_JWT_SECRET=%s\n' "$(openssl rand -base64 64 | tr -d '\n')" >> .env
printf 'ENCRYPTION_KEY=%s\n'      "$(openssl rand -base64 32)"             >> .env

docker compose up -d --build

That builds and starts everything but leaves you unable to log in: there is no seeded account, self-service signup is disabled, and the wizard's POST /setup/initialize is disabled. The first user is created through a localhost-only bootstrap endpoint — set SECURITY_ADMIN_BOOTSTRAP_ENABLED=true and ADMIN_BOOTSTRAP_SECRET in .env and call it yourself. install.sh does exactly this, then turns the flag back off.

First login

Open http://localhost:3000 and log in with the admin email and password you entered during install. From there: add a database connection, teach the brain your business context, and point the agent at your slow query logs.

Back up ENCRYPTION_KEY from .env now. It encrypts every database credential you store. Lose it and you re-enter all of them — there is no recovery path.

Models

Open .env and set the chat group. Whatever you pick, the provider id stays openai — there is one provider implementation and it speaks OpenAI, Azure OpenAI, and every OpenAI-compatible server. It dispatches on the shape of your endpoint, not on a name you configure.

VariableWhat to put in it
DEEPSQL_CHAT_PROVIDERalways openai, for every provider below
DEEPSQL_CHAT_API_KEYYour key. For a local model, any non-empty string.
DEEPSQL_CHAT_ENDPOINTThe base URL. No working default — set it explicitly.
DEEPSQL_CHAT_MODELModel name, or your Azure deployment name

OpenAI

DEEPSQL_CHAT_PROVIDER=openai
DEEPSQL_CHAT_API_KEY=sk-your-key
DEEPSQL_CHAT_ENDPOINT=https://api.openai.com/v1
DEEPSQL_CHAT_MODEL=gpt-4o

Azure OpenAI

An .azure.com or .azure-api.net endpoint switches authentication to the api-key header automatically. _MODEL is your deployment name.

DEEPSQL_CHAT_PROVIDER=openai
DEEPSQL_CHAT_API_KEY=your-azure-openai-key
DEEPSQL_CHAT_ENDPOINT=https://your-resource.cognitiveservices.azure.com/
DEEPSQL_CHAT_MODEL=your-deployment-name

Anthropic

Anthropic serves an OpenAI-compatible /v1/chat/completions, so it needs no gateway. It publishes no embeddings API, so pair it with another provider for embeddings.

DEEPSQL_CHAT_PROVIDER=openai
DEEPSQL_CHAT_API_KEY=sk-ant-your-key
DEEPSQL_CHAT_ENDPOINT=https://api.anthropic.com/v1
DEEPSQL_CHAT_MODEL=claude-haiku-4-5-20251001

Ollama, vLLM, LM Studio, TGI — your own hardware

Anything speaking the OpenAI wire format. No key is required, but the variable must be non-empty.

DEEPSQL_CHAT_PROVIDER=openai
DEEPSQL_CHAT_API_KEY=ollama
DEEPSQL_CHAT_ENDPOINT=http://host.docker.internal:11434/v1
DEEPSQL_CHAT_MODEL=llama3.1

LiteLLM proxy

DEEPSQL_CHAT_PROVIDER=openai
DEEPSQL_CHAT_API_KEY=sk-your-litellm-virtual-key
DEEPSQL_CHAT_ENDPOINT=http://litellm:4000/v1
DEEPSQL_CHAT_MODEL=your-alias

Name your alias carefully. _USE_RESPONSES_API defaults to auto, which decides from the model name rather than from what your endpoint implements. An alias beginning gpt-5, o1, o3, o4 or codex selects the Responses API. If your gateway does not serve /v1/responses, avoid those prefixes or set DEEPSQL_CHAT_USE_RESPONSES_API=false.

DEEPSQL_CHAT_PROVIDER gates the whole group: with it unset, no other DEEPSQL_CHAT_* variable is read. That is the most common reason a carefully filled-in .env appears to be ignored.

Embeddings

Configured independently of chat, so they can point at a different provider, key or endpoint — exactly what you need when your chat model has no embeddings API.

DEEPSQL_EMBEDDING_PROVIDER=openai
DEEPSQL_EMBEDDING_API_KEY=sk-your-key
DEEPSQL_EMBEDDING_ENDPOINT=https://api.openai.com/v1
DEEPSQL_EMBEDDING_MODEL=text-embedding-3-large

Skipping this is survivable — the app starts and retrieval falls back to keyword-only — but answer quality drops noticeably, so treat it as part of setup rather than an extra.

Your embedding model must produce 3072-dimension vectors. rag_documents.embedding is a single vector(3072) column shared by every connection, so text-embedding-3-small (1536) is rejected. Changing width means migrating the column.

Environment reference

Everything lives in .env, documented inline. The variables that matter most:

VariablePurpose
DEEPSQL_CHAT_PROVIDER, _API_KEY, _ENDPOINT, _MODELThe chat model. Required.
DEEPSQL_EMBEDDING_PROVIDER, _API_KEY, _ENDPOINT, _MODELEmbeddings for retrieval. Optional; without them retrieval is keyword-only.
DEEPSQL_CHAT_TEMPERATURE, _API_VERSION, _USE_RESPONSES_APIOptional chat tuning. _USE_RESPONSES_API is true / false / auto.
SECURITY_JWT_SECRETSigns session tokens. Generate with openssl rand -base64 64.
ENCRYPTION_KEYOr ENCRYPTION_KEYS + ENCRYPTION_KEY_ID. AES-GCM key(s) for the credential vault. The backend refuses to start without one.
DB_URL, DB_USERNAME, DB_PASSWORDThe vault database. Compose points these at its own postgres service.
SPRING_PROFILES_ACTIVEprod for self-hosting — hardened defaults.
SECURITY_AUTH_ENABLEDSet false only for local development.
SECURITY_ADMIN_BOOTSTRAP_ENABLED, ADMIN_BOOTSTRAP_SECRETGate the localhost-only first-admin endpoint.
CORS_ALLOWED_ORIGINSBrowser origins allowed to call the API.
VECTOR_STORE_TYPEpgvector (the self-hosting default) or azure.
EMBEDDING_FAIL_OPENWhether a failed embedding call degrades silently or raises.
SLACK_*, EMAIL_*Optional Slack bot and SMTP.

Ports

ServicePortOverride
Frontend3000DEEPSQL_FRONTEND_PORT
Backend8080DEEPSQL_BACKEND_PORT
Postgres5432DEEPSQL_POSTGRES_PORT
Valkey6379DEEPSQL_VALKEY_PORT

What it does

  • Answers BI questions. The agent loads your business context, resolves the schema, drafts and validates SQL, then executes it read-only — with every step you can inspect. The hand-written SQL editor is the only path that can mutate, and only for a confirming admin.
  • Fixes slow queries. Reads pg_stat_statements or the MySQL slow log, groups queries by fingerprint, ranks them by cost, and flags regressions against their baseline.
  • Index recommendations. Advises, and can apply them for you — CREATE INDEX CONCURRENTLY on PostgreSQL, so no table lock.
  • Watches your schema. Tracks what changed and what needs attention, so drift surfaces before it breaks a query or a dashboard.
  • A brain that knows your business. Teach it your metrics, rules and conventions once — MRR, active accounts, currency handling — and every query, dashboard and recommendation uses the same governed definitions.
  • Dashboards without the analyst backlog. An agent writes a single self-contained HTML document, rendered in a sandboxed iframe with no network access. It reads data only through a read-only query bridge back to the backend.
  • Postgres and MySQL, in your infra. One dialect registry, read-only execution, and SSH tunnelling to reach databases behind a bastion.

Demo database

To explore DeepSQL without connecting your own database:

./scripts/self-host/seed-demo-data.sh

This creates a demo_shop e-commerce database with 100 products, 500 customers and 5,000+ orders, intentionally suboptimal query patterns to trigger recommendations, pre-configured slow query analysis and index recommendations, sample saved queries in the SQL editor, and sample agent conversation history.

Alternatively set DEEPSQL_SEED_DEMO_DATA=1 in .env before running install.sh to seed automatically.

MCP server

mcp/ exposes 44 tools wrapping the backend API, so coding agents reuse the same orchestration, retrieval and guardrails instead of getting raw database credentials. SQL execution is read-only-enforced before it reaches the backend.

DEEPSQL_API_BASE_URL=http://localhost:8080/api/ \
DEEPSQL_AUTH_TOKEN=<your-deepsql-token> \
npm run mcp:phase1

It has no npm dependencies of its own — npm run mcp:phase1 is just node mcp/deepsql-phase1-server.js, so it runs straight from a fresh clone. See mcp/README.md for editor configuration and the full tool table.

CLI & Slack

Ask DeepSQL from anywhere: the web UI, your terminal, or a Slack channel. Over MCP (stdio), Claude Code, Cursor, Codex and Claude Desktop get the same capabilities as the built-in agent — governed definitions, read-only execution, schema guardrails.

The Slack bot is optional and configured with the SLACK_* variables in .env; once connected, anyone in the channel can ask business questions without the data leaving your infrastructure.

Operating the stack

./scripts/self-host/status.sh                    # compose ps + health probes
./scripts/self-host/smoke-test.sh                # end-to-end check against the vault DB
./scripts/self-host/seed-demo-data.sh            # seed demo e-commerce database
./scripts/self-host/uninstall.sh                 # stop and remove containers, keep data
./scripts/self-host/uninstall.sh --purge-data    # also drop the volumes

Upgrading:

git pull && docker compose up -d --build

Remote access (SSH tunnel)

If DeepSQL runs on a server you only reach through a bastion, forward the frontend port locally instead of exposing it to the internet.

ssh -N -L 3100:localhost:3000 -o ExitOnForwardFailure=yes <user>@<bastion-host>

If the target host is itself only reachable from inside the bastion's network, add a Host entry per leg in ~/.ssh/config and let ProxyJump chain them:

Host my-bastion
    HostName <bastion-ip-or-dns>
    User <bastion-user>
    IdentityFile ~/.ssh/<bastion-key>

Host deepsql
    HostName <target-host-ip-or-dns>
    Port <target-ssh-port>
    User <target-user>
    IdentityFile ~/.ssh/<target-key>
    ProxyJump my-bastion
    LocalForward 3100 localhost:3000
    ServerAliveInterval 30
    ExitOnForwardFailure yes
ssh -N deepsql

Then open http://localhost:3100. Use a non-3000 local port if something on your machine already binds 3000 — ExitOnForwardFailure=yes makes a port collision fail loudly instead of handing you a dead tunnel that looks connected.

Telemetry

The backend can report anonymous install and usage counters to PostHog. No project key ships with the repository, so the sink is a no-op unless you configure deepsql.telemetry.posthog-project-key yourself. DO_NOT_TRACK=1 or DEEPSQL_TELEMETRY_DISABLED=1 disables it outright, as does the admin toggle.

Development

Run the stateful dependencies in Docker — PostgreSQL needs the pgvector extension — and everything else natively for hot reload.

docker compose up -d postgres valkey    # requires .env to exist

cd backend && ./mvnw spring-boot:run    # http://localhost:8080/api
npm install && npm run dev              # http://localhost:3000

You need JDK 25 and Node 22. Maven comes from the wrapper (./mvnw). The backend needs the same environment as the container: at minimum DB_URL, DB_USERNAME, DB_PASSWORD, SECURITY_JWT_SECRET, ENCRYPTION_KEY and the DEEPSQL_CHAT_* group.

npm run lint                # eslint
npm run build               # production frontend bundle
cd backend && ./mvnw test   # backend test suite

Stack: Spring Boot 4 on Java 25 · React 19 + Vite · PostgreSQL with pgvector · Valkey for caching · nginx. Licensed under Apache 2.0.

Support

Stuck on an install, or want a second pair of eyes on a workload? Reach us: