Installation
Clone Epure, start Rust + PostgreSQL 16, and confirm GET /health.
Two containers: Epure + PostgreSQL 16. No Redis. No separate worker fleet.
Laptop install is below. Production is a separate path: overlay compose, .env.production.example, HTTPS in front. Do not publish the laptop compose file.
Requirements
Docker Compose v2, disk for images plus the Postgres volume. Production also needs a DNS name and a reverse proxy that terminates HTTPS.
Local
Clone and enter
Compose files live at the public product repo root.
Clone the public tree
command
git clone https://github.com/epure-sh/epure.git cd epure
Ports live in one file. Copy only if 8080 is taken:
cp .env.example .envChange EPURE_PORT and EPURE_PUBLIC_URL together. Recreate epure after any .env change.
Start
docker compose upCompose pulls ghcr.io/epure-sh/epure:latest. Pin a tag with EPURE_IMAGE in .env.
| Service | Image | Ports (.env defaults) |
|---|---|---|
epure | ghcr.io/epure-sh/epure:latest | host ${EPURE_PORT} → container 8080 (default 8080) |
postgres | postgres:16-alpine | host ${POSTGRES_HOST_PORT} → container 5432 (default 5433) |
Laptop compose allows the documented example DB passwords only while EPURE_PUBLIC_URL is localhost. Point that URL at a real hostname and boot refuses to start until you switch to the production overlay.
Create access
Register at /login, or for local smoke only (never production):
./scripts/seed-dev.shLogin: dev@epure.local / devpassword
Then Quickstart: copy the DSN and capture an exception.
Production
Fresh Postgres volume. Do not reuse a laptop data directory.
Copy the production env file
cp .env.production.example .envReplace every CHANGE_ME. Generate passwords with openssl rand -hex 24. Set:
| Var | Value |
|---|---|
EPURE_PUBLIC_URL | https://errors.example.com (must be https://) |
EPURE_CORS_ORIGINS | Your app origins, comma-separated. Not * |
POSTGRES_PASSWORD | Superuser. Applied on first empty volume only |
EPURE_INGEST_PASSWORD | Ingest role. Set on every boot from this file |
EPURE_APP_PASSWORD | Dashboard role. Set on every boot from this file |
Leave EPURE_DEV_SEED unset. Overlay forces EPURE_SESSION_SECURE=1 and refuses example passwords (epure, epure_ingest, epure_app, CHANGE_ME).
DNS and TLS
Point the hostname at the box. Put Caddy (or nginx) in front of 127.0.0.1:8080 (or your EPURE_PORT). Forward Host, X-Forwarded-For, X-Forwarded-Proto. Allow POST and OPTIONS on /api/{project_id}/envelope/ and /api/{project_id}/store/.
Caddy (ports 80 and 443 open):
errors.example.com {
reverse_proxy 127.0.0.1:8080
}nginx:
server {
listen 443 ssl;
server_name errors.example.com;
# ssl_certificate …;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Start the proxy before you expect browser login to work. Session cookies are Secure-only.
Start the overlay
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -dPostgres is not published on the host. Migrations run on boot, then the process sets ingest/app role passwords from .env. They are not the strings in old SQL files.
Health on HTTPS
curl -sS https://errors.example.com/health{"status":"ok"}On the box, curl -sS http://127.0.0.1:8080/health also works. The dashboard URL is EPURE_PUBLIC_URL.
Register
Open https://errors.example.com/login. The first email/password register becomes owner of a new workspace. Do not run ./scripts/seed-dev.sh here.
Then Quickstart with your public DSN host.
Existing Postgres volume
Changing POSTGRES_PASSWORD in .env does not retarget a volume that already initialized. Keep the original superuser password, or rotate it inside Postgres, then match DATABASE_URL.
Confirm the install
-
GET /health→{"status":"ok"}on the public origin - Login works; session persists across refresh (HTTPS in production)
- Create DSN → SDK or Try ingest → 202 → issue in UI
- Prod: Postgres not published on the host
- Prod: backups for
postgres_data(andartifacts_dataif you upload maps)
FAQ
Why does the app exit on migrate?
Postgres is not healthy, DATABASE_URL is wrong, or example passwords were used with a non-localhost EPURE_PUBLIC_URL. Wait until postgres is healthy, then read docker compose logs epure. Recreate epure after .env changes: Troubleshooting.
Can I use the laptop compose file in production?
No. That file allows example DB passwords only for localhost. Use docker-compose.prod.yml and .env.production.example.
Do I need Redis?
No. The stack is two containers. See Configuration.
Next
- Quickstart: point a Sentry SDK
- Configuration: env vars
- Verify: 202 checklist