Skip to content

feat: report errors to self-hosted GlitchTip - #94

Merged
Skeyelab merged 1 commit into
masterfrom
feat/glitchtip-error-tracking
Sep 23, 2026
Merged

Skeyelab merged 1 commit into
masterfrom
feat/glitchtip-error-tracking

Conversation

@Skeyelab

Copy link
Copy Markdown
Member

Wires the Sentry SDK to the self-hosted GlitchTip instance at errors.ericdahl.dev, covering the client, server and edge runtimes.

Before this, server-side errors were reported nowhere. PostHog's capture_exceptions only covers the browser, so anything thrown in a route handler, server component or proxy.ts was invisible.

Approach

Shared options live in app/lib/observability/sentry-options.ts rather than being repeated across four init calls, which makes the behaviour testable without testing Sentry.init itself. 11 unit tests cover:

  • Disabled when no DSN is set, and always disabled under NODE_ENV=test, so local dev and CI never ship events.
  • The client reads only NEXT_PUBLIC_SENTRY_DSN, so a server-only SENTRY_DSN can never be inlined into the browser bundle.
  • release comes from Coolify's SOURCE_COMMIT, overridable via SENTRY_RELEASE.

Security note for review

SDK v11 changed the defaults here: dataCollection.cookies, httpHeaders, urlQueryParams and httpBodies all default to collected. This app carries Neon Auth session cookies and node auth tokens, so every category is turned off explicitly. This is the v11 replacement for the old sendDefaultPii: false, which no longer exists in the options type.

NEXT_PUBLIC_SENTRY_DSN is present in the client bundle by design — a DSN is a public, write-only ingest key, not a secret. It is not a credential leak.

Deliberately out of scope

  • relay.ts is not instrumented. It runs on users' own machines, so reporting their process errors into our GlitchTip would be a privacy problem.
  • PostHog is untouched, including capture_exceptions. Errors will land in both places for now; that is intentional so there is nothing to undo if GlitchTip disappoints.
  • The WebSocket server (server.ts / app/lib/ws/node-socket.ts) sits outside Next's request lifecycle, so onRequestError does not see it. Uncaught errors there are still caught by the SDK's global handlers, but anything caught-and-logged needs an explicit captureException to be reported.
  • Source map upload is disabled. Verified against the live instance that GlitchTip's chunk-upload endpoint advertises release_files and artifact_bundles, so the bundler plugin's upload path should work once an auth token and CI step exist. Follow-up, not this PR.

Deploy steps (after merge)

NEXT_PUBLIC_SENTRY_DSN must be added to the Coolify app as both build-time and runtime (matching how NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN is set) or it will be undefined in the bundle. Value is in Doppler as CLAWPROXY_GLITCHTIP_DSN.

Verification

  • yarn lint clean
  • yarn test:run — 302 tests, 69 files, all passing
  • yarn build passes with turbopack

Note withSentryConfig moved to @sentry/nextjs/config in v11; importing it from the package root fails at build time.

Adds the Sentry SDK pointed at the self-hosted GlitchTip instance at
errors.ericdahl.dev, covering client, server and edge runtimes. Server
errors had no reporting at all before this; PostHog only captured client
exceptions.

Shared options live in app/lib/observability/sentry-options.ts so the
behaviour is testable: disabled without a DSN (and always disabled under
test), client reads only NEXT_PUBLIC_SENTRY_DSN so no server-only DSN can
reach the bundle, and release comes from Coolify's SOURCE_COMMIT.

SDK v11 collects cookies, HTTP headers and query params by default. This
app carries Neon Auth session cookies and node auth tokens, so every
dataCollection category is turned off explicitly.

Replay and tracing are pinned off: GlitchTip implements neither fully.
Source map upload is disabled until an upload step and auth token exist.

PostHog is left untouched, including capture_exceptions.
@strix-security

strix-security Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Strix Security Review

No security issues found.

Review summary

Reviewed all changed files in this PR (the Sentry/GlitchTip wiring for client, server, and edge runtimes, the shared options module, Next.js config, dependency addition, and the unit tests; the yarn.lock diff is a lock file and was not treated as security-relevant). The review focused on the two sensitive-data risk areas this change introduces: what error payloads the SDK could transmit to the self-hosted GlitchTip instance, and whether any server-only configuration could leak into the browser bundle.

The data-collection controls were verified against the resolved @sentry/nextjs v11.0.0 dataCollection semantics: disabling userInfo, cookies, httpHeaders, urlQueryParams, and setting httpBodies: [] correctly suppresses these categories at both capture time and event-enrichment time, so Neon Auth session cookies and node auth tokens are not included in error reports. The remaining v11 default collection categories do not cause secret disclosure in this application (local-variable capture requires includeLocalVariables, which is not enabled; database/GraphQL/generative-AI/queue categories require integrations that are not added; and source-context-line capture only exposes already-public source code). DSN handling correctly prevents the server-only SENTRY_DSN from being inlined into the client bundle, and the client-bundle DSN is a public write-only ingest key rather than a credential. No hardcoded secrets were found in the changed code.

Updated for ab373ea.


Reviewed by Strix
Re-run review · Configure security review settings

@Skeyelab
Skeyelab merged commit a1b39c8 into master Sep 23, 2026
3 checks passed
@Skeyelab
Skeyelab deleted the feat/glitchtip-error-tracking branch September 23, 2026 20:17
Skeyelab added a commit that referenced this pull request Sep 23, 2026
PR #94 read the DSN through a helper that indexes process.env dynamically.
Next only substitutes literal `process.env.NEXT_PUBLIC_*` expressions when
building the client bundle, so the dynamic read survived into the browser as
undefined and Sentry disabled itself with no error. Verified against the
deployed site: the SDK shipped but the DSN string was absent, while PostHog's
token was inlined because it is referenced literally.

Server and edge runtimes were unaffected — they read process.env at runtime.

The client now passes literal references explicitly, and a guard test asserts
the literal is present and that the no-argument form is not used, since a unit
test cannot observe bundler substitution. Confirmed with a real build: a probe
DSN now appears in a client chunk.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant