Get started with Quellery

All you need is Docker. Quellery runs as a single container using either SQLite (zero-config, file-based) or PostgreSQL (shared-server deployments) for its own persistence. The example below uses SQLite — see Configuration to switch to PostgreSQL.

Download the compose file

Save this docker-compose.yml to an empty directory, or download it directly.

services:
  quellery:
    image: lancewalton/quellery:latest
    ports:
      - "8080:8080"
    volumes:
      - ./quellery-data:/data
    environment:
      - DATABASE_URL=jdbc:sqlite:/data/quellery.sqlite
      - ENCRYPTION_KEY=change-me-to-a-secure-key
      - SESSION_SECRET=change-me-to-a-session-secret

Replace ENCRYPTION_KEY and SESSION_SECRET with your own random strings. ENCRYPTION_KEY is used to encrypt stored database credentials with AES-256-GCM; SESSION_SECRET signs session tokens. (Quellery user account passwords are separately hashed with bcrypt and do not use either value.)

Start Quellery

docker compose up -d

Then open http://localhost:8080 in your browser.

Alternative: Run without Docker

If you prefer not to use Docker, you can download the fat JAR and run Quellery directly with Java. Like Docker, you can use either SQLite or PostgreSQL — the example below uses SQLite.

Prerequisites

Java 21 or later. Check with java -version.

Download

Download the latest release:

Download quellery.jar 1.8.0

Run

DATABASE_URL=jdbc:sqlite:./quellery.sqlite \
ENCRYPTION_KEY=change-me-to-a-secure-key \
SESSION_SECRET=change-me-to-a-session-secret \
java -jar quellery.jar

Then open http://localhost:8080 in your browser.

DATABASE_URL is the JDBC URL for Quellery's own database. Use jdbc:sqlite:<path> for SQLite or jdbc:postgresql://host:port/dbname for PostgreSQL.

Configuration

