LibreDB Studio libredb.org ONLINE • PostgreSQL
RUN
docker_compose.sql
SELECT variable, default, description FROM env_vars;
21 rows | 3 cols 6ms

Docker Compose example

One command to self-host LibreDB Studio — pulls the published ghcr.io image, with every environment variable.

Quick start

curl -O https://libredb.org/docker-compose.example.yml
mv docker-compose.example.yml docker-compose.yml
# set JWT_SECRET, ADMIN_PASSWORD and USER_PASSWORD in .env
docker compose up -d
# open http://localhost:3000

That's it — LibreDB Studio is now running at http://localhost:3000. Log in with the admin credentials from your .env file.

The full docker-compose.example.yml

# =============================================================================
# LibreDB Studio — Ready-to-use Docker Compose
# =============================================================================
# Pulls the published image (ghcr.io/libredb/libredb-studio:latest) — no source
# build required. Works on any Docker host and PaaS that consumes a plain
# docker-compose.yml (Dokploy, Coolify, Portainer, etc.).
#
# Quick start:
#   1. cp docker-compose.example.yml docker-compose.yml
#   2. cp .env.example .env        # then set at least JWT_SECRET / passwords
#   3. docker compose up -d
#   4. open http://localhost:3000
#
# Every supported environment variable is listed below. Commonly-used ones are
# active; less-frequently-used ones are shown commented out — uncomment as needed.
# Secrets are read from the .env file via ${VAR} interpolation and are never
# hardcoded in this file.
# =============================================================================

