Self-hosted error tracking in two containers
Docker Compose with exactly two services: a Rust ingest binary and PostgreSQL 16. No Redis, no Kafka, no worker fleet. Keep the official Sentry SDK and swap the DSN.
On this pageShowHide
Ops teams searching for docker compose two container error tracking postgres usually already know Sentry Cloud. What they want is a self-host shape they can reason about: how many images, which database, whether Redis is mandatory, and whether the official SDK still works.
This guide is the constraint narrative, not a RAM bake-off. For VPS memory floors see Self-hosted under 512 MB. For the roster see Sentry alternatives. Product install truth lives in Installation.
Why container count wins
Compose sprawl is the first failure mode on a small box. Each service is another image pull, another healthcheck, another thing that can refuse to start. Exception tracking does not need a queue broker if ingest can use an in-process queue and store sessions in Postgres.
- Self-hosted Sentry: 20+ containers, documented as a full observability stack (FSL self-host).
- GlitchTip: about four containers (web, worker, Postgres, Valkey) on MIT.
- Bugsink: one Django container, SQLite-first, Polyform Shield.
- Telebugs: one Rails + SQLite container, $299 appliance.
- Epure: two containers only. Rust binary + PostgreSQL 16. Apache 2.0.
The two-service stack
Documented laptop Compose (Compose v2) from the public product repo:
epure
- Image
- ghcr.io/epure-sh/epure:latest
- Ports (defaults)
- host EPURE_PORT → 8080 (default 8080)
postgres
- Image
- postgres:16-alpine
- Ports (defaults)
- host POSTGRES_HOST_PORT → 5432 (default 5433)
| Dimension | Image | Ports (defaults) |
|---|---|---|
| epure | ghcr.io/epure-sh/epure:latest | host EPURE_PORT → 8080 (default 8080) |
| postgres | postgres:16-alpine | host POSTGRES_HOST_PORT → 5432 (default 5433) |
No .env required for localhost:8080. Pin a tag with EPURE_IMAGE. Production uses a separate overlay and HTTPS in front; do not publish the laptop compose file.
What ships inside that binary: exception events and breadcrumbs, JS/TS source map demangle, Issues triage, releases, webhooks. What does not ship as Epure features: tracing/APM, session replay, profiling, generic logs (Welcome).
No Redis on purpose
Installation FAQ: do you need Redis? No. The stack is two containers. Welcome FAQ: do you need Redis or Kafka? No. Ingest uses an in-process Tokio queue; sessions live in Postgres (Installation, Welcome, Configuration).
Rate limits are also in-process on the Rust binary (spike valve and hourly project cap). There is no Redis-backed global rate limiter (API Errors). Soft-sample flood behavior is covered in Spike valve flood.
Scoreboard
Containers
- Sentry
- 20+
- GlitchTip
- ~4
- Bugsink
- 1
- Telebugs
- 1
- Epure
- 2
Default DB
- Sentry
- Postgres (+ more)
- GlitchTip
- Postgres
- Bugsink
- SQLite (Postgres optional)
- Telebugs
- SQLite
- Epure
- PostgreSQL 16
Broker / cache
- Sentry
- Full fleet
- GlitchTip
- Valkey in the install
- Bugsink
- None required
- Telebugs
- None required
- Epure
- None (no Redis/Kafka)
License
- Sentry
- FSL self-host / Cloud prop.
- GlitchTip
- MIT
- Bugsink
- Polyform Shield
- Telebugs
- $299 appliance
- Epure
- Apache 2.0
SDK path
- Sentry
- Native
- GlitchTip
- DSN swap
- Bugsink
- DSN swap
- Telebugs
- DSN swap
- Epure
- DSN swap
| Dimension | Sentry | GlitchTip | Bugsink | Telebugs | Epure |
|---|---|---|---|---|---|
| Containers | 20+ | ~4 | 1 | 1 | 2 |
| Default DB | Postgres (+ more) | Postgres | SQLite (Postgres optional) | SQLite | PostgreSQL 16 |
| Broker / cache | Full fleet | Valkey in the install | None required | None required | None (no Redis/Kafka) |
| License | FSL self-host / Cloud prop. | MIT | Polyform Shield | $299 appliance | Apache 2.0 |
| SDK path | Native | DSN swap | DSN swap | DSN swap | DSN swap |
Public docs as of 2026-09 (Sentry self-host, GlitchTip install, Bugsink, Telebugs, Epure Installation / Welcome). Idle RAM omitted here; remasure before claiming.
Local compose path
From Quickstart / Installation:
git clone https://github.com/epure-sh/epure.git && cd epure && docker compose up
Health: curl -sS http://localhost:8080/health → {"status":"ok"}. Dashboard at http://localhost:8080. Register, create a project, copy the DSN from setup or Settings → SDK connection.
Point @sentry/browser@7.120.0 or @sentry/node@7.120.0 (Quickstart pins) at that DSN. Set traces, replay, and profile sample rates to 0. Ingest returns HTTP 202 before the Issues row appears. Wire honesty: Sentry SDK compatible.
If 8080 is taken: cp .env.example .env, set EPURE_PORT, recreate epure. Host tools talk to Postgres on **5433** by default, not 5432 (Configuration).
Production path
Production is a separate path: ./configure --prod (or .env.production.example), compose overlay, fresh Postgres volume, HTTPS reverse proxy in front of 127.0.0.1:8080. Do not reuse a laptop data directory. Do not publish the laptop compose file with example passwords on a public hostname (Installation).
- Set
EPURE_PUBLIC_URLtohttps://…(must be https). - Set
EPURE_CORS_ORIGINSto your app origins (not*). - Replace every
CHANGE_MEpassword; overlay refuses example passwords. - Forward
Host,X-Forwarded-For,X-Forwarded-Proto; allow POST/OPTIONS on envelope and store. - Confirm
GET /health→{"status":"ok"}on the public origin.
Limitations
- Exception-only. No tracing, replay, profiling, or generic logs product.
- JS/TS sourcemaps via
@sentry/cli; other languages group on raw frames. - Two containers beat Sentry and GlitchTip on count; Bugsink/Telebugs still win one-container SQLite ops.
- Idle RAM figures are omitted here (dated sources conflict). Re-measure on your box before quoting.
- This is not protocol parity with Sentry Cloud.
Pick Epure if
- The brief is exactly two Compose services plus PostgreSQL 16.
- You refuse Redis and Kafka in the error stack.
- Counsel wants Apache 2.0 and a DSN swap on official Sentry SDKs.
- You will set traces, replay, and profile sample rates to 0.
Pick another tool if
- Replay or APM is the daily debug loop: stay on Sentry.
- MIT plus Django/Valkey is already home: GlitchTip.
- One SQLite container is the ops model: Bugsink (or Telebugs at $299).
- You are shopping RAM floors only: Self-hosted under 512 MB.
Install: Installation. Marketing path: Self-host. Clone: GitHub.