LM-Kit OneDocs2026.9.7lm-kit.comEULA

Search on pgvector, in Containers

Two containers on one private network: PostgreSQL with the pgvector extension, and LM-Kit One using it as a search cluster, so indexed documents and their vectors live in a database you can back up, replicate and monitor with the PostgreSQL tooling you already have. About ten minutes, with Docker or Podman, on any host that runs containers. Every command below was run as written; where a step has depth, the guide that owns it is linked.


1Before you start#

  • Docker (Docker Desktop on Windows or macOS) or Podman. The commands are identical in Podman: replace docker with podman.
  • Two passwords you choose: one for the PostgreSQL superuser, one for LM-Kit One's admin account. The commands carry the placeholders your-db-password and your-admin-password; replace both.
  • A GPU is optional. Section 4 of Running in Containers has the one flag for NVIDIA and the one for AMD or Intel.

2Create the network#

docker network create lmkit-net

Containers on a user-defined network reach each other by container name, so LM-Kit One will address the database as pgvector with nothing else configured, and the database never needs a published port.

3Start PostgreSQL with pgvector#

docker run -d --name pgvector --network lmkit-net \
  -e POSTGRES_PASSWORD=your-db-password \
  -v pgvector-data:/var/lib/postgresql \
  pgvector/pgvector:0.8.6-pg18-trixie

The image is the official PostgreSQL 18 image with pgvector 0.8.6 added (pgvector on Docker Hub); a pg17 or pg16 tag serves a shop whose tooling expects an older major. The volume mounts at /var/lib/postgresql, where the PostgreSQL 18 image keeps its data, so the index survives replacing the container; a mount anywhere else is ignored silently. There is no -p: the database is reachable from the network only. For a shell on it, docker exec -it pgvector psql -U postgres.

4Start LM-Kit One on the same network#

docker run -d --name lmkit --network lmkit-net -p 5189:5189 -p 7221:7221 \
  -e Admin__InitialPassword=your-admin-password \
  -v lmkit-state:/data/state -v lmkit-models:/data/models \
  lmkitone/lm-kit-one

Add --gpus all for an NVIDIA GPU, or --device /dev/dri for an AMD or Intel GPU on a Linux host. Podman needs the NVIDIA toolkit's CDI specification before --gpus all resolves; section 4 of Running in Containers has the two commands. Open https://localhost:7221/admin, accept the self-signed certificate once, and sign in as admin with the password you seeded. Without the seed, the server prints a one-time password in docker logs lmkit; section 1 of Running in Containers covers that sign-in in full.

5Register the database as a search cluster#

In the panel, open Build > Search and click + Add cluster. A cluster is one search database, and the form creates it for you.

Field Value
Cluster ID pgvector
Full-text store PostgreSQL (external server)
Vector store pgvector (same PostgreSQL)
Host pgvector
Port 5432
Database lmkit_search
Application user, and its password lmkit_search_app, with a password you choose
Admin username, Admin password postgres, your-db-password

Click Test connection first. The reply reads: full-text (PostgreSQL) server reachable, the database does not exist yet and will be created when you save the cluster, vectors (pgvector 0.8.6) ok. Then Create. LM-Kit One creates the database, installs the vector extension, initializes the schema, creates the application login and signs in with it once, and the cluster lists as Healthy beside the built-in local cluster. From here on the application user carries the search traffic; the admin login served the provisioning alone. Open the cluster and click Set default if requests that name no cluster should land here; otherwise pass cluster_id in every call, as section 7 does.

6A tenant and a key#

A tenant is an isolated workspace inside the cluster, and an API key reaches only the clusters and tenants it was granted (Search: Access Model).

  1. On the cluster's page, click + Add tenant, name it docs, and Create. The tenant's page shows its id; section 7 needs it.
  2. In Settings > Access, open API access and click Create key. Name the key, set Search access to Only pgvector, tick the docs tenant under Grant tenants in pgvector now, and Create key. Copy the token: it is shown once.

Create the key after the cluster exists. A key's cluster access is chosen when it is minted, and a key minted without it cannot reach a tenant it is later granted.

7Index one document and search it#

Three calls from the host, with the key and the tenant id from section 6. Collection and document ids are yours to choose; any UUID works, so the two below can be pasted as they are.

curl -s http://localhost:5189/lmkit/v1/search/collections \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"cluster_id":"pgvector","tenant_id":"TENANT_ID","collection_id":"00000000-0000-4000-8000-000000000001","display_name":"notes"}'

curl -s http://localhost:5189/lmkit/v1/search/documents \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"cluster_id":"pgvector","tenant_id":"TENANT_ID","collection_id":"00000000-0000-4000-8000-000000000001","document_id":"00000000-0000-4000-8000-000000000002","input":"LM-Kit One keeps this index in PostgreSQL with pgvector.","input_format":"PlainText","name":"first-note.txt"}'

curl -s http://localhost:5189/lmkit/v1/search/search \
  -H "Authorization: Bearer YOUR_KEY" -H "Content-Type: application/json" \
  -d '{"cluster_id":"pgvector","tenant_id":"TENANT_ID","collection_id":"00000000-0000-4000-8000-000000000001","query":"pgvector","search_type":"FullText"}'

The second call answers "outcome":"Created"; the third returns the document with the match highlighted in its snippet, and the cluster page now counts one tenant, one collection and one document. Full-text answers at once; the tenant's semantic index builds in the background once its embedding model has downloaded, and hybrid search follows. Indexing real documents and tuning quality is Indexing Well; queries, filters and reranking are Querying and Relevance; cited answers over the corpus are Grounded Answers.

8Keep it running#

  • Backups. docker exec pgvector pg_dump -U postgres lmkit_search > lmkit_search.sql dumps the index; the lmkit-state volume is the installation itself (Backup and Upgrades).
  • Upgrades. Pull the new tag and recreate the container; both volumes stay.
  • One node per state volume. A second LM-Kit One container must never mount the same lmkit-state. Two nodes are a farm, with a shared identity store, and that is Scaling Out.
  • Compose. The same two services in one file; Compose puts them on a shared network by itself, so pgvector resolves exactly as before, and sections 5 to 7 apply unchanged after docker compose up -d.
services:
  pgvector:
    image: pgvector/pgvector:0.8.6-pg18-trixie
    container_name: pgvector
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: your-db-password
    volumes:
      - pgvector-data:/var/lib/postgresql

  lmkit:
    image: lmkitone/lm-kit-one
    container_name: lmkit
    restart: unless-stopped
    depends_on:
      - pgvector
    ports:
      - "5189:5189"
      - "7221:7221"
    environment:
      Admin__InitialPassword: your-admin-password
    volumes:
      - lmkit-state:/data/state
      - lmkit-models:/data/models

volumes:
  pgvector-data:
  lmkit-state:
  lmkit-models: