Deployment

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

01

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.

02

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.

03

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.

terminal
git clone https://github.com/Yousefb92/askLenny.git
cd askLenny

Step 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.

terminal
cp .env.example .env
# Edit .env and set AI_API_KEY=your-key-here
.env
# .env  (never commit this file)
# Your AI provider API key - Gemini, Anthropic, or OpenAI
AI_API_KEY=your-api-key-here

Step 3. Edit python-backend/connectors.yaml to point at your databases and set the AI model. See the full reference below.

python-backend/connectors.yaml
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 host

Step 4. Build and start all three containers. The first build compiles the Rust engine - expect 2–5 minutes. Subsequent starts are instant.

terminal
docker compose up --build

# Or run in the background:
docker compose up --build -d

Open http://localhost once the containers are running.

The two config files

.envrepo root - never committed

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.

connectors.yamlpython-backend/

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 set base_url to route to any OpenAI-compatible endpoint.

connectors.yaml reference

Connector fields

FieldRequiredNotes
idYesUnique identifier for this connector
display_nameYesHuman-readable name shown in the UI
engineYesSee supported engines below
serverYesUse host.docker.internal for local DBs
portYesTCP port
usernameYesRead-only DB account
passwordYesPlain text - file is never committed
databaseYesTarget database name
schemasNoList of schemas to include. Omit to scan all.

Supported database engines

Databaseengine valueDefault port
SQL Servermssql1433
Azure SQLmssql1433
PostgreSQLpostgresql5432
MySQLmysql3306
python-backend/connectors.yaml
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 host

AI 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

Start (first time - builds images)docker compose up --build
Start in backgrounddocker compose up --build -d
Stop containersdocker compose down
View live logsdocker compose logs -f
Rebuild after code changesdocker compose up --build
Check container statusdocker compose ps

First run walkthrough

1

Open the dashboard

Navigate to http://localhost. The Schema Discovery view loads automatically.

2

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.

3

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.

4

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.

5

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.