services:
  libredb-studio:
    image: ghcr.io/libredb/libredb-studio:latest
    container_name: libredb-studio
    restart: unless-stopped
    ports:
      - "3000:3000"
    # Uncomment if you enable the bundled PostgreSQL service below:
    # depends_on:
    #   libredb-postgres:
    #     condition: service_healthy
    environment:
      # -----------------------------------------------------------------------
      # AUTHENTICATION (required)
      # -----------------------------------------------------------------------
      ADMIN_EMAIL: ${ADMIN_EMAIL:[email protected]}        # admin: full access + maintenance tools
      ADMIN_PASSWORD: ${ADMIN_PASSWORD:?set ADMIN_PASSWORD in .env}
      USER_EMAIL: ${USER_EMAIL:[email protected]}           # user: query execution only
      USER_PASSWORD: ${USER_PASSWORD:?set USER_PASSWORD in .env}
      # JWT signing secret — min 32 chars. Generate: openssl rand -base64 32
      JWT_SECRET: ${JWT_SECRET:?set JWT_SECRET in .env (min 32 chars)}

      # Auth provider: "local" (default, email/password) or "oidc" (SSO)
      NEXT_PUBLIC_AUTH_PROVIDER: ${NEXT_PUBLIC_AUTH_PROVIDER:-local}

      # -----------------------------------------------------------------------
      # OIDC SSO  (only when NEXT_PUBLIC_AUTH_PROVIDER=oidc)
      # Auth0 / Keycloak / Okta / Azure AD / Zitadel
      # -----------------------------------------------------------------------
      # OIDC_ISSUER: ${OIDC_ISSUER}                # must serve /.well-known/openid-configuration
      # OIDC_CLIENT_ID: ${OIDC_CLIENT_ID}
      # OIDC_CLIENT_SECRET: ${OIDC_CLIENT_SECRET}
      # OIDC_SCOPE: ${OIDC_SCOPE:-openid profile email}
      # OIDC_ROLE_CLAIM: ${OIDC_ROLE_CLAIM:-}      # e.g. realm_access.roles (Keycloak), groups (Okta)
      # OIDC_ADMIN_ROLES: ${OIDC_ADMIN_ROLES:-admin}

      # -----------------------------------------------------------------------
      # STORAGE — where connections/config are persisted (server-side)
      #   "local"    (default) browser localStorage, zero config
      #   "sqlite"   server file, single-node persistent (uncomment volume below)
      #   "postgres" multi-node persistent (uncomment the postgres service below)
      # -----------------------------------------------------------------------
      STORAGE_PROVIDER: ${STORAGE_PROVIDER:-local}
      # STORAGE_SQLITE_PATH: ${STORAGE_SQLITE_PATH:-/app/data/libredb-storage.db}
      # STORAGE_POSTGRES_URL: ${STORAGE_POSTGRES_URL:-postgresql://postgres:postgres@libredb-postgres:5432/libredb_storage?sslmode=disable}

      # -----------------------------------------------------------------------
      # AI / LLM  (optional) — provider: gemini | openai | ollama | custom
      # -----------------------------------------------------------------------
      # LLM_PROVIDER: ${LLM_PROVIDER:-gemini}
      # LLM_API_KEY: ${LLM_API_KEY}                # required for gemini/openai
      # LLM_MODEL: ${LLM_MODEL:-gemini-2.5-flash}
      # LLM_API_URL: ${LLM_API_URL}                # ollama/custom only, e.g. http://host:11434/v1

      # -----------------------------------------------------------------------
      # SEED CONNECTIONS (optional) — pre-configure databases on boot.
      # Uncomment the seed volume mount below, then provide seed-connections.yaml.
      # Credentials referenced in that file via ${VAR} are read from this .env.
      # -----------------------------------------------------------------------
      # SEED_CONFIG_PATH: /app/config/seed-connections.yaml
      # SEED_CACHE_TTL_MS: ${SEED_CACHE_TTL_MS:-60000}

    # volumes:
    #   # SQLite storage persistence (STORAGE_PROVIDER=sqlite):
    #   - libredb-data:/app/data
    #   # Seed connections file (read-only):
    #   - ./seed-connections.yaml:/app/config/seed-connections.yaml:ro

    # Image runs as node:24.16.0-trixie-slim (no curl/wget) — use Node's built-in fetch.
    healthcheck:
      test: ["CMD", "node", "-e", "fetch('http://localhost:3000/api/db/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s

  # ---------------------------------------------------------------------------
  # Optional: PostgreSQL backend for STORAGE_PROVIDER=postgres
  # To enable: uncomment this service, the STORAGE_POSTGRES_URL env above,
  # the depends_on block above, and the pgdata volume below.
  # ---------------------------------------------------------------------------
  # libredb-postgres:
  #   image: postgres:18
  #   container_name: libredb-postgres
  #   restart: unless-stopped
  #   environment:
  #     POSTGRES_USER: postgres
  #     POSTGRES_PASSWORD: postgres
  #     POSTGRES_DB: libredb_storage
  #   volumes:
  #     - pgdata:/var/lib/postgresql/data
  #   healthcheck:
  #     test: ["CMD-SHELL", "pg_isready -U postgres"]
  #     interval: 10s
  #     timeout: 5s
  #     retries: 5

# volumes:
#   libredb-data:   # SQLite storage persistence
#   pgdata:         # PostgreSQL storage persistence

Environment variable reference

Every supported variable, grouped as in the file. Secrets are read from your .env file via ${VAR} interpolation — never hardcoded in the compose file.

Authentication (required)

Variable Default Description
ADMIN_EMAIL [email protected] Admin login — full access plus maintenance tools.
ADMIN_PASSWORD — (required) Admin password. Set this in your .env file.
USER_EMAIL [email protected] Standard user login — query execution only.
USER_PASSWORD — (required) User password. Set this in your .env file.
JWT_SECRET — (required) JWT signing secret, min 32 chars. Generate: openssl rand -base64 32
NEXT_PUBLIC_AUTH_PROVIDER local Auth mode: "local" (email/password) or "oidc" (SSO).

OIDC SSO (when NEXT_PUBLIC_AUTH_PROVIDER=oidc)

Variable Default Description
OIDC_ISSUER Issuer URL serving /.well-known/openid-configuration.
OIDC_CLIENT_ID OIDC client ID from your identity provider.
OIDC_CLIENT_SECRET OIDC client secret.
OIDC_SCOPE openid profile email Requested OIDC scopes.
OIDC_ROLE_CLAIM Claim holding roles, e.g. realm_access.roles (Keycloak), groups (Okta).
OIDC_ADMIN_ROLES admin Roles mapped to admin access. Works with Auth0, Keycloak, Okta, Azure AD, Zitadel.

Storage — where connections & config persist

Variable Default Description
STORAGE_PROVIDER local "local" (browser localStorage, zero config), "sqlite" (single-node file), or "postgres" (multi-node).
STORAGE_SQLITE_PATH /app/data/libredb-storage.db SQLite file path. Mount a volume to persist it.
STORAGE_POSTGRES_URL postgresql://…@libredb-postgres:5432/libredb_storage PostgreSQL connection string for multi-node persistence.

AI / LLM (optional)

Variable Default Description
LLM_PROVIDER gemini Provider: gemini | openai | ollama | custom.
LLM_API_KEY API key — required for gemini/openai.
LLM_MODEL gemini-2.5-flash Model name to use for NL2SQL.
LLM_API_URL Base URL for ollama/custom, e.g. http://host:11434/v1

Seed connections (optional)

Variable Default Description
SEED_CONFIG_PATH /app/config/seed-connections.yaml Pre-configure databases on boot from a mounted YAML file.
SEED_CACHE_TTL_MS 60000 Cache TTL for seeded connections, in milliseconds.