Skip to content

rockdrilla/sentry-api-proxy

Repository files navigation

sentry-api-proxy

A lightweight HTTP reverse proxy for Sentry that authenticates outgoing requests with a Sentry API token. Designed for internal use — sits between Sentry clients and the Sentry API, handling token management transparently.

build-status goreport docker-pulls license

Features

  • Token-aware proxying — Automatically injects Authorization: Bearer <token> into proxied requests.
  • Dual token modes:
    • Static token — A pre-configured Sentry API token.
    • System token — Fetches the Sentry internal system token directly from the Sentry PostgreSQL database and renews it automatically in the background.
  • Request isolation — Each request gets a fresh connection; no keep-alives. Simplifies resource management for an internal proxy.
  • Header sanitization — Strips potentially problematic request/response headers to ensure isolation between client and upstream.
  • JSON-aware error responses — Returns JSON errors when the client Accept header indicates JSON preference; falls back to plain text otherwise.
  • Alias tokens — When configured, only requests with matching bearer tokens go through the proxy client (with Sentry token injection); all other requests are forwarded as-is without additional authentication enforcement. When no alias tokens are configured, every request goes through the proxy client with the Sentry token. Useful for restricting which clients can access the Sentry API with elevated credentials.

Usage

Command-line flags

Flag Default Description
--listen 0.0.0.0:8080 Listen endpoint (addr:port).
--sentry-uri http://sentry-web:9000 Upstream Sentry base URI.
--token system Sentry API token, or "system" for DB-fetched token.
--pgx-conn (empty) PostgreSQL connection string (used only with system token).
--alias-token (empty) Semicolon-separated list of alias bearer tokens.

Notes:

Environment variables

Each flag has a corresponding environment variable:

Variable Equivalent Flag
LISTEN --listen
SENTRY_URI --sentry-uri
SENTRY_TOKEN --token
PGX_CONN --pgx-conn
ALIAS_TOKENS --alias-token

Examples

Using a static token:

sentry-api-proxy \
  --listen 0.0.0.0:8080 \
  --sentry-uri http://sentry:9000 \
  --token sntry_abc123...

Using the Sentry system token (fetched from PostgreSQL):

sentry-api-proxy \
  --listen 0.0.0.0:8080 \
  --sentry-uri http://sentry-web:9000 \
  --token system \
  --pgx-conn "postgres://sentry:sentry@localhost:5432/sentry"

With alias tokens (only allowed tokens get Sentry authentication):

sentry-api-proxy \
  --listen 0.0.0.0:8080 \
  --sentry-uri http://sentry:9000 \
  --token sntry_abc123... \
  --alias-token "app-token-1;app-token-2"

Build

make

The binary is statically linked with CGO disabled. HTTP/2 support is stripped from the build (nethttpomithttp2 build tag) to reduce binary size.

Docker

docker build -t sentry-api-proxy .

The Docker image is based on gcr.io/distroless/static-debian13:nonroot and runs as a non-root user.

Build tags

Tag Effect
nethttpomithttp2 Excludes HTTP/2 from net/http.
nopgxregisterdefaulttypes Reduces binary size (see pgx docs).

Development build

Enables the race detector and CGO:

make dev-build

Architecture

┌────────┐     ┌──────────────────┐     ┌────────┐
│ Client │────▶│ sentry-api-proxy │────▶│ Sentry │
└────────┘     └──────────────────┘     └────────┘
                        │
                        ▼
                  ┌────────────┐
                  │ PostgreSQL │
                  │ (optional) │
                  └────────────┘

Request flow

  1. Client sends request to the proxy.
  2. Proxy checks for alias tokens — if alias tokens are configured, only requests with a matching bearer token go through the proxy client (with Sentry token injection). All other requests go through the bypass client (forwarded as-is, without additional authentication enforcement). If no alias tokens are configured, every request goes through the proxy client.
  3. The proxy client injects the Sentry Authorization header and forwards the request to the upstream Sentry instance.
  4. On 401 Unauthorized, the proxy automatically renews the token and retries once (only when using the system token — static tokens are not renewable).
  5. Response headers are sanitized and the upstream response is relayed back to the client.

Headers stripped by the proxy client

Common request headers:

Header Reason
Accept-Encoding Prevent client-specific encoding.
Accept-Language Prevent client-specific language.
Connection Managed by the proxy (set to close).
Expect Not supported for proxied requests.
Forwarded Cleared to avoid conflicts.
Host Set by the upstream URL.
Proxy-Authorization Proxy authentication, not forwarded.
Te Trailer encoding, not used.
Upgrade Protocol upgrades not supported.
Via Cleared to avoid conflicts.
X-Forwarded-For Cleared to avoid conflicts.
X-Forwarded-Host Cleared to avoid conflicts.
X-Forwarded-Proto Cleared to avoid conflicts.

Common response headers:

None currently. The list will be expanded as needed.

Request headers specific to proxy:

Header Reason
Authentication Cleared to avoid conflicts.
Authorization Replaced by proxy's own token.
Cookie Session isolation.

Response headers specific to proxy:

Header Reason
Set-Cookie Prevent upstream cookies leaking to client.
Www-Authenticate Strip upstream authentication challenges from proxied responses.

Timeouts

Timeout Value
ReadTimeout 25s
ReadHeaderTimeout 10s
WriteTimeout 25s

Keep-alives are disabled — each request gets a new connection.

Token providers

Provider Source Renewable Background refresh
StaticToken Pre-configured string No No
SystemToken PostgreSQL query Yes Yes (every ~15 min)

The system token is fetched from Sentry's own database:

SELECT value FROM sentry_option WHERE key = 'sentry:system-token';

It is refreshed in the background when its lifetime exceeds half of systemTokenLifeTime (30 minutes).

License

Apache 2.0 | spdx.org | opensource.org

About

A lightweight HTTP reverse proxy for Sentry API

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors