Getting started
quicSQL is one static binary. This page takes you from nothing to a running server your language can query, in about a minute.
Install
docker run -p 7775:7775 -v quicsql-data:/data \
-v ./quicsql.yaml:/etc/quicsql/quicsql.yaml \
ghcr.io/quicsql/quicsql:latest1. Run the daemon
One YAML file describes the whole server: listeners (one per transport), databases (one per line), and — when you want them — secrets, TLS, principals, and grants.
# quicsql.yaml
server:
data_dir: ./data
secrets:
- {name: keys, type: file, dir: ./data/keys} # "keys:<name>" reads ./data/keys/<name>
tls:
dev: {mode: self_signed, hosts: [localhost, 127.0.0.1]} # use mode: files in production
listeners:
- {name: h1, transport: h1, address: 127.0.0.1:7775}
- {name: h2, transport: h2, address: 127.0.0.1:7777, tls: dev}
- {name: h3, transport: h3, address: 127.0.0.1:7778, tls: dev} # HTTP/3 over QUIC
- {name: unix, transport: unix, address: ./data/quicsql.sock, socket_mode: "0600"}
databases:
- {name: users, backend: file, path: users.db, mode: rwc, pragmas_preset: recommended}
- name: orders # encrypted + compressed at rest
backend: vault
path: orders.vault
vault: {compression: default, cipher: adiantum, key: keys:orders}quicsql --config quicsql.yaml127.0.0.1 and nothing else. To lock it down, add a principal, a grant,
and a listener auth: list — see Auth & authorization.Every listener serves the same endpoints: POST /<db>/query (native JSON),
/<db>/v2|v3/pipeline and /<db>/v3/cursor (Hrana), /<db>/export,
/<db>/changeset/*, /<db>/blob/*, plus the server-scoped /_health,
/_metrics, /_admin/*, and /_auth/challenge. The canonical port is
7775 (h1); the sequence continues h2c 7776, h2 7777, h3 7778.
2. Talk to it — from your language
The native JSON endpoint takes {sql, args} — or a statements batch, which
runs as one explicit transaction, all-or-nothing:
curl -s http://127.0.0.1:7775/users/query \
-d '{"sql":"CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, name TEXT)"}'
curl -s http://127.0.0.1:7775/users/query \
-d '{"statements":[
{"sql":"INSERT INTO users(name) VALUES (?)","args":["ada"]},
{"sql":"SELECT * FROM users"}
]}'Integers stay exact on the wire; blobs are boxed as {"base64": …}. Full
shapes in the HTTP API reference.
These are dev-mode snippets (open mode, no token). Once you add principals,
every SDK passes its token via authToken / auth_token, which quicSQL
receives as standard bearer auth — see Clients & languages.
3. Embed it (Go)
serverd.Run assembles the whole pipeline in-process — for tests, custom SQL
functions, or shipping a bundled server inside your own binary:
import "quicsql.net/serverd"
inst, _ := serverd.Run(cfg, log) // cfg is a *config.Config; returns an *Instance
defer inst.Shutdown(ctx)Where next
- Clients & languages — your language’s path in, with CI-tested examples: JavaScript/TypeScript, Python, PHP, Go, and more.
- Databases & backends — every open mode gosqlite has, over the wire: files, in-memory, mvcc snapshots, and vault containers in every shape, plus pragmas, pool tuning, and secrets.
- Auth & authorization — six authentication methods,
the
none < read-only < read-write < admincapability model, and why read-only cannot be talked around. - The Hrana pipeline — transactions, batches, batons, and production limits.
- Runnable examples — every language above, asserting its results against a real server in CI.