---
title: "Reverse Proxy"
url: https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy/
---

# Self-Hosted Reverse Proxy

Adding a reverse proxy in front of your Sentry deployment is strongly recommended for one big reason: you can fine tune every configuration to fit your current setup. A dedicated reverse proxy that does SSL/TLS termination that also forwards the client IP address as Docker Compose internal network (as this is [close to impossible to get otherwise](https://github.com/getsentry/self-hosted/issues/554)) would give you the best Sentry experience.

Once you have setup a reverse proxy to your Sentry instance, you should modify the `system.url-prefix` in the `config.yml` file to match your new URL and protocol. You should also update the SSL/TLS section in the `sentry/sentry.conf.py` script, otherwise you may get CSRF-related errors when performing certain actions such as configuring integrations.

Keep in mind that all this setup uses single-nodes for all services, including Kafka. For larger loads, you'd need a beefy machine with lots of RAM and disk storage. To scale up even further, you are very likely to use clusters with a more complex tool, such as Kubernetes. Due to self-hosted installations' very custom nature, we do not offer any recommendations or guidance around scaling up. We do what works for us for our thousands of customers over at [sentry.io](https://sentry.io/) and would love to have you over when you feel your local install's maintenance becomes a burden instead of a joy.

## [Enabling HTTPS](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#enabling-https)

We recommend TLS termination to be done on your own dedicated load balancer or proxy. Although you can set it on the `nginx.conf` file provided by the self-hosted installation, it is not recommended as newer self-hosted releases might alter some configurations on the file. Some examples are available on [Reverse Proxy Examples](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#reverse-proxy-examples) section.

## [Expose Only Ingest Endpoint Publicly](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#expose-only-ingest-endpoint-publicly)

Certain self-hosted deployments requires the dashboard to be accessed only via internal network. But, they also need to provide public Sentry ingestion endpoint for client devices such as mobile and desktop apps. You can expose some of these endpoints publicly:

* `/api/{project_id}/envelope/` - Main endpoint for submitting event from SDK.

* `/api/{project_id}/store/` - Legacy endpoint for submitting event from SDK, it is deprecated.

* `/api/{project_id}/security/` - Endpoint for submitting security-related reports.

* `/api/{project_id}/csp-report/` - Endpoint for submitting [CSP (Content Security Policy) reports](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP).

* `/api/{project_id}/nel/` - Endpoint for submitting [NEL (Network Error Logging)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/NEL) reports.

* `/api/{project_id}/minidump/` and `/api/{project_id}/minidump` - Endpoint for submitting minidump from native SDKs.

* `/api/{project_id}/events/{event_id}/attachments/` - Endpoint for submitting attachments.

* `/api/{project_id}/unreal/{sentry_key}` - Endpoint for submitting crash report from Unreal Engine SDK.

* `/api/{project_id}/cron` - Endpoint for submitting cron monitors from APIs. For more specific endpoints:

  * `/api/{project_id}/cron/{monitor_slug}/{sentry_key}/`
  * `/api/{project_id}/cron/{monitor_slug}/{sentry_key}`
  * `/api/{project_id}/cron/{monitor_slug}/`
  * `/api/{project_id}/cron/{monitor_slug}`

* `/api/{project_id}/integration/otlp` - Endpoint for submitting native OTLP dataset (traces, logs and metrics). For more specific endpoints:

  * `/api/{project_id}/integration/otlp/v1/traces` - Endpoint for submitting native OTLP dataset (traces).
  * `/api/{project_id}/integration/otlp/v1/traces/` - Endpoint for submitting native OTLP dataset (traces).
  * `/api/{project_id}/integration/otlp/v1/logs` - Endpoint for submitting native OTLP dataset (logs).
  * `/api/{project_id}/integration/otlp/v1/logs/` - Endpoint for submitting native OTLP dataset (logs).

The `{project_id}` placeholder should resolve to `[0-9]+` regular expression.

The `{event_id}`, `{monitor_slug}` and `{sentry_key}` placeholders should resolve to `[A-Za-z0-9-_+=]+` regular expression.

## [Rate Limiting](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#rate-limiting)

By default, Sentry does not handle rate limiting for any incoming request. On hosted version of Sentry (SaaS), it has a feature called [spike protection](https://docs.sentry.io/product/accounts/quotas/spike-protection/) which can protect you from event flood. The code for that module is not available on the public [sentry](https://github.com/getsentry/sentry) repository, it lives on the private getsentry repository instead.

For self-hosted deployment, it is recommended to have a rate limiter on your dedicated load balancer to prevent such things to happen. It is highly recommended than ever if you expose your Sentry instance publicly to the internet.

## [Health Checks](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#health-checks)

Endpoint for health checks is available on `/_health/` endpoint using HTTP protocol. This will return a 200 if Sentry is up or a 500 with the list of problems.

## [Reverse Proxy Examples](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#reverse-proxy-examples)

##### Note

If you run your reverse proxy as a Docker container, and place it on the same Docker Compose network as your Sentry instance, make sure to target `nginx:80` instead of `web:9000` in the examples below.

### [NGINX](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#nginx)

We recommend installing NGINX since that's what we are using on [sentry.io](https://sentry.io/).

```nginx
error_log /var/log/nginx/error.log warn;

# generated 2024-04-29, Mozilla Guideline v5.7, nginx 1.24.0, OpenSSL 3.0.13, modern configuration, no HSTS, no OCSP
# https://ssl-config.mozilla.org/#server=nginx&version=1.24.0&config=modern&openssl=3.0.13&hsts=false&ocsp=false&guideline=5.7
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate /etc/letsencrypt/live/sentry.yourcompany.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sentry.yourcompany.com/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    ssl_dhparam /etc/letsencrypt/ffdhe2048.txt;

    # modern configuration
    ssl_protocols TLSv1.3;
    ssl_prefer_server_ciphers off;

    proxy_buffering on;
    proxy_buffer_size    128k;
    proxy_buffers        4 256k;

    # Handle CORS-related headers for ingest endpoints.
    # You can also only expose the ingest endpoints only,
    # by removing the other `location` directive.
    #
    # It is recommended to put a rate limiter on the ingest endpoints.
    location ~ ^/api/[0-9]+/(envelope|minidump|security|store|unreal)/ {
        add_header Access-Control-Allow-Origin * always;
        add_header Access-Control-Allow-Credentials false always;
        add_header Access-Control-Allow-Methods GET,POST,PUT always;
        add_header Access-Control-Allow-Headers sentry-trace,baggage always;
        add_header Access-Control-Expose-Headers sentry-trace,headers always;
        include proxy_params;
        proxy_pass http://your-sentry-ip:9000;
    }

    location / {
        include proxy_params;
        proxy_pass http://your-sentry-ip:9000;
    }
}

server {
    server_name sentry.yourcompany.com;
    listen 80;
    listen [::]:80;

    root /var/www/html;
    # Allow certbot to do http-01 challenges
    location /.well-known/ {
        try_files $uri =404;
    }
    # otherwise redirect to HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}
```

To use NGINX with ACME server such as Let's Encrypt, refer to this [blog post by Nginx](https://www.nginx.com/blog/using-free-ssltls-certificates-from-lets-encrypt-with-nginx/).

It is also recommended to fine tune your NGINX for some performance benefits. You can refer to these blog posts from NGINX:

* [Tuning NGINX for Performance - NGINX](https://www.nginx.com/blog/tuning-nginx/)
* [Performance Tuning - Tips & Tricks - NGINX](https://www.nginx.com/blog/performance-tuning-tips-tricks/)

### [Caddy](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#caddy)

[Caddy](https://caddyserver.com/) is one alternative similar to NGINX that automatically handles TLS certificate management via ACME. After you [install Caddy](https://caddyserver.com/docs/install), modify your Caddy configuration file that reside on `/etc/caddy/Caddyfile`.

```caddyfile
sentry.yourcompany.com {
    # Handle CORS-related headers for ingest endpoints.
    # You can also only expose the ingest endpoints only,
    # by removing the other `handle` directive.
    #
    # It is recommended to put a rate limiter on the ingest endpoints.
    @ingest_endpoint path_regexp ^/api/[0-9]+/(envelope|minidump|security|store|unreal)/

    handle @ingest_endpoint {
        header {
            Access-Control-Allow-Origin *
            Access-Control-Allow-Credentials false
            Access-Control-Allow-Methods GET,POST,PUT
            Access-Control-Allow-Headers sentry-trace,baggage
            Access-Control-Expose-Headers sentry-trace,headers
        }

        reverse_proxy your-sentry-ip:9000 {
            health_uri /_health/
            health_status 2xx
            header_up Host {upstream_hostport}
        }
    }

    handle {
        reverse_proxy your-sentry-ip:9000 {
            health_uri /_health/
            health_status 2xx
            header_up Host {upstream_hostport}
        }
    }

    # By default, the TLS is acquired from Let's Encrypt
    tls name@yourcompany.com

    # If you have self-signed certificate
    # tls /path/to/server-certificate.crt /path/to/server-certificate.key

    header {
        # Delete "Server" header
        -Server
    }

    # To enable rate limiter, install additional module from
    # https://github.com/mholt/caddy-ratelimit
    # rate_limit {
    #     zone sentry {
    #         key {remote_host}
    #         window 1s
    #         events 100
    #     }
    # }
}
```

For detailed documentation on Caddyfile configuration, see [Caddy documentation](https://caddyserver.com/docs/caddyfile).

### [Traefik](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#traefik)

[Traefik](https://doc.traefik.io/traefik/) is another reverse proxy that provides a lot of plugin and integrations out of the box. It automatically handles TLS certificate management via ACME, too. After you [install Traefik](https://doc.traefik.io/traefik/getting-started/install-traefik/), add a configuration to Traefik as follows (this example is using the YAML file provider, convert to your preferred configuration provider as needed).

The configuration below is intended for Traefik v3 with a File Provider.

```yaml
http:
  routers:
    # Handle CORS-related headers for ingest endpoints.
    # You can also only expose the ingest endpoints only,
    # by removing the other `handle` directive.
    #
    # It is recommended to put a rate limiter on the ingest endpoints.
    sentry-ingest:
      entryPoints:
        - web # Assuming this your HTTP entrypoint
        - websecure # Assuming this is your HTTPS entrypoint
      service: sentry@file
      rule: "Host(`sentry.yourcompany.com`) && PathRegexp(`^/api/[0-9]+/(envelope|minidump|security|store|unreal)`)"
      tls:
        certResolver: letsencrypt # Assuming you have a TLS certificate resolver named "letsencrypt"
      middlewares:
        - https_redirect@file
        - cors_headers@file # For handling browser clients
        - rate_limiter@file
    sentry:
      entryPoints:
        - web # Assuming this your HTTP entrypoint
        - websecure # Assuming this is your HTTPS entrypoint
      service: sentry@file
      rule: "Host(`sentry.yourcompany.com`)"
      tls:
        certResolver: letsencrypt # Assuming you have a TLS certificate resolver named "letsencrypt"
      # Enable middleware as needed
      middlewares:
        - https_redirect@file

  services:
    sentry:
      loadBalancer:
        servers:
          - url: "http://your-sentry-ip:9000"
        healthCheck:
          scheme: http
          path: /_health/
          interval: 30s
          timeout: 10s
        passHostHeader: true

  middlewares:
    https_redirect:
      redirectScheme:
        scheme: "https"
        port: "443"
        permanent: true
    cors_headers:
      headers:
        customResponseHeaders:
          addVaryHeader: true
          # If you want to set this to true, adjust "accessControlAllowOriginList" to a valid domain and remove the asterisk wildcard
          accessControlAllowCredentials: false
          accessControlAllowOriginList:
            - "*"
          accessControlAllowHeaders:
            - "sentry-trace"
            - "baggage"
          accessControlAllowMethods:
            - GET
            - POST
            - PUT
          accessControlExposeHeaders:
            - "sentry-trace"
            - "baggage"
    rate_limiter:
      rateLimit:
        average: 100
        period: 1s
        burst: 150
```

### [HAProxy](https://develop.sentry.dev/self-hosted/production-enhancements/reverse-proxy.md#haproxy)

[HAProxy](https://www.haproxy.org/) is a high performance reverse proxy. This is the recommended reverse proxy to go when you have encountered network hiccups by using other reverse proxies due to its' performance. HAProxy requires external module to handles automatic TLS certificate management.

To install HAProxy, it is recommended to acquire it from your distribution package manager (apt or yum). See [their official distribution repositories](https://github.com/haproxy/wiki/wiki/Packages#official-distribution-repositories). Then, you should be able to configure your HAProxy configuration file that should be on `/etc/haproxy/haproxy.cfg`.

```haproxy
global
	# Your global configuration (may varies between version and Linux distributions)

defaults
    mode	http
    log     global
    option	httplog
    option	dontlognull
    option  forwardfor
    option  http-server-close
    option  http-keep-alive
    timeout connect 10s         # Connect timeout in 10s
    timeout client  30s         # Client timeout in 30s
    timeout server  30s         # Server timeout in 30s
    timeout http-keep-alive 2m  # HTTP keep alive in 2 minutes
    # Your remaining defaults configuration

frontend http_bind
    bind *:80 name http_port
    mode http

    acl sentry_domain hdr(host) -i sentry.yourcompany.com

    # HTTPS redirection
    http-request redirect scheme https code 301 if sentry_domain !{ ssl_fc }

    use_backend sentry


frontend https_bind
    bind *:443 ssl crt /etc/haproxy/certs/ name https_port
    mode http

    acl sentry_domain   hdr(host) -i sentry.yourcompany.com
    acl ingest_endpoint path_reg -i /api/[0-9]+/(envelope|minidump|security|store|unreal)/

    # Handle CORS-related headers for ingest endpoints.
    # You can also only expose the ingest endpoints only,
    # by removing the other `handle` directive.
    #
    # It is recommended to put a rate limiter on the ingest endpoints.
    use_backend sentry_ingest if sentry_domain ingest_endpoint

    use_backend sentry if sentry_domain

backend sentry_ingest
    mode http
    option httpchk
    server server1 your-sentry-ip:9000 check
    http-response set-header Access-Control-Allow-Origin *
    http-response set-header Access-Control-Allow-Credentials false
    http-response set-header Access-Control-Allow-Methods GET,POST,PUT
    http-response set-header Access-Control-Allow-Headers sentry-trace,baggage
    http-response set-header Access-Control-Expose-Headers sentry-trace,headers

backend sentry
    mode http
    option httpchk
    server server1 your-sentry-ip:9000 check
```

To use HAProxy with ACME server such as Let's Encrypt, refer to this [blog post by HAProxy](https://www.haproxy.com/blog/haproxy-and-let-s-encrypt).
