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.

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:
-
--pgx-conn may be empty - pgx will then use environment variables, see for details:
-
when using PgBouncer, set --pgx-conn with the default_query_exec_mode option set to exec or simple_protocol,
e.g. postgres://user:pass@host:5432/sentry?default_query_exec_mode=exec.
See for details:
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.
| 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
- Client sends request to the proxy.
- 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.
- The proxy client injects the Sentry
Authorization header and forwards the
request to the upstream Sentry instance.
- On
401 Unauthorized, the proxy automatically renews the token and retries
once (only when using the system token — static tokens are not renewable).
- Response headers are sanitized and the upstream response is relayed back to
the 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