2 minute read

Sentry is an open-source error and crash reporting platform. The cloud-hosted version is convenient, but has limitations: data leaves your infrastructure, and costs grow quickly with event volume. Self-hosting Sentry gives you full control over your data, no per-event pricing, and the ability to integrate with internal tools without exposing anything externally. This guide covers deploying Sentry on your own Ubuntu server with Nginx as a reverse proxy and a Let’s Encrypt SSL certificate.

1. Install Sentry

First, prepare your Ubuntu server by adding a user and installing Docker.

These are the minimum requirements for Sentry self-hosted:

  • 4 CPU Cores
  • 16 GB RAM + 16 GB swap
  • 20 GB Free Disk Space

1.1 Install from repository:

VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/getsentry/self-hosted/releases/latest)
VERSION=${VERSION##*/}
git clone https://github.com/getsentry/self-hosted.git
cd self-hosted
git checkout ${VERSION}
./install.sh

1.2 Update sentry/config.yml

Update system.url-prefix:

system.url-prefix: 'https://sentry.example.com'

Update email settings:

###############
# Mail Server #
###############

mail.backend: 'smtp'
mail.host: 'mail.smtp2go.com'
mail.port: 587
mail.username: '<USERNAME>'
mail.password: '<PWD>'

1.3 Update sentry/sentry.conf.py

Update CSRF:

CSRF_TRUSTED_ORIGINS = ["https://sentry.example.com"]

Enable SSL/TLS

###########
# SSL/TLS #
###########

# If you're using a reverse SSL proxy, you should enable the X-Forwarded-Proto
# header and enable the settings below

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
USE_X_FORWARDED_HOST = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SOCIAL_AUTH_REDIRECT_IS_HTTPS = True

1.4 Restart docker

docker composer down
docker composer up -d

2. Install Nginx

sudo apt install nginx certbot python3-certbot-nginx

2.2 Create ‘sentry’ nginx config:

sudo nano /etc/nginx/sites-available/sentry

set initial config:

server {
    listen 80;
    listen [::]:80;
    server_name sentry.example.com;
    root /var/www/html;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    location / {
        return 404;
    }
}

2.2 Check config file and reload server

sudo nginx -t
sudo systemctl reload nginx

2.3 Request certifcate

sudo mkdir -p /var/www/html
sudo certbot certonly --webroot -w /var/www/html -d sentry.example.com --email support@example.com --agree-tos --no-eff-email

2.4 Create dhparam:

sudo ls /etc/letsencrypt/ffdhe2048.txt || sudo curl -o /etc/letsencrypt/ffdhe2048.txt https://ssl-config.mozilla.org/ffdhe2048.txt

2.5 Set full nginx config:

sudo nano /etc/nginx/sites-available/sentry
error_log /var/log/nginx/error.log warn;

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name sentry.example.com;

    ssl_certificate     /etc/letsencrypt/live/sentry.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sentry.example.com/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache   shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_dhparam         /etc/letsencrypt/ffdhe2048.txt;
    ssl_protocols       TLSv1.3;
    ssl_prefer_server_ciphers off;

    add_header Strict-Transport-Security "max-age=63072000" always;

    client_max_body_size 100m;

    proxy_buffering   on;
    proxy_buffer_size 128k;
    proxy_buffers     4 256k;
    proxy_read_timeout 300s;
    proxy_send_timeout 300s;

    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,baggage always;

        include proxy_params;
        proxy_pass http://127.0.0.1:9000;
    }

    location / {
        include proxy_params;
        proxy_pass http://127.0.0.1:9000;
    }
}

server {
    listen 80;
    listen [::]:80;
    server_name sentry.example.com;
    root /var/www/html;

    location /.well-known/ {
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

2.6 Check nginx config and reload:

sudo nginx -t
sudo systemctl reload nginx
curl -I https://sentry.example.com

2.6 Restart sentry docker:

docker compose down
docker compose up -d