Three supported install flavours. Pick the one that matches your situation. None of them require GitHub credentials — both PointlesSQL and the soyuz-catalog catalog backend are public.
| Flavour | Who it is for | What it needs |
|---|---|---|
| Docker (recommended) | End users, quick-start | Docker Engine 24+ |
| pip install from git tag | Library consumers, scripting | Python 3.14, uv |
| Source checkout | Contributors | Git, Python 3.14, uv |
Zero-build, zero-credential install. Pulls both images from GHCR and runs the full stack in ≤2 minutes.
1. Download the reference compose file into a fresh working directory (not inside a PointlesSQL source clone):
mkdir ~/pointlessql && cd ~/pointlessql
curl -fsSL https://raw.githubusercontent.com/FloHofstetter/PointlesSQL/main/docker/docker-compose.yml -o docker-compose.yml2. Set a JWT signing key. The stack ships no baked-in key (a public
default would let anyone forge session tokens), so write a strong random
one into a .env file next to the compose file:
echo "POINTLESSQL_AUTH_SECRET_KEY=$(python -c 'import secrets; print(secrets.token_urlsafe(48))')" >> .env3. Start the stack:
docker compose up -dExpected state: http://127.0.0.1:8000/ renders the PointlesSQL
welcome page. JupyterLab is on :8888, soyuz-catalog's UC API on
:8080.
The compose file defaults to the latest published image tags. Pin a
specific release by exporting PQL_VERSION / SOYUZ_VERSION before
docker compose up:
PQL_VERSION=v0.1.0rc3 SOYUZ_VERSION=v0.3.0rc3 docker compose up -dDelta tables and notebooks persist in named Docker volumes
(warehouse_data, notebooks_data, …) that survive
docker compose down. Wipe them with docker compose down -v.
Optional — Grafana audit dashboard. Append the
docker/docker-compose.grafana.yml overlay to spin up Grafana with a
pre-provisioned audit + lineage dashboard at
http://127.0.0.1:3000:
docker compose -f docker-compose.yml -f docker-compose.grafana.yml up -dReads the same SQLite metadata DB the app uses; no agent code,
no API changes, no extra config. Postgres deployments aren't yet
supported here (see
ROADMAP.md).
Pin to a digest for reproducibility in production:
image: ghcr.io/flohofstetter/pointlessql@sha256:<digest>Every published image is signed keylessly with cosign (Sigstore OIDC — no long-lived key) and ships an SBOM + max provenance attestation. Confirm an image came from this repo's release workflow before trusting it:
cosign verify ghcr.io/flohofstetter/pointlessql:<tag> \
--certificate-identity-regexp '^https://github.com/FloHofstetter/PointlesSQL' \
--certificate-oidc-issuer https://token.actions.githubusercontent.comThe same command works for ghcr.io/flohofstetter/soyuz-catalog:<tag>.
A non-zero exit means the image was not signed by the workflow — do
not run it.
Install PointlesSQL as a Python package via uv. Useful for
scripting / library use where you already have soyuz-catalog
running elsewhere.
1. Install PointlesSQL from a tagged release. The
soyuz-catalog-client dependency resolves from its public git tag
with no credentials:
uv pip install "pointlessql @ git+https://github.com/FloHofstetter/PointlesSQL.git@v0.1.0rc3"2. Start soyuz-catalog however suits your deployment. If you
have the soyuz-catalog repo checked out, uv run soyuz-catalog
listens on :8080. Otherwise run the Docker image:
docker run -p 8080:8080 ghcr.io/flohofstetter/soyuz-catalog:v0.3.0rc33. Start PointlesSQL:
POINTLESSQL_SOYUZ_CATALOG_URL=http://127.0.0.1:8080 pointlessqlExpected state: http://127.0.0.1:8000/ renders the
welcome page.
Install from the development tree. Matches the loop you'd use if you were iterating on PointlesSQL itself.
1. Clone the repo:
git clone https://github.com/FloHofstetter/PointlesSQL.git
cd PointlesSQL2. Install dependencies. uv sync fetches the
soyuz-catalog-client wheel from its pinned public git tag — no
credentials required:
uv sync3. Optional — iterate on soyuz-catalog side-by-side. If you need regenerated client output to surface without a tag bump, flip the dependency to an editable sibling checkout:
git clone https://github.com/FloHofstetter/soyuz-catalog.git ../soyuz-catalog
bash scripts/use-editable-soyuz.sh # pyproject.toml dirty on purpose
# …iterate: edit soyuz-catalog, regen client, `uv sync`, test…
bash scripts/use-pinned-soyuz.sh # restore before committing4. Start both processes. In terminal 1:
cd ../soyuz-catalog
uv sync
uv run soyuz-catalogIn terminal 2:
cd PointlesSQL
uv run pointlessqlExpected state: http://127.0.0.1:8000/ renders the welcome
page. Code reloads with uvicorn --reload (see pointlessql/api/main.py).
To build the Docker images from your local checkout instead of pulling from GHCR, layer the contributor override:
docker compose -f docker/docker-compose.yml -f docker/docker-compose.dev.yml up --buildThis requires a sibling ../soyuz-catalog checkout for the soyuz
image build context.
docker: pull access denied / manifest unknown for
ghcr.io/flohofstetter/... — The tag you pinned doesn't exist.
Drop PQL_VERSION / SOYUZ_VERSION to use the defaults, or check
the published tags on the repo's GHCR packages page.
docker compose up says soyuz-catalog healthcheck: unhealthy —
The soyuz-catalog image failed to start. Check logs with
docker compose logs soyuz-catalog. Most common cause: the
/app/data volume has a stale SQLite from a previous version;
docker compose down -v wipes it.
docker compose -f … -f docker-compose.dev.yml build fails on the
soyuz-catalog build context — The contributor override needs a
sibling ../soyuz-catalog checkout. Clone it next to PointlesSQL,
or drop the -f docker-compose.dev.yml override to pull the
published image instead.
The SQLite database, MLflow tracking store, and MLflow artifact root all anchor to the repository root rather than the working directory the server was launched from. Concretely the defaults resolve to:
| File | Default path | Override env var |
|---|---|---|
| PointlesSQL DB | <repo>/pointlessql.db |
POINTLESSQL_DB_URL |
| MLflow backend | <repo>/mlflow.db |
POINTLESSQL_MLFLOW_BACKEND_STORE_URI |
| MLflow artifacts | <repo>/mlflow_artifacts/ |
POINTLESSQL_MLFLOW_ARTIFACT_ROOT |
Pre-fix, those paths were CWD-relative — starting pointlessql
from a sibling directory created a parallel pointlessql.db
there, which the server then read from while the seed-demo wrote
to the in-repo file. Operators who need the legacy CWD-relative
behaviour set the matching env var to sqlite:///./pointlessql.db
(or file://./mlflow_artifacts) explicitly.