VariableRequiredDefaultDescription
DATABASE_URLYesJDBC URL for Quellery's database (jdbc:sqlite:... or jdbc:postgresql://...)
DATABASE_USERNAMENoDatabase username (PostgreSQL only)
DATABASE_PASSWORDNoDatabase password (PostgreSQL only)
ENCRYPTION_KEYYesKey for AES-256-GCM encryption of stored database credentials
SESSION_SECRETYesSigns session tokens
SESSION_EXPIRY_HOURSNo24Login session duration (hours)
PROMOTE_ADMIN_EMAILNoPromote an existing user to admin on startup
QUELLERY_SNAPSHOT_THRESHOLDNo0 (disabled)Number of events before snapshotting state to speed up startup
QUELLERY_SECURE_COOKIESNotrueSets the Secure attribute on the session cookie and emits a Strict-Transport-Security header on every response. Leave at the default for any deployment terminating TLS at or before Quellery. Set to false only for local HTTP development.
QUELLERY_API_ENABLEDNofalseSet to true to enable the read-only HTTP API at /api/v1/*. Available on Personal, Team, and Enterprise editions; Trial editions can read /api-docs.html but cannot call the API.
QUELLERY_METRICS_BIND_ADDRESSNo127.0.0.1Bind address for the internal observability listener exposing /internal/live, /internal/ready, /internal/metrics, and /internal/version. Override only when running inside a compose network where the metrics scraper needs to reach the listener from another container — the server logs a WARN at startup when you do, so the override is visible in the operator log.
QUELLERY_METRICS_BIND_PORTNo8081Port for the internal observability listener.

Enabling the API

Quellery's HTTP API at /api/v1/* is read-only and off by default. Turn it on by setting QUELLERY_API_ENABLED=true and restarting; the API is available on Personal, Team, and Enterprise editions.

API keys are minted in the GUI, not via the API. Log in as an administrator, open Admin → API Keys, click Create, and copy the quellery_… secret from the reveal panel — it's shown once. Then open the Groups tab, create or pick a group with the grants the key should have (for read-only access, ModelSee(Global) and SchemaSee(Global) are usually enough), open its Members panel, flip the Users / API Keys toggle to API Keys, and add the key. The key can then call the API as Authorization: Bearer quellery_… with the access the group grants it.

The full route reference, with request and response schemas for every endpoint, is at /api-docs.html inside your Quellery instance.

Quellery also exposes a WebSocket at /ws, used internally by the browser app. It is not a supported external interface — integrations should call /api/v1/* and stay on the documented contract.

Data storage

Quellery supports SQLite and PostgreSQL for its own persistence. When using SQLite, it stores its database at the path specified in DATABASE_URL. The Docker compose file mounts a local quellery-data directory to /data in the container so your data persists across restarts and is easily accessible on your host filesystem. To use PostgreSQL instead, set DATABASE_URL to a PostgreSQL JDBC URL with DATABASE_USERNAME and DATABASE_PASSWORD.

First-run setup token

Whenever Quellery starts with no users in its database, it generates a one-time setup token and prints it to the operator log under a banner reading FIRST-RUN SETUP TOKEN. The setup page (/setup.html) requires this token before the first OpsAdmin account can be created. This closes the race where an attacker who reaches the bound port first could otherwise claim OpsAdmin. The token is regenerated on every restart while no users exist; the first successful setup consumes it and the token is gone for the lifetime of the instance.

Find the token by searching your log for FIRST-RUN SETUP TOKEN (or check the container's stdout):

docker compose logs quellery | grep -A 4 "FIRST-RUN SETUP TOKEN"

Emergency admin recovery

If all admin accounts are locked out, set PROMOTE_ADMIN_EMAIL to an existing user's email. On the next startup that user will be promoted to administrator. Remove the variable afterwards.

Logging

Quellery writes two log files to ./logs/ (override with the LOG_DIR environment variable):

Updating

Pull the latest image and restart:

docker compose pull
docker compose up -d

Your data is preserved in the quellery-data directory.

Using Quellery

Now that Quellery is running, open http://localhost:8080 in your browser.

Create your administrator account

On first launch you'll see a welcome screen. Enter a display name, email address, and password (minimum 8 characters). This becomes the first administrator account — more users can be added later.

Quellery welcome screen with fields for display name, email, and password

The dashboard

After logging in you see the main dashboard. Use the dropdowns along the top to select a database, schema, and model. The left panel lists tables, types, and queries for the selected schema.

Quellery dashboard with database, schema, and model dropdowns along the top and a left panel for tables, types, and queries

Add a database connection

On the dashboard, find the Database dropdown at the top of the screen. Next to it, click the + (create) icon button to open the Create / Edit Database dialog.

The sections below walk through every field, grouped the same way they appear in the dialog.

Database connection form with fields for name, type, host, port, database name, credentials, pool size, and refresh interval

Filling in the connection form

The fields in the dialog change depending on the database type you pick, so fill them in roughly in the order given below.

Name and Database Type

Name is free text — whatever you want to call this connection in Quellery (for example Production PostgreSQL or Local dev).

Database Type is a dropdown of PostgreSQL, MySQL, and H2. Only the drivers Quellery can find on the classpath at startup appear in the list. PostgreSQL and H2 are bundled with Quellery; MySQL is not — see Connecting to MySQL below for how to add the MySQL JDBC driver.

Connection details

For PostgreSQL and MySQL:

  • Host — hostname or IP of the database server. See Network addressing below for the right value depending on where the database is running.
  • Port — defaults to 5432 for PostgreSQL and 3306 for MySQL. Override only if your server listens somewhere else.
  • Database Name — the name of the database (catalog) to inspect. Quellery lists every schema in this database once connected.

For H2:

  • Connection Type — choose In-Memory (ephemeral, lost when the JVM exits) or File (backed by a file on disk).
  • Database Name — for in-memory, any identifier; for file-backed, the path to the database file.

Credentials

Username — the database user Quellery should connect as. For read-only introspection, a read-only role is ideal.

Password Type controls how the password is supplied:

  • Literal — you type the password into the Password field. Quellery encrypts it with AES-256-GCM (using ENCRYPTION_KEY) before storing it. Simplest option; fine for development.
  • Environment Variable — you type the name of an environment variable (for example PROD_DB_PASSWORD). Quellery reads the value from that variable on the server at connect time. The password itself is never written to Quellery's database. Best for production — rotate the password by changing the env var and restarting the container.
  • No Password — for databases that don't require one (typical for a local H2). The Password field disappears.

Pool, test SQL, and refresh interval

  • Connection Pool Size — number of concurrent JDBC connections Quellery may open. 10 is a reasonable default for most workloads.
  • Test SQL — a trivial query run to validate the connection. SELECT 1 works for every supported database and is pre-filled.
  • Refresh Interval — how often Quellery re-reads the target database's schema. Pick from the preset intervals (e.g. every 5 minutes, every hour, never). Shorter intervals catch schema changes faster but add load on the target database; Never means you refresh manually with the refresh button.

Save

Click Save. The new connection appears in the Database dropdown at the top of the dashboard. Select it, and the Schema dropdown next to it populates once Quellery has read the schema. From there you can pick a schema and start working.

If something is wrong (wrong host, bad credentials, driver not installed), you'll see an error message. Click the edit (pencil) icon next to the Database dropdown to reopen the dialog and adjust the fields.

Network addressing

What you put in the Host field depends on where the target database is running relative to Quellery.

Database on the same machine as Docker

If your database runs on the host machine and Quellery runs in a Docker container on that same machine, use host.docker.internal as the hostname. This is Docker's special name for reaching the host from inside a container. localhost will not work — it would refer to the container itself.

Database on a remote machine

Use the hostname or IP address of the remote machine directly (e.g. db.example.com or 10.0.0.42), just as any other client would. Make sure the relevant port is reachable from wherever Quellery is running.

Database in another Docker container

Put the database container on the same Docker network as Quellery, then use the container name as the hostname. For example, if your compose file defines a postgres service alongside Quellery, use postgres as the host.

Connecting to MySQL

Quellery does not bundle the MySQL JDBC driver (Connector/J). MySQL Connector/J is licensed under GPL 2.0 with a FOSS exception that does not extend to proprietary software like Quellery, so we cannot redistribute it. Adding it yourself takes about a minute.

Download Connector/J

Download the Platform Independent ZIP or TAR archive from dev.mysql.com/downloads/connector/j and extract mysql-connector-j-<version>.jar from it. Any Connector/J 8.x or 9.x release is fine; we test against the latest 9.x.

Docker

Mount the driver JAR into the container at /app/drivers/ and tell Java to include that directory on the classpath. The simplest way is to add a volume and override the entrypoint in your docker-compose.yml:

services:
  quellery:
    image: lancewalton/quellery:latest
    ports:
      - "8080:8080"
    volumes:
      - ./quellery-data:/data
      - ./drivers:/app/drivers:ro
    environment:
      - DATABASE_URL=jdbc:sqlite:/data/quellery.sqlite
      - ENCRYPTION_KEY=change-me-to-a-secure-key
      - SESSION_SECRET=change-me-to-a-session-secret
    entrypoint:
      - java
      - -Dlogback.configurationFile=logback-console.xml
      - -cp
      - /app/quellery.jar:/app/drivers/*
      - quellery.server.Server

Place the downloaded JAR into a drivers/ directory next to the compose file, then docker compose up -d. MySQL will appear in the database type dropdown the next time Quellery starts.

JAR

If you run Quellery directly from the fat JAR, add the driver to the classpath with -cp and run the main class explicitly:

DATABASE_URL=jdbc:sqlite:./quellery.sqlite \
ENCRYPTION_KEY=change-me-to-a-secure-key \
SESSION_SECRET=change-me-to-a-session-secret \
java -cp quellery.jar:mysql-connector-j-9.6.0.jar \
  quellery.server.Server

On Windows, replace the : classpath separator with ;.

What to try next

With a database connected, here are a few first things to do. Every screen has a Help button (the question-mark icon) that explains the current tab in detail — reach for it whenever a term or control is unfamiliar.

Create a model

Use the Model dropdown at the top of the dashboard to create one. A model is your conceptual overlay on the physical schema — where you record what the database should guarantee, independent of what it currently declares. Nothing you do in a model changes the target database until you generate a migration script.

Click Infer on a table

Pick a table and open the Columns, Keys & Indexes, Relationships, Functional Dependencies, or Null Cohorts tab. Each has an Infer button that scans the live data and proposes model elements — NOT NULL columns, candidate keys, foreign keys, FDs, and null cohorts — which Quellery then continuously validates.

Try the Migration tab

Once you have some verified model elements, open the Migration tab on a table (or at schema level). Quellery generates an SQL script to make the database enforce what your model asserts — NOT NULL constraints, unique indexes, foreign keys, CHECK constraints, and null-cohort table extractions.