Sentry self-hosted na VPS
Sentry captura cada exceção da aplicação com stack trace completa, contexto do usuário, variáveis de ambiente e histórico de commits — tudo o que você precisa para reproduzir e corrigir um bug em produção sem depender de logs vagos. Self-hosteado, os dados de erro ficam na sua infraestrutura.
Instalar Sentry self-hosted
O Sentry tem um repositório oficial com docker-compose:
bash
# Requisitos mínimos: 4 vCPUs, 8 GB RAM, 20 GB disco
# (Sentry roda muitos containers internamente)
# Clonar e instalar:
git clone https://github.com/getsentry/self-hosted /opt/sentry
cd /opt/sentry
# Instalar (script interativo):
./install.sh
# O script vai:
# 1. Verificar dependências (Docker, docker-compose)
# 2. Gerar configurações e chaves
# 3. Criar banco de dados
# 4. Criar usuário admin
# Subir após instalação:
docker compose up -d
# Verificar containers rodando (são muitos!):
docker compose ps | grep -v "Exit"
# Porta padrão: 9000 (apenas local)
# Configurar Nginx como proxy:
# server_name sentry.seudominio.com.br → proxy_pass http://127.0.0.1:9000
# Atualizar Sentry:
cd /opt/sentry && git pull && ./install.shAtenção
Sentry self-hosted consome bastante recursos — mínimo real de 8 GB RAM para rodar confortavelmente. Para VPS com menos memória: use o Sentry Cloud (plano gratuito com 5k erros/mês) ou GlitchTip (alternativa leve ao Sentry).
Integrar com Node.js
Capturar exceções e erros não tratados:
typescript
// npm install @sentry/node @sentry/profiling-node
import * as Sentry from '@sentry/node'
import { nodeProfilingIntegration } from '@sentry/profiling-node'
Sentry.init({
dsn: 'https://CHAVE@sentry.seudominio.com.br/1',
environment: process.env.NODE_ENV,
release: process.env.GIT_COMMIT_SHA, // ligar erros a releases
// Performance monitoring:
tracesSampleRate: 0.1, // 10% das transações
profilesSampleRate: 0.1,
integrations: [
nodeProfilingIntegration(),
],
})
// Express — capturar erros de rotas:
app.use(Sentry.Handlers.requestHandler())
app.use(Sentry.Handlers.tracingHandler())
// ... suas rotas ...
// Sempre depois das rotas:
app.use(Sentry.Handlers.errorHandler())
// Capturar erro manualmente com contexto extra:
try {
await processarPagamento(pedido)
} catch (err) {
Sentry.withScope((scope) => {
scope.setUser({ id: userId, email: userEmail })
scope.setTag('pedido.id', pedido.id)
scope.setContext('pagamento', { valor: pedido.valor, metodo: pedido.metodo })
Sentry.captureException(err)
})
throw err
}Integrar com React (frontend)
Capturar erros do frontend e correlacionar com o backend:
typescript
// npm install @sentry/react
import * as Sentry from '@sentry/react'
import { BrowserTracing } from '@sentry/tracing'
Sentry.init({
dsn: 'https://CHAVE_FRONTEND@sentry.seudominio.com.br/2',
environment: import.meta.env.MODE,
release: import.meta.env.VITE_GIT_COMMIT,
integrations: [
new BrowserTracing({
tracePropagationTargets: ['api.seudominio.com.br'],
}),
],
tracesSampleRate: 0.1,
// Ignorar erros conhecidos de extensions do browser:
ignoreErrors: ['ResizeObserver loop limit exceeded', 'Non-Error promise rejection captured'],
})
// Envolver o App com ErrorBoundary:
root.render(
<Sentry.ErrorBoundary fallback={<p>Algo deu errado. Nossa equipe foi notificada.</p>}>
<App />
</Sentry.ErrorBoundary>
)
// Source maps para ver o stack trace real (TypeScript/minificado):
// vite.config.ts:
import { sentryVitePlugin } from '@sentry/vite-plugin'
export default defineConfig({
plugins: [
sentryVitePlugin({
org: 'minha-org',
project: 'frontend',
url: 'https://sentry.seudominio.com.br',
}),
],
build: { sourcemap: true },
})Configurar alertas e notificações
Alertar no Slack, email ou Telegram quando erros novos aparecem:
bash
# No Sentry — Settings → Integrations
# Integrar com Slack:
# 1. Settings → Integrations → Slack → Install
# 2. Configurar webhook ou app OAuth
# Alertas automáticos — Settings → Alerts → Create Alert Rule:
# Condição: "An issue is seen for the first time"
# Condição: "The issue count exceeds 100 in 1 hour"
# Ação: "Send a Slack notification" ou "Send an email"
# Integração com Telegram via webhook customizado:
# Settings → Integrations → Webhooks → Add
# URL: https://seu-servidor.com.br/sentry-webhook
# Eventos: issue.created, issue.resolved, issue.assigned
# Handler do webhook no Node.js:
app.post('/sentry-webhook', express.json(), async (req, res) => {
const { action, data } = req.body
if (action === 'created') {
const { issue } = data
await enviarTelegram(
`🐛 Novo erro no Sentry:\n${issue.title}\n${issue.culprit}\n${issue.permalink}`
)
}
res.sendStatus(200)
})Source maps e releases
Ligar erros minificados ao código fonte real via releases:
yaml
# Configurar releases no CI/CD para ligar erros a commits:
# No GitHub Actions — após o deploy:
- name: Criar release no Sentry
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: minha-org
SENTRY_PROJECT: minha-api
SENTRY_URL: https://sentry.seudominio.com.br
run: |
npx @sentry/cli releases new ${{ github.sha }}
npx @sentry/cli releases files ${{ github.sha }} \
upload-sourcemaps ./dist --url-prefix "~/dist"
npx @sentry/cli releases finalize ${{ github.sha }}
npx @sentry/cli releases deploys ${{ github.sha }} new \
-e production
# Resultado no Sentry:
# - Stack trace mostra TypeScript original (não o JS minificado)
# - "Introduced in commit abc123 by João Silva"
# - "Resolved in release 1.2.3"
# - Ver % de usuários afetados por cada erro$ runstack deploy --plan starter
Não quer configurar manualmente?
Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.