Epure

Production checklist

Use this after a successful Quickstart on localhost. Production means a public HTTPS URL, the deploy/ compose overlay, and secrets that are not the documented laptop defaults.

Do not sign in on port 8080

EPURE_SESSION_SECURE=1 means the browser keeps the session only on HTTPS. http://YOUR_SERVER:8080 looks healthy (/health returns ok) and then login loops with no error. Point a DNS name at the box, open ports 80 and 443, and run the prod overlay with --profile tls. Skip that profile only when nginx, Caddy, or Traefik already serves your HTTPS URL.

Laptop compose is not the same file you publish. Installation separates local vs production paths.

Before you cut over traffic

CheckWhy
EPURE_PUBLIC_URL is https://…DSN and OAuth redirects must match the browser
EPURE_SESSION_SECURE=1Session cookie uses __Host-epure.sid behind TLS
Production env from deploy/env.production.example or ./configure --prodExample DB passwords are refused off localhost
Reverse proxy terminates TLSEpure listens HTTP inside the container
EPURE_CORS_ORIGINS lists your SPA originsBrowser SDK POSTs fail closed otherwise
EPURE_IMAGE=ghcr.io/epure-sh/epure:v0.2.2Current release pin (from docs release catalog)
EPURE_REGISTRATION=false after the first accountPublic URL cannot open another workspace. Sign-in and invites still work
Postgres dump scheduleUpgrades assume you can restore
Per-project ingest cap and retentionProtect disk on shared VPS: Projects
DSN keys rotated after any leakPublic keys in frontend bundles are expected; rotate if scraped
Running image is v0.1.5+Official SDKs send public-key-only DSN auth; older binaries return invalid_dsn

Do not publish laptop compose

The root docker-compose.yml is for local proof. Production uses the overlay under deploy/ with stricter boot checks. See Configuration.

Health and smoke tests

curl -sS "https://your-host.example/health"

Expect {"status":"ok"}. Then:

  1. Login at /login (cookie must stick — no redirect loop).
  2. Copy production DSN → one captureException from staging.
  3. Confirm 202 and issue row with correct environment filter.
  4. Optional: webhook test fire → Webhooks.

Symptom table: Troubleshooting.

Backup and upgrade rhythm

CadenceAction
Before every image bumppg_dump off-box — steps in Upgrades
After deploy/health, login, one test event
MonthlyReview retention, caps, and webhook URLs

Operator env highlights

Full tables: Configuration.

VariableProduction note
DATABASE_URL / ingest / app URLsAll three required; migrations exit on missing migrate URL
EPURE_CORS_ORIGINSComma-separated origins, not * in prod
GOOGLE_CLIENT_IDOptional; set callback {EPURE_PUBLIC_URL}/api/v1/auth/google/callback
EPURE_WEBHOOK_ALLOW_PRIVATELeave off — hooks must be public HTTPS
EPURE_REGISTRATIONfalse after the operator account exists. Unset stays open
Why does the app refuse to start with example passwords?

When EPURE_PUBLIC_URL is not localhost, boot rejects documented placeholder DB credentials. Switch to production env templates before pointing DNS.

Can I run Postgres on a managed service?

Yes, if all three connection URLs reach the same logical database with the expected roles. You still run the Epure binary container (or image) yourself. Connection strings: Configuration.

What about multi-region?

The self-host binary uses a single Postgres region. Run one instance per region if you need data residency; the OSS binary does not replicate across regions.