mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-06 12:02:51 +09:00
The third deferred item. An extension installs INTO a running engine rather than getting its own container, so it lives in its own namespace: `backend/templates/extensions/<id>.yaml` with a top-level `extension:` block, discovered by the same operator-wins two-directory scan the app templates use. Dropping a YAML in makes it available with no code change, and a test pins that. Not nested inside the engine template, because pgvector applies to any PostgreSQL-speaking engine rather than to `postgresql.yaml` — nesting would force duplication per host. Not a third `kind:` in the app catalog either: an extension has no compose, port or volume and produces no Application, so every consumer of `list_all_templates` would have had to learn to skip it. The hard part is not the SQL. `CREATE EXTENSION vector` is valid and fails on stock `postgres:16` with "could not open extension control file", because that image does not ship the library. Two layers, and the statement is never sent speculatively: an extension declares which images provide it, so a listing marks an instance unsupported BEFORE anything is clicked; then at install `pg_available_extensions` is queried first and a negative answer is a 409 with a remedy, not an attempt. The live probe overrules the image name in both directions — a private `registry.internal/ops/pg-with-vector` is allowed, and a `pgvector/pgvector` tag that does not actually carry the library is still refused. ServerKit does not recreate a container behind the operator's back. The remedy instead names an engine template that IS capable, found by matching the extension's images against each engine template's compose — hence `postgresql-pgvector.yaml`. TimescaleDB deliberately ships no bundled host and says so rather than implying one exists. Compatibility also needed correcting mid-build: matching on wire protocol alone claimed CockroachDB could host pgvector. It answers on pgwire and cannot load a single extension. Engines opt in with `engine.extensions: true`, which excludes it without any Python naming it. Two fixes fell out. `DatabaseService` had no psql twin of `docker_mysql_execute` — `managed_db_user_service` carried a private copy with a comment saying as much; there is now one implementation and it delegates. And that twin sets `ON_ERROR_STOP=1`, without which psql reports SUCCESS for a statement the server rejected. 57 tests, covering the zero-code-change property, compatibility, the image problem in both probe directions, admin gating, and refusals that must not execute anything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
89 lines
2.4 KiB
YAML
89 lines
2.4 KiB
YAML
id: postgresql-pgvector
|
|
name: PostgreSQL + pgvector
|
|
version: "16"
|
|
description: PostgreSQL on an image that ships the pgvector shared library, so vector search can be enabled without rebuilding the container
|
|
icon: https://serverkit.ai/imgs/template-icons/postgresql.svg
|
|
categories:
|
|
- database
|
|
- sql
|
|
- ai
|
|
website: https://github.com/pgvector/pgvector
|
|
documentation: https://github.com/pgvector/pgvector#readme
|
|
|
|
# A normal engine template. The only thing that distinguishes it from
|
|
# `postgresql.yaml` is the image: `pgvector/pgvector` carries the extension's
|
|
# control file, so `CREATE EXTENSION vector` succeeds here and cannot on stock
|
|
# `postgres:16`. Nothing in Python knows that -- the extension declares which
|
|
# image repositories provide it, and this template is discovered by matching.
|
|
engine:
|
|
family: Relational
|
|
protocol: postgresql
|
|
default_port: 5434
|
|
admin_user: postgres
|
|
admin_password_var: DB_PASSWORD
|
|
database_var: DB_NAME
|
|
port_var: PORT
|
|
bind_var: BIND_ADDRESS
|
|
unit: tables
|
|
client: psql
|
|
data_path: /var/lib/postgresql/data
|
|
extensions: true
|
|
version_var: IMAGE_TAG
|
|
versions:
|
|
- "16"
|
|
- "15"
|
|
- "14"
|
|
|
|
variables:
|
|
- name: IMAGE_TAG
|
|
type: string
|
|
default: "16"
|
|
hidden: true
|
|
description: PostgreSQL major version; constrained to engine.versions by the installer
|
|
- name: PORT
|
|
type: port
|
|
# 5432 is usually the host's own PostgreSQL and 5433 the plain engine template.
|
|
default: "5434"
|
|
hidden: false
|
|
description: Host port to publish PostgreSQL on
|
|
- name: BIND_ADDRESS
|
|
type: string
|
|
default: 127.0.0.1
|
|
hidden: true
|
|
description: Address the port binds to. 127.0.0.1 keeps the engine private.
|
|
- name: DB_PASSWORD
|
|
type: password
|
|
length: 28
|
|
description: Password for the postgres superuser
|
|
- name: DB_NAME
|
|
type: string
|
|
default: postgres
|
|
description: Initial database to create
|
|
|
|
compose:
|
|
services:
|
|
app:
|
|
image: pgvector/pgvector:pg${IMAGE_TAG}
|
|
container_name: ${APP_NAME}
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${BIND_ADDRESS}:${PORT}:5432"
|
|
environment:
|
|
POSTGRES_PASSWORD: "${DB_PASSWORD}"
|
|
POSTGRES_USER: postgres
|
|
POSTGRES_DB: "${DB_NAME}"
|
|
volumes:
|
|
- postgresql-pgvector-data:/var/lib/postgresql/data
|
|
|
|
volumes:
|
|
postgresql-pgvector-data:
|
|
|
|
ports:
|
|
- port: "${PORT}"
|
|
protocol: postgresql
|
|
description: PostgreSQL wire protocol
|
|
|
|
requirements:
|
|
memory: 512MB
|
|
storage: 5GB
|