Build the image

The build context is the repository root, not api/. The image needs web/ (the permalink templates), which lives beside api/, and Docker cannot COPY out of its context. Building with api/ as the context produces an image whose /n/{post_id} route 503s on every request. .dockerignore at the root is what keeps a root context cheap.Build --platform linux/amd64 unless every node is arm64 — the most common self-host failure is an arm64 image built on an Apple laptop that no x86 node can run.

Compose

DB_SSL=disable is correct only when the database is unreachable from outside the compose network. Anything else — a managed database, a database on another host — should use require, or verify-full with the CA bundle already baked into the image at /srv/rds-ca-bundle.pem.

Load the schema

Extensions first — the schema calls extensions.uuid_generate_v4(), following the convention of keeping extensions in their own schema. A stock Postgres has no extensions schema, so loading without this fails with schema "extensions" does not exist.
Skip db/07-telemetry-cron.sql — it needs pg_cron, which the pgvector image does not ship, and nothing else depends on it. Full ordering notes and the appuser grants are in Database.
db/schema.sql declares posts.embedding as vector(1536). The compose file above uses a 768-wide model, so retype the column before the first note is written — the one-line migration is in Embeddings. pgvector rejects a vector whose width disagrees with its column, and the API logs exactly which side is wrong.

Verify

A search returning that note proves all three components are wired: API, database, and embeddings — it is the one check worth running before handing an instance to anyone. If it returns [], the note has no vector. Check, in order: the API logs for [embed] lines (they name the reason precisely), then EMBEDDING_BASE_URL and EMBEDDING_PROVIDER — an unconfigured backend logs nothing at all, because no request is made. Confirm with select count(*) from posts where embedding is null;.

Point the CLI at it