selfhost.directory

The index of self-hostable projects — ranked, categorized and served with live updates.
Own your data and stop giving it to big tech.

LibreDB Studio logo

Self-host LibreDB Studio

libredb-studio-0.1.108

A browser SQL IDE spanning 41 database engines

ReleaseOpen SourceMIT
docker run --name libredb-studio -p 3000:3000 -e ADMIN_EMAIL=admin@libredb.org ghcr.io/libredb/libredb-studio:latest
Updated2 hours ago
LanguageTypescript
Setup difficultyEasy
MobileResponsive
ThemeDark mode
Stars
1 299
Port
3000 (Web UI and API served by the Studio server)
Docker
ghcr.io/libredb/libredb-studio
Connection manager dialog listing the supported database engines with SSL/TLS and SSH tunnel optionsORM code generator screen producing model code from live table schemasAI data profiler showing per-column statistics

What is LibreDB Studio?

Should you self-host LibreDB Studio?

LibreDB Studio scores 58/100 on selfhost.directory (how scoring works) and ranks #27 of 40 in Database Management. It has 1 299 GitHub stars.

It shipped 8 stable releases in the past year. The latest, libredb-studio-0.1.108, came out on 28 October 2026.

Setup is easy: most people get it running in one sitting. An official Docker image is available. It is MIT-licensed and written mostly in Typescript.

Its closest alternative on selfhost.directory is supabase (92/100, 114 240 stars). It scores higher overall, so compare the two before you pick. See LibreDB Studio vs supabase side by side.

Features

  • AI-assisted query agentAgent statement execution only on PostgreSQL, SQLite, DuckDB, SQL Server, MySQL, Kubernetes and MongoDB; no model configured means no AI.
  • Audit Trail
  • Charting
  • Database monitoring dashboardAdmin only; metric availability varies per engine.
  • Data export (CSV/JSON)
  • Interactive ER diagrams
  • MCP ServerOff by default.
  • Monaco-based SQL editor
  • Multi-engine database supportDruid, Elasticsearch and OpenSearch are read-only because their SQL has no UPDATE or CREATE TABLE.
  • Multi-tab workspace
  • OIDC single sign-on with role mapping
  • Role-based Access Control
  • Schema diff and migration generationAutomatic migration SQL for PostgreSQL, MySQL, SQLite, Oracle, SQL Server plus ClickHouse column changes.
  • Virtualized data grid with inline editingInline editing hidden on engines whose SQL has no single-table row update.
  • Visual EXPLAIN plansAvailability depends on the engine.

LibreDB Studio README

How to install LibreDB Studio

Install LibreDB Studio with Docker

Docker
Environment variables
ADMIN_EMAIL, ADMIN_PASSWORD, JWT_SECRET, AUTH_BOOTSTRAP, AUTH_COOKIE_SECURE, LLM_PROVIDER, LLM_API_KEY, LLM_MODEL
docker run \
  --name libredb-studio \
  -p 3000:3000 \
  -e ADMIN_EMAIL=admin@libredb.org \
  ghcr.io/libredb/libredb-studio:latest

Zero-config: the admin password is printed to the log on first run. Alpine and alpine-slim tag variants exist.

