PocketBase as a standalone database server
CI / Test (ubuntu-latest) (push) Canceled after 0s
CI / Test (windows-latest) (push) Canceled after 0s
CI / Storage tests on PostgreSQL (push) Canceled after 0s
CI / Complement (federation off) (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
CI / Smoke test the binary (push) Canceled after 0s
CI / Admin panel (push) Canceled after 0s
CI / Web client (push) Canceled after 0s
CI / Desktop client (ubuntu-24.04) (push) Canceled after 0s
CI / Desktop client (windows-latest) (push) Canceled after 0s

The pocketbase driver no longer embeds PocketBase: Warp keeps its data as
PocketBase collections on a server of its own and reaches it only through
the REST API, the way the postgres driver reaches PostgreSQL.
database.connection_string is the server's URL, and Warp signs in as the
superuser in WARP_PB_SUPERUSER_EMAIL / WARP_PB_SUPERUSER_PASSWORD (or a
WARP_PB_SUPERUSER_FILE of the two).

Every SQL table is a superuser-only collection of the same name and
columns, created by warp migrate. Reads go through PocketBase's SQL
endpoint with the SQL drivers' queries, via a read-only database/sql
driver that inlines arguments, moves long ones into warp_params and pages
past 1000 rows. Writes are record operations in batch requests under one
write lock in the Warp process. Media is a protected file field in
warp_media, local or in the S3 bucket Warp writes into PocketBase's
settings. Search matches word prefixes with LIKE. The storage tests run
against an in-process PocketBase and pass as on SQLite.

Docker: the PocketBase stacks get a pocketbase service running
tajniak81/pocketbase-docker-root (WARP_PB_IMAGE), with a pb-data volume
and its admin UI on loopback; the AIO images run that PocketBase binary
as a process beside the homeserver, making up a superuser when none is
set. The .env examples, READMEs, docs and warp.yaml.example follow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
tajniak81andClaude Opus 5.5 committed 2026-10-26 16:31:08 +01:00
1 parent 0994156705
commit a47e15cc1c
69 files changed
+8209 -374

No files matched your search

+5 -7
View File
@@ -37,19 +37,17 @@ List-valued variables are comma-separated. A single `-` clears a list:
| `listen.tls_cert_file` | `WARP_TLS_CERT_FILE` | empty | PEM certificate chain for the federation listener. Required with it. |
| `listen.tls_key_file` | `WARP_TLS_KEY_FILE` | empty | PEM key for the federation listener. Required with it. |
| `database.driver` | `WARP_DB_DRIVER` | `sqlite` | `sqlite`, `postgres`, `pocketbase`. |
| `database.connection_string` | `WARP_DB_CONNECTION_STRING` | SQLite file in the working directory | A DSN for postgres, a `file:` URI for sqlite, the data directory (PocketBase's `pb_data`) for pocketbase. |
| `database.connection_string` | `WARP_DB_CONNECTION_STRING` | SQLite file in the working directory | A DSN for postgres, a `file:` URI for sqlite, the PocketBase server's URL, e.g. `http://pocketbase:8070`, for pocketbase. |
| `database.max_open_conns` | `WARP_DB_MAX_OPEN_CONNS` | `10` | Ignored by SQLite: writes are serialised onto one connection. |
| `database.max_idle_conns` | `WARP_DB_MAX_IDLE_CONNS` | `5` | |
| `database.conn_max_lifetime` | `WARP_DB_CONN_MAX_LIFETIME` | `1h` | |
| `database.auto_migrate` | `WARP_DB_AUTO_MIGRATE` | `true` | `false` makes startup fail while migrations are pending. |
| `database.pocketbase.s3.enabled` | `WARP_PB_S3_ENABLED` | `false` | pocketbase only: media content goes to an S3-compatible bucket instead of `pb_data/storage`. |
| `database.pocketbase.s3.bucket` / `.region` / `.endpoint` | `WARP_PB_S3_BUCKET` / `WARP_PB_S3_REGION` / `WARP_PB_S3_ENDPOINT` | empty | All required when S3 is on. |
| `database.pocketbase.superuser_email` / `.superuser_password` | `WARP_PB_SUPERUSER_EMAIL` / `WARP_PB_SUPERUSER_PASSWORD` | empty | pocketbase only, and required: the PocketBase superuser Warp signs in as. |
| `database.pocketbase.superuser_file` | `WARP_PB_SUPERUSER_FILE` | empty | A file of `WARP_PB_SUPERUSER_EMAIL=` and `WARP_PB_SUPERUSER_PASSWORD=` lines, read for whichever is not set otherwise. The all-in-one images keep the superuser they make up there. |
| `database.pocketbase.s3.enabled` | `WARP_PB_S3_ENABLED` | `false` | pocketbase only: media content goes to an S3-compatible bucket instead of PocketBase's `pb_data/storage`. Warp writes it into PocketBase's settings on every start; PocketBase is what talks to the bucket. |
| `database.pocketbase.s3.bucket` / `.region` / `.endpoint` | `WARP_PB_S3_BUCKET` / `WARP_PB_S3_REGION` / `WARP_PB_S3_ENDPOINT` | empty | All required when S3 is on. The endpoint has to be reachable from the PocketBase server. |
| `database.pocketbase.s3.access_key` / `.secret` | `WARP_PB_S3_ACCESS_KEY` / `WARP_PB_S3_SECRET` | empty | All required when S3 is on. |
| `database.pocketbase.s3.force_path_style` | `WARP_PB_S3_FORCE_PATH_STYLE` | `false` | For MinIO and other servers without virtual-host buckets. |
| `database.pocketbase.s3.enabled` | `WARP_PB_S3_ENABLED` | `false` | pocketbase only: media content in an S3-compatible bucket instead of `pb_data/storage`. |
| `database.pocketbase.s3.bucket` / `.region` / `.endpoint` | `WARP_PB_S3_BUCKET` / `WARP_PB_S3_REGION` / `WARP_PB_S3_ENDPOINT` | empty | All required with S3 on. |
| `database.pocketbase.s3.access_key` / `.secret` | `WARP_PB_S3_ACCESS_KEY` / `WARP_PB_S3_SECRET` | empty | All required with S3 on. |
| `database.pocketbase.s3.force_path_style` | `WARP_PB_S3_FORCE_PATH_STYLE` | `false` | For MinIO and other servers without virtual-host buckets. |
| `client_api.cors_allowed_origins` | `WARP_CORS_ALLOWED_ORIGINS` | `["*"]` | The spec expects any origin. |
| `client_api.trust_x_forwarded_for` | `WARP_TRUST_X_FORWARDED_FOR` | `false` | Only behind a proxy that overwrites the header; the rate limiter keys on the result. |
| `client_api.access_token_lifetime` | `WARP_ACCESS_TOKEN_LIFETIME` | `0s` | `0` = never expire. With a lifetime, clients may ask for a refresh token at login. |
+17 -8
View File
@@ -12,15 +12,24 @@ tester, which is `server/cmd/warp-loadtest`.
|---|---|---|
| `postgres` | production | Several connections, so reads and writes run side by side. |
| `sqlite` | development, a single user, a small server | One writer. Everything is one file plus `media.base_path`. |
| `pocketbase` | an "appliance": one binary, one data directory | The sqlite driver's tables inside an embedded [PocketBase](https://pocketbase.io) app's `data.db`, written through PocketBase's own single-writer connection. Media goes into PocketBase's filesystem, which can be an S3 bucket (`database.pocketbase.s3`). |
| `pocketbase` | a [PocketBase](https://pocketbase.io) server you want to see and manage the data in | Warp's tables as PocketBase collections on a PocketBase server of its own (0.40 or later), reached only through its REST API. Media goes into PocketBase's storage, which can be an S3 bucket (`database.pocketbase.s3`). |
The pocketbase driver is the SQLite schema on the SQLite engine, so it is
at parity with sqlite by construction, and the storage tests run against
both. What it adds is PocketBase around it: its system tables in the same
database, its `auxiliary.db` for its own logs, and its filesystem
abstraction for media. Warp does not serve PocketBase's admin UI or API;
the app is reachable from Go through `pocketbase.Database.App()` for
features that want it later. Back up the whole data directory.
The pocketbase driver connects to PocketBase the way the postgres driver
connects to PostgreSQL: `database.connection_string` is the server's URL,
and Warp signs in as the superuser in `database.pocketbase`. Every table
the SQL drivers have is a superuser-only collection of the same name and
columns, so the PocketBase admin UI shows Warp's accounts, rooms and events
as records. Warp creates and updates the collections itself (`warp
migrate`), reads them through PocketBase's SQL endpoint with the same
queries the SQL drivers run, and writes them as record operations in batch
requests, each one a transaction. It turns batch requests on in
PocketBase's settings at startup.
Writes go through one lock in the Warp process, so one Warp server per
PocketBase, and every database call is an HTTP request: expect it to be
slower than PostgreSQL. Search has no full-text engine behind it; it
matches the start of words, case-insensitively. The storage tests run
against a real PocketBase. Back up PocketBase's whole `pb_data`.
## The container image