# Deploy with Docker Compose

Readsmith self-hosts as two containers: the app, and Postgres with the pgvector extension. That is the entire stack. There are no external services to sign up for, no build farm, and no telemetry you did not turn on.

## The shape of a deployment

```text
docker-compose.yml
├── app        the serving shell, your docs prebuilt inside
└── db         Postgres 16 + pgvector: search, vectors, jobs
```

The compose file in the repository root is the reference deployment. An
optional third service exists behind a profile: `docker compose --profile s3
up` adds MinIO as an S3-compatible bundle store (see
[Environment](/docs/self-host/environment) for the `STORAGE_*` variables). It wires the database with a health check, a persistent volume for each store, and the app port; you provide an `.env` created from `.env.example`.

## From zero to serving

```bash
git clone https://github.com/readsmith/readsmith
cd readsmith
cp .env.example .env
```

Set a real `POSTGRES_PASSWORD` in `.env`, point `READSMITH_CONTENT` at your docs directory, and keep the file out of version control.

```bash
docker compose up -d --build
```

The image build compiles your content into the site bundle, so the running container serves prebuilt pages and never compiles at request time.

```bash
curl -s http://localhost:4321/llms.txt | head -3
```

Pages, search, and the agent outputs are serving. Put your reverse proxy in front and you are live.

## Content is baked at build time

Docs pages are prerendered into the image when it builds. Publishing a content change means rebuilding the image (`docker compose up -d --build`); rolling back means running the previous image. Deploys are therefore reproducible artifacts, not mutable state on a server. To publish on `git push` instead, without rebuilding the image, [connect a repository](/docs/self-host/git-deploys).

## What runs without a database

Without `DATABASE_URL` the app runs docs-only: pages, navigation, themes, the API reference, and every agent output (`llms.txt`, per-page Markdown, `skill.md`) work from the precompiled bundle alone. The database activates search, Ask AI, and background jobs.

## Keys and limits

Set model keys in the environment if you want semantic search and Ask AI; the app degrades gracefully without them (full-text search stays on). The built-in rate limits are on by default and sized for a public deployment. Both are cataloged in the [environment reference](/docs/self-host/environment).

Two sites must never share one storage root. Give each deployment its own `READSMITH_STORAGE_ROOT`; sharing one directory makes the second site overwrite the first site's compiled bundle.
