Deploy Epure error tracking on Coolify with Docker Compose
Import the template from the Epure repository, set the domain and four variables, verify ingest, then schedule backups and pin upgrades.
On this pageShowHide
- What do you need before deploying Epure on Coolify?
- How do you create the Epure resource in Coolify?
- Which environment variables does Epure need on Coolify?
- How do you check that Epure on Coolify receives errors?
- How do you back up and upgrade Epure on Coolify?
- Why does Epure on Coolify fail to start or keep me signed out?
- Questions
Deploying Epure on Coolify takes one Git import and a short list of variables. The template in deploy/templates/coolify/docker-compose.yml runs the Epure image and postgres:16-alpine, turns on Secure session cookies, refuses the example database passwords, and leaves the MCP server off. The table is the whole procedure; each step has its own section below.
1. Import
- Do
- Public Git repo, Docker Compose build pack, base directory /deploy/templates/coolify
- Confirm
- Coolify lists two services: epure and postgres
- If it fails
- Check the base directory has a leading slash and the file is docker-compose.yml
2. Domain
- Do
- On epure, set Domains to https://errors.example.com:8080
- Confirm
- Certificate issued; the URL loads the login page
- If it fails
- Point DNS at the Coolify server; keep the :8080 suffix
3. Variables
- Do
- Set EPURE_IMAGE, EPURE_CORS_ORIGINS; leave generated passwords alone
- Confirm
- Both containers run and the epure log shows no error
- If it fails
- Read the exact error in the epure logs (see troubleshooting)
4. Health
- Do
- curl https://errors.example.com/health
- Confirm
- {"status":"ok"}
- If it fails
- Postgres not healthy yet, or the domain points elsewhere
5. First event
- Do
- Register, create a project, send one error with its DSN
- Confirm
- Ingest answers 202 and the issue appears
- If it fails
- Follow the ingest checklist
6. Lock and back up
- Do
- EPURE_REGISTRATION=false; schedule pg_dump
- Confirm
- Register returns 403 for new workspaces; a dump file exists off the server
- If it fails
- Redeploy after changing variables
| Dimension | Do | Confirm | If it fails |
|---|---|---|---|
| 1. Import | Public Git repo, Docker Compose build pack, base directory /deploy/templates/coolify | Coolify lists two services: epure and postgres | Check the base directory has a leading slash and the file is docker-compose.yml |
| 2. Domain | On epure, set Domains to https://errors.example.com:8080 | Certificate issued; the URL loads the login page | Point DNS at the Coolify server; keep the :8080 suffix |
| 3. Variables | Set EPURE_IMAGE, EPURE_CORS_ORIGINS; leave generated passwords alone | Both containers run and the epure log shows no error | Read the exact error in the epure logs (see troubleshooting) |
| 4. Health | curl https://errors.example.com/health | {"status":"ok"} | Postgres not healthy yet, or the domain points elsewhere |
| 5. First event | Register, create a project, send one error with its DSN | Ingest answers 202 and the issue appears | Follow the ingest checklist |
| 6. Lock and back up | EPURE_REGISTRATION=false; schedule pg_dump | Register returns 403 for new workspaces; a dump file exists off the server | Redeploy after changing variables |
Checked against the epure-sh/epure repository (deploy/templates/coolify, v0.2.0, 5 Nov 2026) and Coolify's Docker Compose docs (coolify.io/docs/knowledge-base/docker/compose, read 6 Nov 2026).
What do you need before deploying Epure on Coolify?
Epure on Coolify needs a Coolify server with its proxy running on ports 80 and 443, and a DNS name such as errors.example.com pointing at it. HTTPS is not optional: the template sets EPURE_SESSION_SECURE=1, so a browser on plain HTTP drops the session cookie and sends you back to the login form. The two containers idled at about 5 MiB and 48 MiB on a 769 MiB VPS in our September measurement; your traffic, retention and source maps add to that.
Coolify fills three kinds of value from the compose file. SERVICE_PASSWORD_64_POSTGRES, SERVICE_PASSWORD_64_EPURE_INGEST and SERVICE_PASSWORD_64_EPURE_APP become 64-character passwords, and SERVICE_URL_EPURE_8080 becomes the public URL routed to port 8080 (Coolify compose docs). On every boot, after migrations, Epure sets the epure, epure_ingest and epure_app role passwords in Postgres from those URLs.
How do you create the Epure resource in Coolify?
Epure is imported into Coolify as a Docker Compose resource from the public repository, not from a marketplace entry. The six steps below match the template's own header comment. The :8080 suffix on the domain tells the Coolify proxy which container port receives requests; without it, the proxy cannot reach Epure.
- In your project, choose + New, then a public Git repository, and paste
https://github.com/epure-sh/epure. - Pick the Docker Compose build pack.
- Set Base Directory to
/deploy/templates/coolifyand Docker Compose Location todocker-compose.yml. - Open the
epureservice and set Domains tohttps://errors.example.com:8080. - Set the variables in the next section.
- Deploy, then open
https://errors.example.com/login.
Which environment variables does Epure need on Coolify?
Epure on Coolify needs two variables from you before the first real event, and two more once you are signed in. The template defaults EPURE_IMAGE to ghcr.io/epure-sh/epure:latest with pull_policy: always, so every redeploy can change the version under you. Pin a release tag instead; the current one is v0.2.0. Everything else in the table has a working default in the template.
EPURE_IMAGE
- Value
- ghcr.io/epure-sh/epure:v0.2.0
- Why
- Upgrade when you choose, not on every redeploy
EPURE_CORS_ORIGINS
- Value
- https://errors.example.com,https://app.example.com
- Why
- Default is the Epure URL only; browser SDKs on your app's origin need it listed
EPURE_REGISTRATION
- Value
- Unset until your account exists, then false
- Why
- Stops strangers creating workspaces; sign-in and invitations keep working
EPURE_TRUSTED_PROXIES
- Value
- IP or CIDR of the proxy network, comma-separated
- Why
- Login rate limits read X-Forwarded-For only from listed proxies
EPURE_MCP_ENABLED
- Value
- true, only if you want /mcp
- Why
- Off by default; serves the hosted MCP endpoint for coding agents
SERVICE_PASSWORD_64_*
- Value
- Generated by Coolify
- Why
- Changing them after first boot breaks the superuser login; see troubleshooting
| Dimension | Value | Why |
|---|---|---|
| EPURE_IMAGE | ghcr.io/epure-sh/epure:v0.2.0 | Upgrade when you choose, not on every redeploy |
| EPURE_CORS_ORIGINS | https://errors.example.com,https://app.example.com | Default is the Epure URL only; browser SDKs on your app's origin need it listed |
| EPURE_REGISTRATION | Unset until your account exists, then false | Stops strangers creating workspaces; sign-in and invitations keep working |
| EPURE_TRUSTED_PROXIES | IP or CIDR of the proxy network, comma-separated | Login rate limits read X-Forwarded-For only from listed proxies |
| EPURE_MCP_ENABLED | true, only if you want /mcp | Off by default; serves the hosted MCP endpoint for coding agents |
| SERVICE_PASSWORD_64_* | Generated by Coolify | Changing them after first boot breaks the superuser login; see troubleshooting |
Coolify does not name its proxy network in its docs, so find the subnet on the host with docker network inspect on the network that both the proxy and the epure container join, and put that CIDR in EPURE_TRUSTED_PROXIES. The full list of variables is in self-hosting configuration.
How do you check that Epure on Coolify receives errors?
Epure answers GET /health with {"status":"ok"} as soon as the server runs. GET /health/ready goes further: it queries both database pools and returns 503 if the ingest queue has dead letters or its oldest item is more than 5 minutes old. Neither proves your SDK reaches the right project, so finish with one real error from a staging app.
curl -sS https://errors.example.com/health
# {"status":"ok"}
curl -sS https://errors.example.com/health/ready
# {"status":"ok","database":"ok",...}Register at /login; the first account owns a new workspace. Create a project, copy its DSN, and send one error from any official Sentry SDK with tracing off. Ingest answers 202, and the issue appears on the Issues page within seconds. If the request succeeds and no issue shows, work through the ingest checklist before touching Coolify.
import * as Sentry from "@sentry/node";
Sentry.init({ dsn: process.env.SENTRY_DSN, tracesSampleRate: 0 });
Sentry.captureException(new Error("Epure on Coolify test"));
await Sentry.flush(2000);How do you back up and upgrade Epure on Coolify?
Epure keeps everything that matters in two named volumes: postgres_data for issues, events and settings, and artifacts_data for uploaded JS/TS source maps. Coolify's Docker Compose docs do not describe backups for a database defined inside a compose resource, so plan your own. A nightly pg_dump in custom format, copied off the server, covers the database.
# on the Coolify host
PG=$(docker ps --filter name=postgres --format '{{.Names}}' | grep -v coolify | head -n1)
docker exec "$PG" pg_dump -U epure -d epure -Fc > "epure-$(date +%Y%m%d).dump"Check that $PG names the Epure Postgres container before you schedule it; a server with several databases needs a stricter filter. To upgrade, take a dump, change EPURE_IMAGE to the new tag and redeploy; migrations run on boot. Read the release notes first, because schema changes move forward only. Rollback means restoring the dump with pg_restore --clean --if-exists and redeploying the previous tag, as in Epure upgrades.
Why does Epure on Coolify fail to start or keep me signed out?
Epure on Coolify fails in four common ways, and each one prints a specific message in the browser or in the epure container log. Open the service's logs in Coolify first, then match the line to a heading below. Most fixes are one variable and a redeploy; none requires deleting the postgres_data volume. Other options for running a tracker yourself are in self-hosted error tracking compared.
Login succeeds, then the login form comes back
The session cookie is Secure, so the browser drops it on plain HTTP. Open the https:// URL, not the server IP or port 8080, and check that Coolify issued a certificate for the domain.
example database passwords are not allowed unless EPURE_PUBLIC_URL is localhost
A database URL still carries epure, epure_ingest or epure_app as its password. This happens when the SERVICE_PASSWORD_64_* variables are empty or were replaced by hand. Restore the generated values and redeploy.
password authentication failed for user "epure"
Postgres sets its superuser password only when the postgres_data volume is first created. If SERVICE_PASSWORD_64_POSTGRES changed after that, put the original value back, or change the password inside Postgres to match. The ingest and app roles are reset from the URLs on every boot.
Browser errors are blocked by CORS
The template allows only the Epure URL by default. Add your app's origins to EPURE_CORS_ORIGINS, comma-separated, and redeploy. Server-side SDKs are not affected. More cases are in self-hosting troubleshooting.
Questions
Is the Coolify template the same Epure as the Docker Compose install?
postgres:16-alpine as the installation guide, with production settings: Secure cookies, no example passwords, and generated role passwords. The difference is that Coolify's proxy terminates HTTPS instead of the Caddy profile in deploy/docker-compose.prod.yml.Does self-hosted Epure on Coolify have an event limit?
Can I deploy Epure on Dokploy, Railway or Render instead?
deploy/templates/dokploy, a Railway compose file in deploy/railway and a render.yaml Blueprint at the root. Each runs the same two containers. The table in the installation guide lists the entry point for each platform.