How to configure LibreDB Studio

  • ADMIN_EMAILAUTHENTICATION (Required when AUTH_BOOTSTRAP=off) Admin credentials (full access + maintenance tools) — ADMIN_PASSWORD is required only when AUTH_BOOTSTRAP=off; otherwise it is auto-generated on first start (see ZERO-CONFIG BOOTSTRAP section below).

    AUTHENTICATION (Required when AUTH_BOOTSTRAP=off) Admin credentials (full access + maintenance tools) — ADMIN_PASSWORD is required only when AUTH_BOOTSTRAP=off; otherwise it is auto-generated on first start (see ZERO-CONFIG BOOTSTRAP section below).

  • ADMIN_PASSWORDLeft empty on purpose: a value here is a password anyone reading this file knows, and this file is copied to .env and run as it stands. Unset, one is generated on first start and printed to the log once. Fill it in only to choose your own.

    Left empty on purpose: a value here is a password anyone reading this file knows, and this file is copied to .env and run as it stands. Unset, one is generated on first start and printed to the log once. Fill it in only to choose your own.

  • ADMIN_PASSWORD_RESETBreak-glass for the account table: true makes ADMIN_EMAIL an enabled admin again with ADMIN_PASSWORD (and ADMIN_TOTP_SECRET, or no second factor) at the next start, and ends its older sessions. Use it for a rotated secret or a locked-out admin, then remove it: every start applies it again while it is set.

    Break-glass for the account table: true makes ADMIN_EMAIL an enabled admin again with ADMIN_PASSWORD (and ADMIN_TOTP_SECRET, or no second factor) at the next start, and ends its older sessions. Use it for a rotated secret or a locked-out admin, then remove it: every start applies it again while it is set.

  • ADMIN_TOTP_SECRETTWO-FACTOR AUTHENTICATION (TOTP) — optional, local provider only Base32 secret (RFC 4648: A-Z and 2-7). When set, that account must present a 6-digit code from an authenticator app after its password. Opt-in per account: set one, both, or neither. Under NEXT_PUBLIC_AUTH_PROVIDER=oidc the login page shows no password form, so MFA belongs at the identity provider (docs/OIDC.md) — but POST /api/auth/

    TWO-FACTOR AUTHENTICATION (TOTP) — optional, local provider only Base32 secret (RFC 4648: A-Z and 2-7). When set, that account must present a 6-digit code from an authenticator app after its password. Opt-in per account: set one, both, or neither. Under NEXT_PUBLIC_AUTH_PROVIDER=oidc the login page shows no password form, so MFA belongs at the identity provider (docs/OIDC.md) — but POST /api/auth/

  • AGENT_MODEL_TUNING_PATHMeasured per-model settings to layer over the ones Studio ships with. Studio carries a document of settings that specific models were measured under — how long a turn of theirs may take, how many readings they may take before they are asked to report, whether an empty turn is worth asking again. A model that is not in that document is driven with the defaults, which is the honest treatment of a mo

    Measured per-model settings to layer over the ones Studio ships with. Studio carries a document of settings that specific models were measured under — how long a turn of theirs may take, how many readings they may take before they are asked to report, whether an empty turn is worth asking again. A model that is not in that document is driven with the defaults, which is the honest treatment of a mo

  • AGENT_MODEL_TURN_TIMEOUT_MSHow long ONE model call may take before the run stops waiting for it, in milliseconds. Default 90000, and leaving it unset is what every published measurement was taken at. Raise it for a LOCAL model. The default was chosen against hosted APIs, where a turn lands in seconds and a 90-second wait only ever means a request that is not coming back. On a local endpoint it is measurably wrong: across 25

    How long ONE model call may take before the run stops waiting for it, in milliseconds. Default 90000, and leaving it unset is what every published measurement was taken at. Raise it for a LOCAL model. The default was chosen against hosted APIs, where a turn lands in seconds and a 90-second wait only ever means a request that is not coming back. On a local endpoint it is measurably wrong: across 25

  • ALLOW_CUSTOM_CONNECTIONSCUSTOM CONNECTIONS (Optional) Whether a signed-in user may open a connection of their own, one that is not a seed connection (SEED_CONFIG_PATH below). On when unset. "false", "0", "off" or "no" (trimmed, any case) switch it off: every route that builds a database provider then refuses a connection the request supplies with 403 "Custom connections are disabled on this server", and the editor hides

    CUSTOM CONNECTIONS (Optional) Whether a signed-in user may open a connection of their own, one that is not a seed connection (SEED_CONFIG_PATH below). On when unset. "false", "0", "off" or "no" (trimmed, any case) switch it off: every route that builds a database provider then refuses a connection the request supplies with 403 "Custom connections are disabled on this server", and the editor hides

  • ALLOWED_ORIGINS─── CSRF: Origin Check ────────────────────────────────────────────────────── Every POST, PUT, PATCH and DELETE must carry an Origin (or, failing that, a Referer) whose HOST matches this deployment's own host. Schemes are ignored deliberately, so a TLS-terminating proxy that forwards plain HTTP does not lock you out. This is a second layer behind the session cookie's SameSite=Lax. SET THIS if a re

    ─── CSRF: Origin Check ────────────────────────────────────────────────────── Every POST, PUT, PATCH and DELETE must carry an Origin (or, failing that, a Referer) whose HOST matches this deployment's own host. Schemes are ignored deliberately, so a TLS-terminating proxy that forwards plain HTTP does not lock you out. This is a second layer behind the session cookie's SameSite=Lax. SET THIS if a re

  • AUTH_BOOTSTRAPZERO-CONFIG BOOTSTRAP (Optional) When JWT_SECRET and/or ADMIN_PASSWORD are NOT set, the server generates the missing values on first start, persists them to <data dir>/auth-bootstrap.json (file mode 0600), and prints the admin password ONCE to stdout. Explicit env vars always win. In OIDC mode (NEXT_PUBLIC_AUTH_PROVIDER=oidc) only the JWT secret is generated — a password is never generated. Set to

    ZERO-CONFIG BOOTSTRAP (Optional) When JWT_SECRET and/or ADMIN_PASSWORD are NOT set, the server generates the missing values on first start, persists them to <data dir>/auth-bootstrap.json (file mode 0600), and prints the admin password ONCE to stdout. Explicit env vars always win. In OIDC mode (NEXT_PUBLIC_AUTH_PROVIDER=oidc) only the JWT secret is generated — a password is never generated. Set to

  • AUTH_COOKIE_SECURECOOKIE SECURITY (Optional) The Secure flag on the auth cookies (auth-token, the OIDC state cookie, and the passkey-registration and passkey-sign-in ceremony cookies). Unset (default): on in production, off otherwise, with one exception - a request that arrived on a loopback host over plain http never gets it, so the desktop shell can keep a session (issue #232). Set to "false" ("off"/"0") when the

    COOKIE SECURITY (Optional) The Secure flag on the auth cookies (auth-token, the OIDC state cookie, and the passkey-registration and passkey-sign-in ceremony cookies). Unset (default): on in production, off otherwise, with one exception - a request that arrived on a loopback host over plain http never gets it, so the desktop shell can keep a session (issue #232). Set to "false" ("off"/"0") when the

  • AUTH_SESSION_TTL_SECONDSSESSION LIFETIME (Optional) How long a session lasts, in seconds: the session token's expiry and the auth-token cookie's Max-Age. A whole number from 300 to 86400; unset keeps 86400 (24 hours). Any other value stops the server at boot. A session carries the role it was issued with, so a role removed at the identity provider keeps working until the session expires. A shorter lifetime bounds that wi

    SESSION LIFETIME (Optional) How long a session lasts, in seconds: the session token's expiry and the auth-token cookie's Max-Age. A whole number from 300 to 86400; unset keeps 86400 (24 hours). Any other value stops the server at boot. A session carries the role it was issued with, so a role removed at the identity provider keeps working until the session expires. A shorter lifetime bounds that wi

  • BASE_PATHBUILD-TIME SUBPATH (Optional) For /libredb, /tools/libredb or /~/libredb, build your own image/app with this value. It cannot relocate a prebuilt image at runtime. No trailing slash.

    BUILD-TIME SUBPATH (Optional) For /libredb, /tools/libredb or /~/libredb, build your own image/app with this value. It cannot relocate a prebuilt image at runtime. No trailing slash.

  • BIGQUERY_EMULATOR_HOSTSends every BigQuery API request to a local emulator (goccy/bigquery-emulator) over plain HTTP instead of Google, for development and the live check (tests/live/bigquery-live-check.ts). No Google credential is minted or sent while it is set. Never set it on a server people use.

    Sends every BigQuery API request to a local emulator (goccy/bigquery-emulator) over plain HTTP instead of Google, for development and the live check (tests/live/bigquery-live-check.ts). No Google credential is minted or sent while it is set. Never set it on a server people use.

  • BIGQUERY_SERVER_CREDENTIALSGOOGLE SERVER CREDENTIALS: BIGQUERY AND FIRESTORE (Optional) Lets an operator-seeded (managed) BigQuery connection with no key in its password field query as the server's own Google identity. Only the exact value true enables it; a connection a user creates always needs its own key.

    GOOGLE SERVER CREDENTIALS: BIGQUERY AND FIRESTORE (Optional) Lets an operator-seeded (managed) BigQuery connection with no key in its password field query as the server's own Google identity. Only the exact value true enables it; a connection a user creates always needs its own key.

  • CSP_REPORT_ONLY─── Security Headers ──────────────────────────────────────────────────────── Every response that passes through the app's request middleware carries X-Content-Type-Options, Referrer-Policy, Permissions-Policy, X-Frame-Options, Strict-Transport-Security and a Content-Security-Policy. Nothing needs to be set for that to happen. (Static assets and the two load-balancer/bootstrap paths, /api/db/healt

    ─── Security Headers ──────────────────────────────────────────────────────── Every response that passes through the app's request middleware carries X-Content-Type-Options, Referrer-Policy, Permissions-Policy, X-Frame-Options, Strict-Transport-Security and a Content-Security-Policy. Nothing needs to be set for that to happen. (Static assets and the two load-balancer/bootstrap paths, /api/db/healt

  • DB_HTTP_BLOCK_PRIVATE_HOSTSHTTP DATABASE DESTINATION POLICY (Optional) Enable for hosted or multi-user deployments where connection creators must not reach the server's private network. It blocks loopback, private, link-local, unique-local and selected special-use IPs on every HTTP database request, including DNS answers, with validation bound to the socket's chosen address. Unset/false preserves local connections, Docker s

    HTTP DATABASE DESTINATION POLICY (Optional) Enable for hosted or multi-user deployments where connection creators must not reach the server's private network. It blocks loopback, private, link-local, unique-local and selected special-use IPs on every HTTP database request, including DNS answers, with validation bound to the socket's chosen address. Unset/false preserves local connections, Docker s

  • DEV_ALLOWED_ORIGINSDEV SERVER ORIGINS (Optional, bun dev only) Hostnames other than localhost that may load the dev server's /_next resources, comma separated, without a scheme or port. Needed to open `bun dev` from another machine on the LAN. Ignored by next build and next start.

    DEV SERVER ORIGINS (Optional, bun dev only) Hostnames other than localhost that may load the dev server's /_next resources, comma separated, without a scheme or port. Needed to open `bun dev` from another machine on the LAN. Ignored by next build and next start.

  • DISCOVERY_EXCLUDEComma-separated app names to skip (the service name without srv-captain--). Only their names reach the export, and Studio's admin status lists each one as skipped with the reason "listed in Apps to skip".

    Comma-separated app names to skip (the service name without srv-captain--). Only their names reach the export, and Studio's admin status lists each one as skipped with the reason "listed in Apps to skip".

  • DISCOVERY_FILE_GID
  • DISCOVERY_FILE_UIDOwner given to the export file: the uid and gid the Studio server runs as, each an integer from 0 to 4294967294.

    Owner given to the export file: the uid and gid the Studio server runs as, each an integer from 0 to 4294967294.

  • DISCOVERY_INTERVAL_MSTime between scans in ms, an integer from 2000 to 2147483647.

    Time between scans in ms, an integer from 2000 to 2147483647.

  • DISCOVERY_NETWORKOverlay network whose services are exported (exact name match).

    Overlay network whose services are exported (exact name match).

  • DISCOVERY_ONCESet to 1 to run one scan and exit (used by the exporter's tests).

    Set to 1 to run one scan and exit (used by the exporter's tests).

  • DISCOVERY_OUTPUT─── Platform Discovery Exporter (docker/discover.mjs) ─────────────────────── Read by the exporter process only, never by the Studio server. The exporter is the -discovery companion of the CapRover auto-connect template (deploy/caprover/libredb-studio-autoconnect.yml). Run as root with the Docker socket mounted, it lists the Swarm services of one overlay network and writes their names, hosts, imag

    ─── Platform Discovery Exporter (docker/discover.mjs) ─────────────────────── Read by the exporter process only, never by the Studio server. The exporter is the -discovery companion of the CapRover auto-connect template (deploy/caprover/libredb-studio-autoconnect.yml). Run as root with the Docker socket mounted, it lists the Swarm services of one overlay network and writes their names, hosts, imag

  • DOCKER_SOCKETDocker Engine API socket.

    Docker Engine API socket.

  • FIRESTORE_EMULATOR_HOSTSends every Firestore connection on this server to a Firestore emulator over plain HTTP, with no credential, instead of Google: host:port or [ipv6]:port, no scheme. A connection that carries a credential is refused while it is set, and changing it needs a restart. Never set it on a server people use.

    Sends every Firestore connection on this server to a Firestore emulator over plain HTTP, with no credential, instead of Google: host:port or [ipv6]:port, no scheme. A connection that carries a credential is refused while it is set, and changing it needs a restart. Never set it on a server people use.

  • FIRESTORE_SERVER_CREDENTIALSThe same switch for Firestore: an operator-seeded Firestore connection with an empty password field reads as the server's own Google identity.

    The same switch for Firestore: an operator-seeded Firestore connection with an empty password field reads as the server's own Google identity.

  • GCE_METADATA_HOSTWith either switch on: the metadata server for GKE Workload Identity or GCE, when it is not the default metadata.google.internal.

    With either switch on: the metadata server for GKE Workload Identity or GCE, when it is not the default metadata.google.internal.

  • GOOGLE_APPLICATION_CREDENTIALSWith either switch on (BIGQUERY_SERVER_CREDENTIALS or FIRESTORE_SERVER_CREDENTIALS): the service-account key file used as that identity. Unset, gcloud's ADC file is tried, then the metadata server.

    With either switch on (BIGQUERY_SERVER_CREDENTIALS or FIRESTORE_SERVER_CREDENTIALS): the service-account key file used as that identity. Unset, gcloud's ADC file is tried, then the metadata server.

  • GOVERNANCE_ALLOWED_ENGINESThe connection type ids Studio admits from the governance source, separated by commas (default: postgres,mysql,mssql,oracle,mongodb,redis). An engine that opens a local file (sqlite, duckdb, libredb) is never admitted.

    The connection type ids Studio admits from the governance source, separated by commas (default: postgres,mysql,mssql,oracle,mongodb,redis). An engine that opens a local file (sqlite, duckdb, libredb) is never admitted.

  • GOVERNANCE_INSTANCE_IDThis instance's id in its heartbeat: 1 to 128 ASCII letters, digits, dots, underscores, colons or hyphens. Required under governance. It must stay the same across restarts, so the host name never stands in for it: a container's host name changes on every recreate. A one-replica install uses libredb-studio.

    This instance's id in its heartbeat: 1 to 128 ASCII letters, digits, dots, underscores, colons or hyphens. Required under governance. It must stay the same across restarts, so the host name never stands in for it: a container's host name changes on every recreate. A one-replica install uses libredb-studio.

  • GOVERNANCE_MAX_STALENESS_MSHow old the last loaded snapshot may grow while reloads fail before the database routes answer 503, in milliseconds: a whole number from GOVERNANCE_REFRESH_MS to 3600000 (default: 120000). Raise it together with a GOVERNANCE_REFRESH_MS above 120000, or the server refuses to start.

    How old the last loaded snapshot may grow while reloads fail before the database routes answer 503, in milliseconds: a whole number from GOVERNANCE_REFRESH_MS to 3600000 (default: 120000). Raise it together with a GOVERNANCE_REFRESH_MS above 120000, or the server refuses to start.

  • GOVERNANCE_POSTGRES_SCHEMAThe schema the governance source lives in (default: bridge). A lowercase identifier of up to 63 characters (^[a-z_][a-z0-9_]{0,62}$).

    The schema the governance source lives in (default: bridge). A lowercase identifier of up to 63 characters (^[a-z_][a-z0-9_]{0,62}$).

  • GOVERNANCE_POSTGRES_URLThe governance source, as a postgresql:// or postgres:// URL for Studio's own role, reaching the primary directly or through a session-mode pooler. Required under governance.

    The governance source, as a postgresql:// or postgres:// URL for Studio's own role, reaching the primary directly or through a session-mode pooler. Required under governance.

  • GOVERNANCE_PRIVATE_KEYS_FILEThe keyring file Studio opens the sealed credentials of governed connections with: JSON {"version":1,"keys":["<key>", ...]}, each key the unpadded base64url of a raw 32-byte X25519 private key, 1 to 16 keys with distinct key ids. Required under governance. Deliver it as a mounted file, never as an environment variable: mode 0400, owned by the user Studio runs as (uid 1001 in the image). Studio rea

    The keyring file Studio opens the sealed credentials of governed connections with: JSON {"version":1,"keys":["<key>", ...]}, each key the unpadded base64url of a raw 32-byte X25519 private key, 1 to 16 keys with distinct key ids. Required under governance. Deliver it as a mounted file, never as an environment variable: mode 0400, owned by the user Studio runs as (uid 1001 in the image). Studio rea

  • GOVERNANCE_REFRESH_MSHow often Studio reloads the governance source when no change notification arrives, in milliseconds: a whole number from 1000 to 600000 (default: 30000).

    How often Studio reloads the governance source when no change notification arrives, in milliseconds: a whole number from 1000 to 600000 (default: 30000).

  • GOVERNANCE_SOURCEGOVERNANCE MODE (Optional) Runs Studio under a control plane: the governance source it publishes in PostgreSQL becomes the only catalog of connections and grants, and the identity provider the only way to sign in. Off while GOVERNANCE_SOURCE is unset or empty, and then nothing below is read. "postgres" switches it on. Any other value counts as on as well, so a typo fails closed: the server refuses

    GOVERNANCE MODE (Optional) Runs Studio under a control plane: the governance source it publishes in PostgreSQL becomes the only catalog of connections and grants, and the identity provider the only way to sign in. Off while GOVERNANCE_SOURCE is unset or empty, and then nothing below is read. "postgres" switches it on. Any other value counts as on as well, so a typo fails closed: the server refuses

  • HOSTNAMESERVER BIND ADDRESS (Optional) Which address the standalone server listens on. Next.js binds to it, and the app reads it in two places: the boot banner (src/lib/startup-banner.ts) and the MCP endpoint, which checks the Host header only when this is a loopback address (127.0.0.1, ::1 or localhost). It applies to every channel that starts that server, and has no effect when the npm package is embedd

    SERVER BIND ADDRESS (Optional) Which address the standalone server listens on. Next.js binds to it, and the app reads it in two places: the boot banner (src/lib/startup-banner.ts) and the MCP endpoint, which checks the Host header only when this is a loopback address (127.0.0.1, ::1 or localhost). It applies to every channel that starts that server, and has no effect when the npm package is embedd

  • HSTS_INCLUDE_SUBDOMAINSHSTS is sent unconditionally with a 180-day max-age and no way to turn it off: an escape hatch that merely stops SENDING the header would be useless, because a browser that already cached the pin keeps enforcing HTTPS-only for the rest of the 180 days regardless of what the server does next, and a server that has already dropped TLS may not even be reachable to serve a corrective response. Browser

    HSTS is sent unconditionally with a 180-day max-age and no way to turn it off: an escape hatch that merely stops SENDING the header would be useless, because a browser that already cached the pin keeps enforcing HTTPS-only for the rest of the 180 days regardless of what the server does next, and a server that has already dropped TLS may not even be reachable to serve a corrective response. Browser

  • JWT_SECRETJWT Secret for session management (min 32 characters) Generate with: openssl rand -base64 32 A shorter value stops the server at startup (exit code 1) instead of booting into a deployment where the health check is green but every login returns 503. Leave it unset to have a strong secret generated on first run - unless you also set AUTH_BOOTSTRAP=off, which turns that generation off too: unset in p

    JWT Secret for session management (min 32 characters) Generate with: openssl rand -base64 32 A shorter value stops the server at startup (exit code 1) instead of booting into a deployment where the health check is green but every login returns 503. Leave it unset to have a strong secret generated on first run - unless you also set AUTH_BOOTSTRAP=off, which turns that generation off too: unset in p

  • KUBERNETES_ALLOW_INSECURE_TLSKUBERNETES CONNECTIONS (Optional) Two server-side switches of the Kubernetes provider, both off when unset. Accepted enabled values: true, on, 1. Disabled values: false, off, 0. Lets a Kubernetes connection use SSL mode require, or turn the certificate check off, which sends the token to a server whose certificate is not checked. Leave it off and give the connection the cluster's CA instead.

    KUBERNETES CONNECTIONS (Optional) Two server-side switches of the Kubernetes provider, both off when unset. Accepted enabled values: true, on, 1. Disabled values: false, off, 0. Lets a Kubernetes connection use SSL mode require, or turn the certificate check off, which sends the token to a server whose certificate is not checked. Leave it off and give the connection the cluster's CA instead.

  • KUBERNETES_ALLOW_LOOPBACK_PLAINTEXTLets a Kubernetes connection reach this machine over plain HTTP, the kubectl proxy route (http://127.0.0.1:8001). kubectl proxy hands the kubectl user's full rights to every process on this machine. The npx and desktop launchers set it when Studio listens on this machine only; Docker, Helm and the operator never set it, and a server other people reach must not.

    Lets a Kubernetes connection reach this machine over plain HTTP, the kubectl proxy route (http://127.0.0.1:8001). kubectl proxy hands the kubectl user's full rights to every process on this machine. The npx and desktop launchers set it when Studio listens on this machine only; Docker, Helm and the operator never set it, and a server other people reach must not.

  • LAUNCH_TOKEN_AUDIENCE
  • LAUNCH_TOKEN_ISSUER
  • LAUNCH_TOKEN_SECRETLAUNCH SIGN-IN (Optional) - a hosting platform signs people in A platform that hosts Studio can open /launch#token=<signed token> and Studio signs that person in; with STORAGE_PROVIDER=sqlite or postgres it creates their account in the server store, bound to their platform identity, with the role the token names, and never signs in to an account that has a password. Off while LAUNCH_TOKEN_SECRET i

    LAUNCH SIGN-IN (Optional) - a hosting platform signs people in A platform that hosts Studio can open /launch#token=<signed token> and Studio signs that person in; with STORAGE_PROVIDER=sqlite or postgres it creates their account in the server store, bound to their platform identity, with the role the token names, and never signs in to an account that has a password. Off while LAUNCH_TOKEN_SECRET i

  • LIBREDB_AGENT_ENABLED─── Agent Runtime (available when AI is configured) ───────────────────────── The agent rail drives a read-only investigation over a connected database: it drafts statements, repairs them against the schema, and composes a report whose claims carry evidence references. Every database reach goes through the AGENT'S OWN audited operation pipeline - a policy decision, an audit event and budget accoun

    ─── Agent Runtime (available when AI is configured) ───────────────────────── The agent rail drives a read-only investigation over a connected database: it drafts statements, repairs them against the schema, and composes a report whose claims carry evidence references. Every database reach goes through the AGENT'S OWN audited operation pipeline - a policy decision, an audit event and budget accoun

  • LIBREDB_AGENT_RESUME_SWEEP_INTERVAL_MSHow often the resume sweep looks for runs a dead process left behind, in milliseconds. Default 60000 (once a minute). A value that is not a positive whole number is ignored and the default stands.

    How often the resume sweep looks for runs a dead process left behind, in milliseconds. Default 60000 (once a minute). A value that is not a positive whole number is ignored and the default stands.

  • LIBREDB_AGENT_STALE_RUN_AFTER_MSHow old a running run's last ledger activity must be before the sweep claims it, in milliseconds. Default: the longest run deadline plus the claim grace and a margin, so a run still inside its deadline is never swept. A value that is not a positive whole number is ignored and the default stands.

    How old a running run's last ledger activity must be before the sweep claims it, in milliseconds. Default: the longest run deadline plus the claim grace and a margin, so a run still inside its deadline is never swept. A value that is not a positive whole number is ignored and the default stands.

  • LIBREDB_AGENT_THREAD_CONTEXTWhether a run may be told about the CONVERSATION it belongs to. Default on. A follow-up question asked on the same connection continues the previous run's conversation: the server derives the earlier steps' objectives and the most recent step's report from those runs' own ledgers, and hands them to the model fenced, so "how many of those?" resolves against what was asked before instead of being an

    Whether a run may be told about the CONVERSATION it belongs to. Default on. A follow-up question asked on the same connection continues the previous run's conversation: the server derives the earlier steps' objectives and the most recent step's report from those runs' own ledgers, and hands them to the model fenced, so "how many of those?" resolves against what was asked before instead of being an

  • LIBREDB_EMBEDDED_SAMPLE─── LibreDB Embedded Sample ───────────────────────────────────────────────── LibreDB embedded sample: on first standalone startup, auto-provide an editable "Sample (LibreDB)" connection seeded with example data (one per lens). Default on. Set to "false" to disable. Has no effect when embedded in libredb-platform.

    ─── LibreDB Embedded Sample ───────────────────────────────────────────────── LibreDB embedded sample: on first standalone startup, auto-provide an editable "Sample (LibreDB)" connection seeded with example data (one per lens). Default on. Set to "false" to disable. Has no effect when embedded in libredb-platform.

  • LIBREDB_EMBEDDED_SAMPLE_PATHOptional file path override (default: <data dir>/sample.libredb):

    Optional file path override (default: <data dir>/sample.libredb):

  • LIBREDB_ENABLED_PROVIDERSENABLED PROVIDERS (Optional) The connection type ids this server may open, separated by commas. A type outside the list is refused with a configuration error before its provider module or driver loads. Unset or blank enables every provider, which is what the web app, Docker, Helm, npx and the desktop launchers expect; the VS Code extension sets it in its backend process. An entry that is not a typ

    ENABLED PROVIDERS (Optional) The connection type ids this server may open, separated by commas. A type outside the list is refused with a configuration error before its provider module or driver loads. Unset or blank enables every provider, which is what the web app, Docker, Helm, npx and the desktop launchers expect; the VS Code extension sets it in its backend process. An entry that is not a typ

  • LIBREDB_MCP_ENABLED─── MCP Server (off by default) ───────────────────────────────────────────── An AI client of your own (Claude Code, Codex, Cursor, VS Code, Gemini CLI) reads schemas and runs bounded, read-only SQL at /api/mcp with a token minted on the settings screen, while the database credentials stay on this server. "true"/"on"/"1" enable it; "false"/"off"/"0", an empty value or unset leave it off; any other

    ─── MCP Server (off by default) ───────────────────────────────────────────── An AI client of your own (Claude Code, Codex, Cursor, VS Code, Gemini CLI) reads schemas and runs bounded, read-only SQL at /api/mcp with a token minted on the settings screen, while the database credentials stay on this server. "true"/"on"/"1" enable it; "false"/"off"/"0", an empty value or unset leave it off; any other

  • LIBREDB_MCP_TOKEN_LABELThe label every token's signing key is derived under, from JWT_SECRET. Any non-empty value; there is no default. Changing it revokes every MCP token at once, which is the only revocation: nothing about a token is stored. A token outlives a deleted or disabled account, so to offboard a person, stop them signing in, then change it once ten minutes have passed: minting needs a sign-in from the last t

    The label every token's signing key is derived under, from JWT_SECRET. Any non-empty value; there is no default. Changing it revokes every MCP token at once, which is the only revocation: nothing about a token is stored. A token outlives a deleted or disabled account, so to offboard a person, stop them signing in, then change it once ten minutes have passed: minting needs a sign-in from the last t

  • LIBREDB_MCP_TOKEN_TTL_DAYSHow many days a minted token stays valid: a whole number from 1 to 365. Default 30. A token keeps the role its owner had when it was minted until it expires or the label changes.

    How many days a minted token stays valid: a whole number from 1 to 365. Default 30. A token keeps the role its owner had when it was minted until it expires or the label changes.

  • LIBREDB_MCP_URLThe address clients use. Every token is bound to it, and its host joins the Origin and Host allowlists. An absolute http(s) URL whose path ends in /api/mcp, with no user name, password, query or fragment; include your BASE_PATH. Unset or invalid, no token can be minted or accepted. The npx launcher derives it from --host and --port when it is unset.

    The address clients use. Every token is bound to it, and its host joins the Origin and Host allowlists. An absolute http(s) URL whose path ends in /api/mcp, with no user name, password, query or fragment; include your BASE_PATH. Unset or invalid, no token can be minted or accepted. The npx launcher derives it from --host and --port when it is unset.

  • LIBREDB_NO_BANNER─── Startup Banner ────────────────────────────────────────────────────────── On standalone startup the server prints one short block naming the version, the local URL and the project repository. It is plain stdout for whoever reads `docker logs` - nothing is sent anywhere. Set to "1" or "true" to print nothing. Has no effect when embedded in libredb-platform.

    ─── Startup Banner ────────────────────────────────────────────────────────── On standalone startup the server prints one short block naming the version, the local URL and the project repository. It is plain stdout for whoever reads `docker logs` - nothing is sent anywhere. Set to "1" or "true" to print nothing. Has no effect when embedded in libredb-platform.

  • LIBREDB_SQLITE_DRIVERSQLite DB Provider Driver (advanced) The SQLite *target-database* provider picks the runtime's built-in driver automatically: bun:sqlite under Bun, node:sqlite under Node (>= 24). Set this only to force a specific driver (e.g. deterministic tests). Options: bun, node

    SQLite DB Provider Driver (advanced) The SQLite *target-database* provider picks the runtime's built-in driver automatically: bun:sqlite under Bun, node:sqlite under Node (>= 24). Set this only to force a specific driver (e.g. deterministic tests). Options: bun, node

  • LIBREDB_SQLITE_WORKEROn-disk SQLite statements run in a killable child process so Cancel and the agent read-only deadline can stop them. Set "0" (also "false", "no", "off") to fall back to the synchronous driver, which blocks the server thread and has no Cancel.

    On-disk SQLite statements run in a killable child process so Cancel and the agent read-only deadline can stop them. Set "0" (also "false", "no", "off") to fall back to the synchronous driver, which blocks the server thread and has no Cancel.

  • LIBREDB_SQLITE_WORKER_TIMEOUT_MSA watchdog (milliseconds) on each child-process request. A request that does not answer in this time is failed and the child is replaced. Unset = no watchdog.

    A watchdog (milliseconds) on each child-process request. A request that does not answer in this time is failed and the child is replaced. Unset = no watchdog.

  • LLM_API_KEYAPI Key for the selected provider Required for: gemini, openai Optional for: ollama, custom (depends on endpoint) Get API keys from: - Gemini: https://aistudio.google.com/ - OpenAI: https://platform.openai.com/

    API Key for the selected provider Required for: gemini, openai Optional for: ollama, custom (depends on endpoint) Get API keys from: - Gemini: https://aistudio.google.com/ - OpenAI: https://platform.openai.com/

  • LLM_API_URLAPI URL (optional - required for the custom provider, and read by every kind) Default URLs: - Gemini: https://generativelanguage.googleapis.com/v1beta - Ollama: http://localhost:11434/v1 - OpenAI: https://api.openai.com/v1 Custom provider examples: - LiteLLM: http://localhost:4000/v1 - LMStudio: http://localhost:1234/v1 - vLLM: http://localhost:8000/v1 - LocalAI: http://localhost:8080/v1 Gemini re

    API URL (optional - required for the custom provider, and read by every kind) Default URLs: - Gemini: https://generativelanguage.googleapis.com/v1beta - Ollama: http://localhost:11434/v1 - OpenAI: https://api.openai.com/v1 Custom provider examples: - LiteLLM: http://localhost:4000/v1 - LMStudio: http://localhost:1234/v1 - vLLM: http://localhost:8000/v1 - LocalAI: http://localhost:8080/v1 Gemini re

  • LLM_MODELgemini-2.5-flashModel name (optional - auto-defaults based on provider) Default models: - Gemini: gemini-2.5-flash - OpenAI: gpt-4o - Ollama: llama3.2 - Custom: gpt-3.5-turbo Popular options: Gemini: gemini-2.5-flash, gemini-2.0-flash, gemini-1.5-flash, gemini-1.5-pro OpenAI: gpt-4o, gpt-4-turbo, gpt-3.5-turbo, gpt-4o-mini Ollama: llama3.2, mistral, codellama, deepseek-coder

    Model name (optional - auto-defaults based on provider) Default models: - Gemini: gemini-2.5-flash - OpenAI: gpt-4o - Ollama: llama3.2 - Custom: gpt-3.5-turbo Popular options: Gemini: gemini-2.5-flash, gemini-2.0-flash, gemini-1.5-flash, gemini-1.5-pro OpenAI: gpt-4o, gpt-4-turbo, gpt-3.5-turbo, gpt-4o-mini Ollama: llama3.2, mistral, codellama, deepseek-coder

  • LLM_MODEL_EFFORTReasoning effort (optional - LLM_PROVIDER=openai only) Allowed values: none, minimal, low, medium, high, xhigh, max Unset or empty sends nothing and leaves the model's own default. Sent as reasoning.effort by Agent and Plan mode (the Responses API) and as reasoning_effort by the chat surface (Chat Completions). Set with any other provider, or to a value outside the list, it is refused as a configu

    Reasoning effort (optional - LLM_PROVIDER=openai only) Allowed values: none, minimal, low, medium, high, xhigh, max Unset or empty sends nothing and leaves the model's own default. Sent as reasoning.effort by Agent and Plan mode (the Responses API) and as reasoning_effort by the chat surface (Chat Completions). Set with any other provider, or to a value outside the list, it is refused as a configu

  • LLM_PROVIDERgeminiLLM Configuration (Strategy Pattern) Provider options: gemini, openai, ollama, custom The system uses Strategy Pattern to automatically select the appropriate provider based on this configuration.

    LLM Configuration (Strategy Pattern) Provider options: gemini, openai, ollama, custom The system uses Strategy Pattern to automatically select the appropriate provider based on this configuration.

  • LOG_LEVEL─── Logging ───────────────────────────────────────────────────────────────── Minimum level written to stdout. One of debug, info, warn or error, case-insensitive; anything else is ignored rather than rejected, and the default applies. The default is level-dependent on NODE_ENV: `debug` outside production, `info` in production - so leaving this unset is the right choice for most deployments, and s

    ─── Logging ───────────────────────────────────────────────────────────────── Minimum level written to stdout. One of debug, info, warn or error, case-insensitive; anything else is ignored rather than rejected, and the default applies. The default is level-dependent on NODE_ENV: `debug` outside production, `info` in production - so leaving this unset is the right choice for most deployments, and s

  • MY_DB_PASSWORD─── Seed Connections (pre-configured databases) ───────────────────────────── SEED_CONFIG_PATH=/app/config/seed-connections.yaml # Path to seed config file SEED_CACHE_TTL_MS=60000 # Cache TTL in ms (default: 60s) Credential env vars referenced in seed config (e.g., ${MY_DB_PASSWORD}):

    ─── Seed Connections (pre-configured databases) ───────────────────────────── SEED_CONFIG_PATH=/app/config/seed-connections.yaml # Path to seed config file SEED_CACHE_TTL_MS=60000 # Cache TTL in ms (default: 60s) Credential env vars referenced in seed config (e.g., ${MY_DB_PASSWORD}):

  • NEXT_PUBLIC_AUTH_PROVIDERAUTHENTICATION PROVIDER "local" (default) = email/password login (ADMIN_EMAIL/ADMIN_PASSWORD, USER_EMAIL/USER_PASSWORD) "oidc" = OpenID Connect SSO (Auth0, Keycloak, Okta, Azure AD, Zitadel, etc.)

    AUTHENTICATION PROVIDER "local" (default) = email/password login (ADMIN_EMAIL/ADMIN_PASSWORD, USER_EMAIL/USER_PASSWORD) "oidc" = OpenID Connect SSO (Auth0, Keycloak, Okta, Azure AD, Zitadel, etc.)

  • NEXT_PUBLIC_MONACO_VS_PATH─── Monaco Editor Assets ──────────────────────────────────────────────────── The SQL editor is served from this origin: `bun run build` stages the Monaco AMD bundle from node_modules into public/monaco/vs, so no CDN is contacted at runtime and the app works air-gapped. Override only when the assets live elsewhere — a sub-path mount, a CDN of your own, or a host app embedding the npm package. When

    ─── Monaco Editor Assets ──────────────────────────────────────────────────── The SQL editor is served from this origin: `bun run build` stages the Monaco AMD bundle from node_modules into public/monaco/vs, so no CDN is contacted at runtime and the app works air-gapped. Override only when the assets live elsewhere — a sub-path mount, a CDN of your own, or a host app embedding the npm package. When

  • OIDC_ADMIN_ROLESComma-separated values that map to admin role (default: admin)

    Comma-separated values that map to admin role (default: admin)

  • OIDC_AUTO_REDIRECTSend a signed-out visitor of /login straight to the identity provider instead of showing the single sign-on button (default: off). true/1/on/yes turn it on. A failed sign-in lands on /login?error=..., which always shows the page, so it cannot loop. Ignored unless NEXT_PUBLIC_AUTH_PROVIDER=oidc.

    Send a signed-out visitor of /login straight to the identity provider instead of showing the single sign-on button (default: off). true/1/on/yes turn it on. A failed sign-in lands on /login?error=..., which always shows the page, so it cannot loop. Ignored unless NEXT_PUBLIC_AUTH_PROVIDER=oidc.

  • OIDC_CLIENT_ID
  • OIDC_CLIENT_SECRET
  • OIDC_ISSUEROIDC Configuration (required when NEXT_PUBLIC_AUTH_PROVIDER=oidc) Issuer URL — must serve /.well-known/openid-configuration

    OIDC Configuration (required when NEXT_PUBLIC_AUTH_PROVIDER=oidc) Issuer URL — must serve /.well-known/openid-configuration

  • OIDC_LOGOUT_HINTSend id_token_hint with the provider's end-session request on logout (default: off). true/1/on/yes turn it on. The sign-in keeps the ID token, up to 3800 bytes, in the httpOnly cookie oidc-logout-hint scoped to <BASE_PATH>/api/auth/logout, and logout sends it only when its sub matches the session. Auth0's /v2/logout ignores it. An installer turns it on only after verifying it against the identity

    Send id_token_hint with the provider's end-session request on logout (default: off). true/1/on/yes turn it on. The sign-in keeps the ID token, up to 3800 bytes, in the httpOnly cookie oidc-logout-hint scoped to <BASE_PATH>/api/auth/logout, and logout sends it only when its sub matches the session. Auth0's /v2/logout ignores it. An installer turns it on only after verifying it against the identity

  • OIDC_PROMPTThe prompt sent to the identity provider on sign-in (default: login) login = ask for credentials on every sign-in, even with a provider session omit = send no prompt, so an existing provider session signs the user in silently (single sign-on) consent, select_account = passed through to the provider Any other value, none included, fails sign-in with oidc_config.

    The prompt sent to the identity provider on sign-in (default: login) login = ask for credentials on every sign-in, even with a provider session omit = send no prompt, so an existing provider session signs the user in silently (single sign-on) consent, select_account = passed through to the provider Any other value, none included, fails sign-in with oidc_config.

  • OIDC_ROLE_CLAIMRole mapping (optional) — claim path for determining admin vs user role Supports dot-notation for nested claims (e.g. "realm_access.roles")

    Role mapping (optional) — claim path for determining admin vs user role Supports dot-notation for nested claims (e.g. "realm_access.roles")

  • OIDC_SCOPEScopes to request (default: openid profile email)

    Scopes to request (default: openid profile email)

  • OIDC_USER_ROLES
  • ORACLE_CLIENT_LIB_DIROracle Thick-mode Client (advanced) The Oracle DB provider runs in Thin mode (pure JS, no Instant Client) by default, which only supports Oracle Database 12.1+. Set this to an installed Oracle Instant Client directory to opt into Thick mode - for servers older than 12.1 (driver error NJS-138), and for a 12.1+ server that requires something Thin mode does not implement: NJS-533 native network encry

    Oracle Thick-mode Client (advanced) The Oracle DB provider runs in Thin mode (pure JS, no Instant Client) by default, which only supports Oracle Database 12.1+. Set this to an installed Oracle Instant Client directory to opt into Thick mode - for servers older than 12.1 (driver error NJS-138), and for a 12.1+ server that requires something Thin mode does not implement: NJS-533 native network encry

  • PASSKEY_ORIGINPASSKEYS (Optional) - local accounts in the server store PASSKEY_ORIGIN is the exact address people open Studio at: scheme, host and port, no path (a BASE_PATH prefix does not belong in it). Passkeys are off while it is unset, and nothing derives it from a request. People must open exactly that address: with PASSKEY_ORIGIN=http://localhost:3000 open http://localhost:3000, not the http://127.0.0.1:

    PASSKEYS (Optional) - local accounts in the server store PASSKEY_ORIGIN is the exact address people open Studio at: scheme, host and port, no path (a BASE_PATH prefix does not belong in it). Passkeys are off while it is unset, and nothing derives it from a request. People must open exactly that address: with PASSKEY_ORIGIN=http://localhost:3000 open http://localhost:3000, not the http://127.0.0.1:

  • RATE_LIMIT_AI_MAXShared, per signed-in user, by every route that reaches an LLM provider or touches an agent run: the /api/ai/* routes, and every /api/agent/* route apart from GET /api/agent/config, which reaches no provider and only reports whether the agent exists. They share the bucket so that rotating between them cannot multiply the budget. It bounds how often LLM work can be STARTED, not how much that work c

    Shared, per signed-in user, by every route that reaches an LLM provider or touches an agent run: the /api/ai/* routes, and every /api/agent/* route apart from GET /api/agent/config, which reaches no provider and only reports whether the agent exists. They share the bucket so that rotating between them cannot multiply the budget. It bounds how often LLM work can be STARTED, not how much that work c

  • RATE_LIMIT_AI_WINDOW_SEC
  • RATE_LIMIT_ANON_MAXBounds how many "permission denied" audit lines an unauthenticated scanner can produce. It never affects whether a request is refused, only how often the refusal is logged.

    Bounds how many "permission denied" audit lines an unauthenticated scanner can produce. It never affects whether a request is refused, only how often the refusal is logged.

  • RATE_LIMIT_ANON_WINDOW_SEC
  • RATE_LIMIT_LOGIN_ACCOUNT_MAXFailed logins per submitted account per window. This one is keyed on a hash of the submitted email and is unaffected by a forged X-Forwarded-For, which is what keeps per-account brute force capped. A successful login clears it, so a typo run is not a lockout - but this is inherently a denial-of-login handle on a known account: whoever trips it (a stranger needs only the address, and the published

    Failed logins per submitted account per window. This one is keyed on a hash of the submitted email and is unaffected by a forged X-Forwarded-For, which is what keeps per-account brute force capped. A successful login clears it, so a typo run is not a lockout - but this is inherently a denial-of-login handle on a known account: whoever trips it (a stranger needs only the address, and the published

  • RATE_LIMIT_LOGIN_ACCOUNT_WINDOW_SEC
  • RATE_LIMIT_LOGIN_MAX─── Rate Limiting ─────────────────────────────────────────────────────────── Counters live in the app process, so the limits are PER REPLICA. The default deployment runs one replica. If you run more than one, enforce the same budgets at your ingress instead (nginx limit_req, Traefik rateLimit) - see charts/libredb-studio/README.md. Setting any *_MAX to 0 disables that bucket. Failed logins per cl

    ─── Rate Limiting ─────────────────────────────────────────────────────────── Counters live in the app process, so the limits are PER REPLICA. The default deployment runs one replica. If you run more than one, enforce the same budgets at your ingress instead (nginx limit_req, Traefik rateLimit) - see charts/libredb-studio/README.md. Setting any *_MAX to 0 disables that bucket. Failed logins per cl

  • RATE_LIMIT_LOGIN_WINDOW_SEC
  • RATE_LIMIT_PASSKEY_MAXFailed passkey sign-ins per client address per window, a budget of its own so passkey retries never lock password sign-in.

    Failed passkey sign-ins per client address per window, a budget of its own so passkey retries never lock password sign-in.

  • RATE_LIMIT_PASSKEY_WINDOW_SEC
  • RATE_LIMIT_QUERY_MAXShared, per user, by every database-reaching route, POST /api/mcp included: a session and an MCP token of the same user share one budget, so routing the same workload through a different endpoint does not multiply it. src/lib/api/rate-limit.ts holds the current list.

    Shared, per user, by every database-reaching route, POST /api/mcp included: a session and an MCP token of the same user share one budget, so routing the same workload through a different endpoint does not multiply it. src/lib/api/rate-limit.ts holds the current list.

  • RATE_LIMIT_QUERY_WINDOW_SEC
  • SEED_DISCOVERY_MAX_AGE_MSAge of the export's last successful scan after which the discovered connections are withdrawn, in ms (default: 60000). Keep it well above the exporter's DISCOVERY_INTERVAL_MS (10000 by default), or a healthy export turns stale between two scans.

    Age of the export's last successful scan after which the discovered connections are withdrawn, in ms (default: 60000). Keep it well above the exporter's DISCOVERY_INTERVAL_MS (10000 by default), or a healthy export turns stale between two scans.

  • SEED_DISCOVERY_PATHPlatform discovery (CapRover auto-connect), off while unset: the path of the export file the discovery companion app writes. Studio re-reads it at most once per SEED_CACHE_TTL_MS, and at most every 5 seconds (or once per SEED_CACHE_TTL_MS when that is shorter) while the copy it holds is stale, and lists the databases it names for admins only. See docs/SEED_CONNECTIONS.md.

    Platform discovery (CapRover auto-connect), off while unset: the path of the export file the discovery companion app writes. Studio re-reads it at most once per SEED_CACHE_TTL_MS, and at most every 5 seconds (or once per SEED_CACHE_TTL_MS when that is shorter) while the copy it holds is stale, and lists the databases it names for admins only. See docs/SEED_CONNECTIONS.md.

  • SEED_LITERAL_VALUESRead every seed value as written: no ${ENV} or ${vault:...} reference in the seed file is resolved, and the plaintext-password warning is not logged. For a seed file a platform writes from data its users control, where a database user named ${JWT_SECRET} would otherwise make this process send its own secret to that user's server. "true", "1", "on" or "yes" (trimmed, any case) turn it on; "false",

    Read every seed value as written: no ${ENV} or ${vault:...} reference in the seed file is resolved, and the plaintext-password warning is not logged. For a seed file a platform writes from data its users control, where a database user named ${JWT_SECRET} would otherwise make this process send its own secret to that user's server. "true", "1", "on" or "yes" (trimmed, any case) turn it on; "false",

  • SQLITE_EMBEDDED_SAMPLE─── SQLite Embedded Sample ────────────────────────────────────────────────── SQLite embedded sample: on first standalone startup, copy the vendored employees database (seed-assets/sqlite/employee.db) into the data dir and auto-provide an editable "Sample (Employees)" connection. Seeded asynchronously (never blocks boot); default on. Set to "false" to disable. Has no effect when embedded in libred

    ─── SQLite Embedded Sample ────────────────────────────────────────────────── SQLite embedded sample: on first standalone startup, copy the vendored employees database (seed-assets/sqlite/employee.db) into the data dir and auto-provide an editable "Sample (Employees)" connection. Seeded asynchronously (never blocks boot); default on. Set to "false" to disable. Has no effect when embedded in libred

  • SQLITE_EMBEDDED_SAMPLE_PATHOptional runtime file path override (default: <data dir>/sample-employees.db):

    Optional runtime file path override (default: <data dir>/sample-employees.db):

  • SQLITE_EMBEDDED_SAMPLE_TEMPLATEOptional template override (default: <cwd>/seed-assets/sqlite/employee.db):

    Optional template override (default: <cwd>/seed-assets/sqlite/employee.db):

  • STORAGE_ENCRYPTION_KEYCredential encryption key for the SERVER-SIDE store (sqlite/postgres only) — OPTIONAL. When STORAGE_PROVIDER is sqlite or postgres, database passwords, connection strings, TLS client keys and SSH keys/passphrases are encrypted before they are written, so a stolen database file or dump is useless on its own. Leave this unset and the key is derived from JWT_SECRET, so there is nothing to configure.

    Credential encryption key for the SERVER-SIDE store (sqlite/postgres only) — OPTIONAL. When STORAGE_PROVIDER is sqlite or postgres, database passwords, connection strings, TLS client keys and SSH keys/passphrases are encrypted before they are written, so a stolen database file or dump is useless on its own. Leave this unset and the key is derived from JWT_SECRET, so there is nothing to configure.

  • STORAGE_POSTGRES_SCHEMASchema of the PostgreSQL storage tables (optional, STORAGE_PROVIDER=postgres only). Unset keeps today's behaviour: the tables are unqualified and land where the connection's search_path puts them. Set, every table, foreign key and index is named "<schema>".<table>. Studio never creates the schema: create it first, owned by the role in STORAGE_POSTGRES_URL (CREATE SCHEMA studio AUTHORIZATION <role>

    Schema of the PostgreSQL storage tables (optional, STORAGE_PROVIDER=postgres only). Unset keeps today's behaviour: the tables are unqualified and land where the connection's search_path puts them. Set, every table, foreign key and index is named "<schema>".<table>. Studio never creates the schema: create it first, owned by the role in STORAGE_POSTGRES_URL (CREATE SCHEMA studio AUTHORIZATION <role>

  • STORAGE_POSTGRES_URLPostgreSQL connection URL (required when STORAGE_PROVIDER=postgres) Local PostgreSQL without SSL:

    PostgreSQL connection URL (required when STORAGE_PROVIDER=postgres) Local PostgreSQL without SSL:

  • STORAGE_PROVIDERlocalSTORAGE PROVIDER (Optional) Controls where application data is persisted. "local" (default) = browser localStorage only (zero config, great for dev) "sqlite" = SQLite file on server (persistent, single-node) "postgres" = PostgreSQL database (persistent, multi-node, enterprise) Note: NOT prefixed with NEXT_PUBLIC_ — server-side only, discovered at runtime via GET /api/storage/config

    STORAGE PROVIDER (Optional) Controls where application data is persisted. "local" (default) = browser localStorage only (zero config, great for dev) "sqlite" = SQLite file on server (persistent, single-node) "postgres" = PostgreSQL database (persistent, multi-node, enterprise) Note: NOT prefixed with NEXT_PUBLIC_ — server-side only, discovered at runtime via GET /api/storage/config

  • STORAGE_SQLITE_PATHSQLite storage path (required when STORAGE_PROVIDER=sqlite)

    SQLite storage path (required when STORAGE_PROVIDER=sqlite)

  • TRUSTED_PROXY_HOPS─── Forwarded Headers ─────────────────────────────────────────────────────── The client address the rate limiter buckets on, and the "ip" field in the audit log, are derived from X-Forwarded-For (falling back to X-Real-IP). Both headers are attacker-controlled: the derived value is a HINT for bucketing and for reading logs, never an identity, and nothing in this product makes an authorization dec

    ─── Forwarded Headers ─────────────────────────────────────────────────────── The client address the rate limiter buckets on, and the "ip" field in the audit log, are derived from X-Forwarded-For (falling back to X-Real-IP). Both headers are attacker-controlled: the derived value is a HINT for bucketing and for reading logs, never an identity, and nothing in this product makes an authorization dec

  • TRUST_PROXY_HEADERSSet to "false" to ignore forwarded headers entirely. Be aware of what that costs: with no address signal at all, every anonymous caller shares one bucket, so a single attacker tripping the login limiter locks everyone out until the window closes.

    Set to "false" to ignore forwarded headers entirely. Be aware of what that costs: with no address signal at all, every anonymous caller shares one bucket, so a single attacker tripping the login limiter locks everyone out until the window closes.

  • USER_EMAILUser credentials (query execution only) — OPTIONAL. The lower-privilege user account exists only when USER_PASSWORD is set. Leave USER_PASSWORD unset to run admin-only (no default user password is ever assumed).

    User credentials (query execution only) — OPTIONAL. The lower-privilege user account exists only when USER_PASSWORD is set. Leave USER_PASSWORD unset to run admin-only (no default user password is ever assumed).

  • USER_PASSWORDEmpty means the account does not exist at all - it is never generated. That is the safer default for anything reachable from outside.

    Empty means the account does not exist at all - it is never generated. That is the safer default for anything reachable from outside.

  • USER_TOTP_SECRET
  • VAULT_ADDR─── HashiCorp Vault (seed credentials) ────────────────────────────────────── Optional. Lets a seed connection take a field from Vault instead of an env var, so a rotated secret is picked up without a pod restart: password: "${vault:secret/data/prod/postgres#password}" The part before `#` is the KV v2 path, the part after it the key inside the returned data. Nothing here is read unless a seed file

    ─── HashiCorp Vault (seed credentials) ────────────────────────────────────── Optional. Lets a seed connection take a field from Vault instead of an env var, so a rotated secret is picked up without a pod restart: password: "${vault:secret/data/prod/postgres#password}" The part before `#` is the KV v2 path, the part after it the key inside the returned data. Nothing here is read unless a seed file

  • VAULT_CACHE_TTL_MSHow long a read secret is cached, in ms. A rotated secret becomes visible within VAULT_CACHE_TTL_MS + SEED_CACHE_TTL_MS (default 60000 + 60000).

    How long a read secret is cached, in ms. A rotated secret becomes visible within VAULT_CACHE_TTL_MS + SEED_CACHE_TTL_MS (default 60000 + 60000).

  • VAULT_K8S_AUTH_PATHMount path of the Kubernetes auth method, when it is not `kubernetes` (e.g. one mount per cluster on a shared Vault). The login is POST /v1/auth/<path>/login.

    Mount path of the Kubernetes auth method, when it is not `kubernetes` (e.g. one mount per cluster on a shared Vault). The login is POST /v1/auth/<path>/login.

  • VAULT_K8S_TOKEN_PATHProjected service account token the Kubernetes login presents.

    Projected service account token the Kubernetes login presents.

  • VAULT_NAMESPACEVault Enterprise namespace, sent as X-Vault-Namespace when set.

    Vault Enterprise namespace, sent as X-Vault-Namespace when set.

  • VAULT_ROLEOr Kubernetes auth: the role bound to the pod's service account. Used only when VAULT_TOKEN is unset.

    Or Kubernetes auth: the role bound to the pod's service account. Used only when VAULT_TOKEN is unset.

  • VAULT_TOKENStatic token (Vault Agent, AppRole, or a dev root token).

    Static token (Vault Agent, AppRole, or a dev root token).

  • WORKFLOW_LOCAL_DATA_DIRWhere the "local" backend keeps run state, and the second half of the availability answer above: if this path cannot be created and written, the agent reports itself absent and GET /api/agent/config says which condition failed. Its own variable, not one of ours: the SDK's fallback is ".workflow-data" resolved against the working directory, which is fine for a dev checkout and wrong in a container

    Where the "local" backend keeps run state, and the second half of the availability answer above: if this path cannot be created and written, the agent reports itself absent and GET /api/agent/config says which condition failed. Its own variable, not one of ours: the SDK's fallback is ".workflow-data" resolved against the working directory, which is fine for a dev checkout and wrong in a container

  • WORKFLOW_TARGET_WORLDDurable-execution backend for agent runs. Exactly two values are accepted; an unrecognized one is refused rather than silently defaulted, because the workflow runtime otherwise treats this variable as a module to load. local (default) zero-config, keeps run state on disk. SINGLE INSTANCE ONLY - it takes file locks, so do not point more than one replica at it. @workflow/world-po

    Durable-execution backend for agent runs. Exactly two values are accepted; an unrecognized one is refused rather than silently defaulted, because the workflow runtime otherwise treats this variable as a module to load. local (default) zero-config, keeps run state on disk. SINGLE INSTANCE ONLY - it takes file locks, so do not point more than one replica at it. @workflow/world-po

LibreDB Studio releases & version history

FAQ

How is it secured for a team?

OIDC single sign-on, role-based access control, an audit trail of executed queries and risk analysis before destructive statements; the first boot generates its own secrets and prints them once, and native channels bind to localhost by default.

What does the database agent do?

You state an objective and the agent runs read-only, budgeted queries, then writes a report in which every claim cites a result; statement execution covers PostgreSQL, MySQL/MariaDB, SQLite, DuckDB, SQL Server, MongoDB and Kubernetes, while plan mode works on every connection.

Does it work on a phone?

Yes — there is dedicated mobile navigation and a card view for results, aimed at running queries while on call.

How do I install it?

With one container (docker run -p 3000:3000), and also via npx, a Helm chart, a certified Rancher Partner Chart, an embeddable npm package, one-click PaaS templates, a DigitalOcean Marketplace listing and a fly.toml — 46 channels, 39 of them live.

Why does each engine list what it does not do?

Capability flags come from the provider itself, so controls that cannot work on that engine are hidden instead of being offered and then failing.

Is anything held back from the open-source build?

No. OIDC single sign-on, ER diagrams, the AI assistant and the MongoDB and Redis drivers all ship in the MIT build, and there is no paid edition or hosted offering.

Which databases are supported?

Forty-one engines across relational, document, key-value, graph, vector, time-series, streaming, analytical, search and federated query; twenty-seven more that speak one of those wire protocols connect through the same drivers, sixty-eight named engines in all.

What does "the tool goes to the data" actually mean?

Studio runs as a container on the same private network as the database and is reached over a URL, so no port is exposed to the internet, no SSH tunnel is needed, and only the query and its result travel.

More in Data Analysis

Rate this project

Click to rate — no account needed.

0 comments

Posting as guest
Loading comments…