Deployment presets
Copy-paste .env starting points for local, single-node, and CDN-fronted deploys.
Three ready-made starting points for .env. Every variable is documented on the
Configuration page — these presets just bundle
sensible values for common deployment shapes. Always generate your own secret with
openssl rand -hex 32.
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.
Local-only (evaluation)
Running on your own machine to try Keenpix. No public URL, no CDN.
POSTGRES_PASSWORD="postgres"
BETTER_AUTH_SECRET="<openssl rand -hex 32>"
BETTER_AUTH_URL="http://localhost:3000"
KEENPIX_SUPER_ADMIN_EMAIL="[email protected]"
KEENPIX_SUPER_ADMIN_PASSWORD="<a real password>"- Plain
httpon localhost, so secure cookies stay off — fine for local only. - No SMTP needed: read the OTP code from
docker compose logs app.
Single-node production
One server answers both the dashboard and every image transform over HTTPS. No separate CDN.
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="[email protected]"
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="[email protected]"
# This box answers every transform: give the disk cache room, bound concurrency.
KEENPIX_CACHE_MAX_BYTES="10737418240" # 10 GB
KEENPIX_MAX_CONCURRENCY="4"
KEENPIX_MAX_QUEUE="200"- An
https://URL turns on secure cookies automatically. - Size
KEENPIX_CACHE_MAX_BYTESto the disk volume; the in-memory LRU (KEENPIX_MEMORY_CACHE_MAX_BYTES) keeps the hottest variants in RAM. - Set
KEENPIX_MAX_CONCURRENCYnear the CPU count; load pastKEENPIX_MAX_QUEUEsheds with503instead of overrunning the box.
CDN-fronted production
A CDN caches /img/* and absorbs repeat traffic, so Keenpix only does cold transforms.
See CDN setup.
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="[email protected]"
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="[email protected]"
# 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_MAX_CONCURRENCY="4"
KEENPIX_MAX_QUEUE="200"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.
- Use omitted
fmt/fmt=autoonly when the CDN can vary byAccept. Otherwise, prefer explicitfmt=webp/fmt=avifin generated URLs to maximize edge hit rate, knowing that an explicit format will not fall back for unsupported browsers. - Use explicit
fmt=svgfor optimized SVG delivery. Omittedfmt/fmt=autorasterizes 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.