Deploy askLenny
Clone the repo, fill in two config files, run one command. Everything - the Rust graph engine, Python app, and React frontend - starts inside Docker.
Prerequisites
Docker + Compose
Docker Engine 20.10+ or Docker Desktop. Docker Compose v2 is included in Docker Desktop and recent Engine installs. No Kubernetes or cloud account needed.
Database credentials
A read-only account that can query INFORMATION_SCHEMA and run SELECT. askLenny never issues DML - SELECT on system views and your tables is sufficient.
AI API key
A Google Gemini, Anthropic, or OpenAI API key. Or run Ollama locally for zero egress - see the AI provider section below.
Quick start
Four steps from zero to running.
Step 1. Clone the repository.
git clone https://github.com/Yousefb92/askLenny.git
cd askLennyStep 2. Create your .env file from the example and add your AI API key. This is the only secret that lives outside the config file.
cp .env.example .env
# Edit .env and set AI_API_KEY=your-key-here# .env (never commit this file)
# Your AI provider API key - Gemini, Anthropic, or OpenAI
AI_API_KEY=your-api-key-hereStep 3. Edit python-backend/connectors.yaml to point at your databases and set the AI model. See the full reference below.
connectors:
- id: "production_warehouse"
display_name: "Production Warehouse"
engine: "mssql"
server: "host.docker.internal" # use this to reach a DB on your host machine
# server: "10.0.1.55" # or a remote server IP / hostname
port: 1433
username: "asklenny_reader"
password: "your-db-password"
database: "Analytics"
# Optional: limit to specific schemas. Omit to scan all non-system schemas.
schemas:
- "Sales"
- "dbo"
ai_integration:
model_to_use: "gemini-2.0-flash-lite" # default - Google Gemini
# model_to_use: "claude-sonnet-4-5" # Anthropic Claude (no base_url needed)
# model_to_use: "gpt-4o" # OpenAI
# model_to_use: "llama3" # Ollama or any local model
# base_url: "http://host.docker.internal:11434/v1" # Ollama running on your hostStep 4. Build and start all three containers. The first build compiles the Rust engine - expect 2–5 minutes. Subsequent starts are instant.
docker compose up --build
# Or run in the background:
docker compose up --build -dOpen http://localhost once the containers are running.
The two config files
Holds secrets that must not appear in source control. Currently only one value is required:
AI_API_KEYYour Gemini, Anthropic, or OpenAI API key. Docker Compose reads this and injects it into the Python container at runtime.
This file is listed in .gitignore and will never be committed. Use .env.example as the template.
Everything else lives here - database connections, credentials, and AI model config. This file is bind-mounted into the Python container at runtime so you can edit it without rebuilding.
connectorsList of databases to connect to. Each entry has server, port, credentials, and optional schema filter.ai_integrationWhich AI model to use. Optionally setbase_urlto route to any OpenAI-compatible endpoint.
connectors.yaml reference
Connector fields
| Field | Required | Notes |
|---|---|---|
| id | Yes | Unique identifier for this connector |
| display_name | Yes | Human-readable name shown in the UI |
| engine | Yes | See supported engines below |
| server | Yes | Use host.docker.internal for local DBs |
| port | Yes | TCP port |
| username | Yes | Read-only DB account |
| password | Yes | Plain text - file is never committed |
| database | Yes | Target database name |
| schemas | No | List of schemas to include. Omit to scan all. |
Supported database engines
| Database | engine value | Default port |
|---|---|---|
| SQL Server | mssql | 1433 |
| Azure SQL | mssql | 1433 |
| PostgreSQL | postgresql | 5432 |
| MySQL | mysql | 3306 |
connectors:
- id: "production_warehouse"
display_name: "Production Warehouse"
engine: "mssql"
server: "host.docker.internal" # use this to reach a DB on your host machine
# server: "10.0.1.55" # or a remote server IP / hostname
port: 1433
username: "asklenny_reader"
password: "your-db-password"
database: "Analytics"
# Optional: limit to specific schemas. Omit to scan all non-system schemas.
schemas:
- "Sales"
- "dbo"
ai_integration:
model_to_use: "gemini-2.0-flash-lite" # default - Google Gemini
# model_to_use: "claude-sonnet-4-5" # Anthropic Claude (no base_url needed)
# model_to_use: "gpt-4o" # OpenAI
# model_to_use: "llama3" # Ollama or any local model
# base_url: "http://host.docker.internal:11434/v1" # Ollama running on your hostAI provider options
Google Gemini
Default- Set AI_API_KEY in .env
- model_to_use: "gemini-2.0-flash-lite"
- No base_url needed
Anthropic Claude
Cloud- Set AI_API_KEY in .env
- model_to_use: "claude-sonnet-4-5"
- No base_url needed
OpenAI
Cloud- Set AI_API_KEY in .env
- model_to_use: "gpt-4o"
- No base_url needed
Ollama (local)
Zero egress- No API key needed
- model_to_use: "llama3"
- base_url: "http://host.docker.internal:11434/v1"
Azure OpenAI
Enterprise- Set AI_API_KEY to your Azure key
- model_to_use: "your-deployment-name"
- base_url: "https://your-resource.openai.azure.com/..."
Any OpenAI-compatible
Flexible- Works with vLLM, LM Studio, LocalAI
- Set model_to_use and base_url
- Set AI_API_KEY if required
Useful Docker commands
docker compose up --builddocker compose up --build -ddocker compose downdocker compose logs -fdocker compose up --builddocker compose psFirst run walkthrough
Open the dashboard
Navigate to http://localhost. The Schema Discovery view loads automatically.
Review discovered schema
askLenny reads INFORMATION_SCHEMA from every configured connector. Tables and columns appear with a "New" badge - they exist in your database but are not yet in the graph.
Generate AI descriptions
Click the ✨ AI button on any table or column to generate a plain-English description. Accept it, edit it, or write your own.
Commit to graph
Click "Commit to Graph". Each node and its vector embedding is written to the Rust engine's persistent binary graph. This runs once per schema change.
Ask a question
Switch to the Query tab. Type a natural-language question. askLenny returns the generated SQL and executes it - the data table appears directly in the dashboard.
Common issues
Cannot connect to a local SQL Server
Use host.docker.internal as the server address in connectors.yaml - not 127.0.0.1. Inside Docker, 127.0.0.1 refers to the container itself.
SSL certificate error when connecting to SQL Server
ODBC Driver 18 enforces TLS by default. If your server uses a self-signed certificate, this is handled automatically by askLenny. If you still see SSL errors, verify your SQL Server has TCP/IP enabled in SQL Server Configuration Manager.
Dashboard loads but shows no connectors
Check that connectors.yaml exists at python-backend/connectors.yaml and is correctly formatted. Run: docker compose logs python-app to see any config parse errors.
AI enrichment returns an error
Check docker compose logs python-app for the error detail. Verify AI_API_KEY is set in your .env file at the repo root.
Graph data lost after restart
The docker-compose.yml uses a named Docker volume (lichen_data) to persist the .dat files. As long as you use docker compose down (not docker compose down -v), data is preserved across restarts.
Rust build takes a long time
Normal - Rust compilation is slow on first build (2–5 minutes). Subsequent builds reuse the layer cache and start in seconds unless Cargo.toml or Cargo.lock changed.