# Deployment presets

> Copy-paste .env starting points for local, single-node, and CDN-fronted deploys.

Canonical HTML: [https://keenpix.com/docs/self-hosting/presets](https://keenpix.com/docs/self-hosting/presets)
Author: Keenpix Team

Three ready-made starting points for `.env`. Every variable is documented on the
[Configuration](/docs/self-hosting/configuration) page — these presets just bundle
sensible values for common deployment shapes. Always generate your own secret with
`openssl rand -hex 32`.

<Callout>
  With the bundled `docker-compose.yml`, set `POSTGRES_PASSWORD` and Compose builds
  `DATABASE_URL` for the app automatically. Only set `DATABASE_URL` yourself for a
  non-Docker run (`pnpm start`) or an external database.
</Callout>

## Local-only (evaluation) [#local-only-evaluation]

Running on your own machine to try Keenpix. No public URL, no CDN.

```bash
POSTGRES_PASSWORD="postgres"
BETTER_AUTH_SECRET="<openssl rand -hex 32>"
BETTER_AUTH_URL="http://localhost:3000"
KEENPIX_SUPER_ADMIN_EMAIL="admin@example.com"
KEENPIX_SUPER_ADMIN_PASSWORD="<a real password>"
```

* Plain `http` on localhost, so secure cookies stay off — fine for local only.
* No email needed: self-host is invite-only. Sign in with
  `KEENPIX_SUPER_ADMIN_EMAIL` / `KEENPIX_SUPER_ADMIN_PASSWORD` — no OTP or
  verification for the bootstrap operator.

## Single-node production [#single-node-production]

One server answers both the dashboard and every image transform over HTTPS. No separate
CDN.

```bash
POSTGRES_PASSWORD="<a long random password>"
BETTER_AUTH_SECRET="<openssl rand -hex 32>"
BETTER_AUTH_URL="https://keenpix.example.com"
KEENPIX_APP_URL="https://keenpix.example.com"
KEENPIX_SUPER_ADMIN_EMAIL="you@example.com"
KEENPIX_SUPER_ADMIN_PASSWORD="<a real password>"

# Deliver staff invitations and OTP codes via SMTP (or use postmark / resend).
EMAIL_PROVIDER="smtp"
SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USER="..."
SMTP_PASSWORD="..."
SMTP_FROM_EMAIL="keenpix@example.com"

# This box answers transforms and runs durable prewarm jobs.
KEENPIX_CACHE_MAX_BYTES="10737418240"   # 10 GB
KEENPIX_WORKER_SECRET="<openssl rand -hex 32>"
KEENPIX_WORKER_CONCURRENCY="4"
```

* An `https://` URL turns on secure cookies automatically.
* Size `KEENPIX_CACHE_MAX_BYTES` to the disk volume; the in-memory LRU
  (`KEENPIX_MEMORY_CACHE_MAX_BYTES`) keeps the hottest variants in RAM.
* Set `KEENPIX_WORKER_CONCURRENCY` for the prewarm worker. Normal image requests
  remain synchronous HTTP work and are protected by origin/input limits.

## CDN-fronted production [#cdn-fronted-production]

A CDN caches `/img/*` and absorbs repeat traffic, so Keenpix only does cold transforms.
See [CDN setup](/docs/self-hosting/cdn).

```bash
POSTGRES_PASSWORD="<a long random password>"
BETTER_AUTH_SECRET="<openssl rand -hex 32>"
# Point auth at the DASHBOARD host, not the image host the CDN serves.
BETTER_AUTH_URL="https://admin.keenpix.example.com"
KEENPIX_APP_URL="https://admin.keenpix.example.com"
KEENPIX_SUPER_ADMIN_EMAIL="you@example.com"
KEENPIX_SUPER_ADMIN_PASSWORD="<a real password>"

EMAIL_PROVIDER="smtp"
SMTP_HOST="smtp.example.com"
SMTP_PORT="587"
SMTP_USER="..."
SMTP_PASSWORD="..."
SMTP_FROM_EMAIL="keenpix@example.com"

# Cloudflare absorbs repeat traffic, but the origin is still the shared shield
# for edge cold misses and tiered-cache fills.
KEENPIX_CACHE_MAX_BYTES="8589934592"    # 8 GB
KEENPIX_MEMORY_CACHE_MAX_BYTES="268435456" # 256 MB
KEENPIX_CACHE_STALE_MS="86400000"       # 24 hours
KEENPIX_WORKER_SECRET="<openssl rand -hex 32>"
KEENPIX_WORKER_CONCURRENCY="4"
```

<Callout type="warn">
  Scope the CDN's cache rule to `/img/*` only, or keep the dashboard on a host the CDN
  does not cache. Caching `/app` or `/api/auth` breaks sign-in.
</Callout>

* Use omitted `fmt` / `fmt=auto` only when the CDN can vary by `Accept`. Otherwise,
  prefer explicit `fmt=webp` / `fmt=avif` in generated URLs to maximize edge hit rate,
  knowing that an explicit format will not fall back for unsupported browsers.
* Use explicit `fmt=svg` for optimized SVG delivery. Omitted `fmt` / `fmt=auto`
  rasterizes SVG origins instead of preserving SVG output.
* Size the origin disk cache to the image working set that still reaches Keenpix after
  Cloudflare. For small sites 2 GB can be enough; for high-cardinality hotel/CMS
  libraries, start around 8 GB and watch Operations for eviction churn.