Zum Hauptinhalt springen
S-EDV news
← Alle Anleitungen
📘 Anleitung Docker 10.10.2026 · 11 min Lesezeit

Bugsink mit Docker Compose: Sentry-kompatibles Error-Tracking selbst hosten

Bugsink ist ein schlanker Error-Tracker, der die Sentry-SDKs versteht. Diese Anleitung zeigt die Installation von Bugsink 2.6.1 mit Docker Compose und PostgreSQL, Team und Projekt, erste Fehler per Python-SDK und curl, Reverse Proxy mit TLS, Backup mit Restore, Updates und typische Fehlermeldungen. Dazu ein ehrlicher Blick auf die PolyForm-Shield-Lizenz.

Geprüft am 10.10.2026 · für Bugsink 2.6.1, PostgreSQL 17.11, sentry-python 2.71.0

Mit KI erstellt – redaktionelle Prüfung ausstehend

WerbelinksMit * markierte Links sind Werbelinks: Bei einem Kauf erhalten wir eine Provision, der Preis bleibt gleich. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Mehr dazu

Illustration mit der Überschrift Bugsink selbst hosten, Symbolen für Fehler, Datenbank und Sicherheit sowie einem stilisierten Fehler-Dashboard

Von Fehlern in eigener Software erfahren Admins oft erst durch Anwender. Ein Error-Tracker sammelt Ausnahmen samt Stacktrace, Release und Umgebung zentral und gruppiert gleiche Fehler zu einem Issue. Bugsink ist eine schlanke Alternative zu selbst gehostetem Sentry: Es versteht die Sentry-SDKs, läuft als ein einziger Container neben einer Datenbank und kommt im Leerlauf mit rund 350 MB RAM aus. Diese Anleitung zeigt die Installation von Bugsink 2.6.1 mit Docker Compose und PostgreSQL, den ersten Fehlerbericht per SDK und curl, Reverse Proxy, Backup mit Restore sowie Updates.

Voraussetzungen

Bugsink stellt geringe Anforderungen. Im Test belegte der Bugsink-Container nach dem Start 312 MiB RAM, PostgreSQL 38 MiB. Das Image ist etwa 346 MB groß und laut Doku für amd64 und arm64 verfügbar.

  • Linux-Server oder VM mit 1 bis 2 CPU-Kernen und 2 GB RAM, x86_64 oder ARM64
  • 5 GB freier Speicher für Images und Datenbank, mehr bei vielen Ereignissen
  • Docker Engine mit Docker Compose v2
  • Eine Subdomain wie bugsink.example.de mit TLS-Reverse-Proxy (Nginx, Caddy oder Traefik)
  • Optional ein SMTP-Konto für Benachrichtigungen und Passwort-Resets

Schritt 1: Version, Image und Lizenz prüfen

Das Projekt liegt auf GitHub unter bugsink/bugsink und hatte am 10.10.2026 laut GitHub-API 2118 Sterne, der letzte Push stammt vom 08.10.2026. Aktuell ist Release 2.6.1 vom 25.09.2026. Auf Docker Hub zeigen die Tags 2.6.1, 2.6, 2 und latest auf denselben Digest. Schreiben Sie trotzdem eine konkrete Version fest, damit ein Neustart nicht unbemerkt ein Update zieht.

EckdatenWert
Imagebugsink/bugsink:2.6.1, Datenbank postgres:17-alpine
Port8000 (Gunicorn im Container)
Volumedb-data für PostgreSQL, Bugsink selbst ist zustandslos
Wichtige VariablenSECRET_KEY, DATABASE_URL, BASE_URL, BEHIND_HTTPS_PROXY, CREATE_SUPERUSER, PHONEHOME
Healthcheck/health/ready, im Image bereits hinterlegt
Prozessnutzerbugsink (UID 14237), kein root
LizenzPolyForm Shield 1.0.0, Teile unter BSD-3 und MIT

GitHub zeigt als Lizenz nur NOASSERTION, weil die Datei LICENSE mehrere Lizenzen kombiniert. Der Kern steht unter der PolyForm Shield License 1.0.0. Sie erlaubt jede Nutzung, auch kommerziell und im Unternehmen, mit einer Ausnahme: Sie dürfen kein Produkt anbieten, das mit Bugsink oder einem Angebot des Herstellers konkurriert. Interne Fehlererfassung für die eigene Software ist damit abgedeckt, ein gehosteter Error-Tracking-Dienst für Dritte nicht.

Verifizieren: docker pull bugsink/bugsink:2.6.1 lädt das Image ohne Fehler. Nach dem Start gibt das Log in der ersten Zeile nach bugsink-show-version die Version 2.6.1 aus.

Schritt 2: Projektordner, compose.yaml und .env anlegen

Die Vorlage orientiert sich an der offiziellen docker-compose-sample.yaml, verlagert aber alle Geheimnisse in eine .env-Datei, bindet den Port nur an localhost und ergänzt PHONEHOME. Bugsink unterstützt auch MySQL; SQLite empfiehlt der Hersteller im Container nur für Wegwerf-Instanzen, weil Docker-Volumes die Garantien für den WAL-Modus nicht zusichern.

mkdir -p /opt/bugsink && cd /opt/bugsink
services:
  db:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: bugsink
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: bugsink
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U bugsink -d bugsink"]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 10s

  web:
    image: bugsink/bugsink:${BUGSINK_VERSION:-2.6.1}
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
    ports:
      - "127.0.0.1:8000:8000"
    environment:
      SECRET_KEY: ${SECRET_KEY}
      CREATE_SUPERUSER: ${CREATE_SUPERUSER}
      PORT: 8000
      DATABASE_URL: postgresql://bugsink:${POSTGRES_PASSWORD}@db:5432/bugsink
      BASE_URL: ${BASE_URL}
      SITE_TITLE: ${SITE_TITLE:-Bugsink}
      PHONEHOME: ${PHONEHOME:-true}
      BEHIND_HTTPS_PROXY: ${BEHIND_HTTPS_PROXY:-false}
    healthcheck:
      test: ["CMD-SHELL", "python -c 'import requests; requests.get(\"http://localhost:8000/health/ready\").raise_for_status()'"]
      interval: 10s
      timeout: 20s
      retries: 10
      start_period: 20s

volumes:
  db-data:

Die passende .env enthält nur Platzhalter. Nutzen Sie für das Datenbankpasswort Hex-Zeichen, denn @ oder / würden DATABASE_URL zerlegen.

BUGSINK_VERSION=2.6.1
# openssl rand -hex 24
POSTGRES_PASSWORD=bitte-ersetzen
# openssl rand -hex 32 (mindestens 50 Zeichen)
SECRET_KEY=bitte-ersetzen
CREATE_SUPERUSER=admin@example.de:bitte-ersetzen
BASE_URL=https://bugsink.example.de
SITE_TITLE=Bugsink
PHONEHOME=false
BEHIND_HTTPS_PROXY=true
chmod 600 .env

BASE_URL bestimmt, unter welcher Adresse Bugsink Links und DSNs erzeugt, und füllt zugleich die Liste erlaubter Hostnamen. PHONEHOME steht ab Werk auf true und meldet Version und Nutzerzahlen an bugsink.com; mit false bleibt die Instanz still.

Verifizieren: docker compose config --quiet endet ohne Ausgabe. Meldet Compose eine Warnung zu einer nicht gesetzten Variable, fehlt der Eintrag in der .env.

Schritt 3: Stack starten und Healthchecks prüfen

docker compose up -d
docker compose ps
docker compose logs web | head -20

Beim Start führt Bugsink zuerst bugsink-manage check --deploy --fail-level WARNING aus und spielt danach die Migrationen ein. Ein zu kurzer SECRET_KEY verhindert deshalb den Start. Im Test erschien mit einem zu kurzen Schlüssel:

?: (security.W009) Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed with 'django-insecure-' ...
SystemCheckError: System check identified some issues:

Verifizieren: Nach etwa 20 Sekunden zeigt docker compose ps beide Dienste als Up (healthy). curl -I http://127.0.0.1:8000/accounts/login/ antwortet auf dem Server selbst mit 200.

Schritt 4: Reverse Proxy und TLS einrichten

Stacktraces enthalten Variableninhalte und oft personenbezogene Daten, deshalb gehört Bugsink hinter HTTPS. Der Proxy muss den originalen Host, das Schema und die Client-IP weiterreichen. Eine Nginx-Konfiguration nach den Vorgaben der Proxy-Doku:

server {
    listen 443 ssl;
    server_name bugsink.example.de;
    # ssl_certificate und ssl_certificate_key wie bei Ihren anderen Diensten

    client_max_body_size 20m;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

In der .env gehört dann BEHIND_HTTPS_PROXY=true. Er aktiviert sichere Cookies und wertet X-Forwarded-Proto und X-Real-IP aus.

Kommt eine Anfrage mit einem Hostnamen an, der nicht zu BASE_URL passt, antwortet Bugsink mit HTTP 400 und schreibt ins Log:

django.core.exceptions.DisallowedHost: 'Host: 203.0.113.10' as sent by browser/proxy not in ALLOWED_HOSTS=['bugsink.example.de', 'localhost', '127.0.0.1'].

Verifizieren: curl -I https://bugsink.example.de/accounts/login/ liefert 200. Ein Aufruf über die IP-Adresse liefert dagegen 400.

Schritt 5: Erstkonfiguration mit Team und Projekt

Melden Sie sich mit der E-Mail-Adresse und dem Passwort aus CREATE_SUPERUSER an. Entfernen Sie die Variable danach aus der .env, damit das Passwort nicht im Klartext liegt. Ohne SMTP blendet Bugsink den Hinweis ein, dass keine E-Mails versendet werden; für Alarme tragen Sie EMAIL_HOST, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD und EMAIL_PORT in der compose.yaml nach. Alarme verschickt Bugsink bei neuen Issues, Regressionen und aufgehobenen Stummschaltungen, wahlweise per E-Mail oder an Slack, Mattermost, Discord, Microsoft Teams, Telegram und eigene Webhooks.

  1. Unter Teams mit New Team ein Team anlegen, etwa Entwicklung.
  2. Unter Projects mit New Project ein Projekt anlegen, das Team zuordnen und einen Namen wie shop-backend vergeben.
  3. Die Vorgabe von 10.000 gespeicherten Ereignissen je Projekt bei Bedarf anpassen.
Bugsink-Seite Connect your application mit DSN des neuen Projekts und Links zu Python, JavaScript, PHP und Go
Nach dem Anlegen des Projekts zeigt Bugsink den DSN, den Sie in Ihrer Anwendung eintragen (Schlüssel unkenntlich gemacht).

Der DSN darf nur Ereignisse einliefern. Für die REST-API legen Sie unter Tokens eigene Bearer-Tokens an.

Verifizieren: Nach dem Speichern leitet Bugsink auf die Seite Connect your application weiter und zeigt einen DSN der Form https://SCHLÜSSEL@bugsink.example.de/1.

Schritt 6: Erste Fehler senden

Für den Funktionsnachweis brauchen Sie keine Anwendung. Ein Sentry-Envelope per curl genügt:

KEY=0123456789abcdef0123456789abcdef   # Teil vor dem @ im DSN
EVT=$(cat /proc/sys/kernel/random/uuid | tr -d -)
printf '{"event_id":"%s"}\n{"type":"event"}\n{"event_id":"%s","platform":"other","level":"error","message":"Testfehler per curl"}\n' \
  "$EVT" "$EVT" > envelope.txt
curl -s -w ' %{http_code}\n' \
  -H 'Content-Type: application/x-sentry-envelope' \
  -H "X-Sentry-Auth: Sentry sentry_version=7, sentry_key=$KEY" \
  --data-binary @envelope.txt https://bugsink.example.de/api/1/envelope/

Bugsink quittiert mit {"id": "…"} 200. Mit falschem Schlüssel lautet die Antwort Project not found or key incorrect und HTTP 403. Prüfen Sie in Skripten deshalb den Statuscode und nicht nur den Exit-Code von curl.

Realistischer ist das offizielle Python-SDK. Im Test lief sentry-sdk 2.71.0 mit diesem Skript:

pip install sentry-sdk
export SENTRY_DSN='https://SCHLÜSSEL@bugsink.example.de/1'
import os, sentry_sdk
sentry_sdk.init(dsn=os.environ["SENTRY_DSN"], release="shop-backend@1.4.2", environment="test")

def berechne_rabatt(preis, prozent):
    return preis / prozent

try:
    berechne_rabatt(100, 0)
except Exception as e:
    print("event_id", sentry_sdk.capture_exception(e))
sentry_sdk.flush(5)

Bestehende Anwendungen brauchen nur den neuen DSN.

Bugsink-Issueliste des Projekts shop-backend mit einem ZeroDivisionError und einer per curl gesendeten Testmeldung
Beide Testereignisse sind als eigene Issues angekommen: links die Python-Ausnahme, darunter die Meldung aus dem curl-Aufruf.
Bugsink-Issueansicht eines ZeroDivisionError mit Quelltextausschnitt, markierter Zeile und lokalen Variablen preis und prozent
Der Stacktrace zeigt die fehlerhafte Zeile samt lokaler Variablen. Genau diese Werte machen die Fehlersuche schnell.

Verifizieren: Unter Issues erscheinen beide Ereignisse als SHOP-BACKEND-1 und SHOP-BACKEND-2. In der Detailansicht des ZeroDivisionError stehen Zeile 4 und die Variablen preis = 100 und prozent = 0.

Schritt 7: Backup und Restore

Bugsink speichert in der Standardkonfiguration Issues und Ereignisse in der Datenbank; der Container selbst hält keine Nutzdaten. Ein Dump von PostgreSQL ist daher das vollständige Backup. Sichern Sie zusätzlich .env und compose.yaml, denn ohne den alten SECRET_KEY werden alle Sitzungen ungültig.

docker compose exec -T db pg_dump -U bugsink -d bugsink -Fc > bugsink-$(date +%F).dump

Für den Restore stoppen Sie Bugsink, legen die Datenbank neu an und spielen den Dump ein:

docker compose stop web
docker compose exec -T db psql -U bugsink -d postgres \
  -c "DROP DATABASE bugsink;" -c "CREATE DATABASE bugsink OWNER bugsink;"
docker compose exec -T db pg_restore -U bugsink -d bugsink --no-owner --exit-on-error < bugsink-2026-10-10.dump
docker compose start web

Im Test war der Dump mit zwei Issues 143 KB groß. Nach dem Löschen enthielt die Datenbank keine einzige Tabelle mehr, nach dem Restore waren beide Issues samt Stacktrace wieder da. Dank unverändertem SECRET_KEY blieb sogar die Browsersitzung gültig.

Verifizieren: docker compose exec -T db psql -U bugsink -d bugsink -Atc "select count(*) from issues_issue" liefert dieselbe Zahl wie vor dem Backup, docker compose ps zeigt web wieder als healthy.

Schritt 8: Updates und Rollback

Das Image führt beim Start automatisch alle Migrationen aus. Ein Update besteht daher aus einem Dump, der neuen Versionsnummer in der .env und einem Neustart:

docker compose exec -T db pg_dump -U bugsink -d bugsink -Fc > vor-update.dump
sed -i 's/^BUGSINK_VERSION=.*/BUGSINK_VERSION=2.6.1/' .env
docker compose pull web && docker compose up -d

Im Test wechselte der Stack von 2.6.1 auf 2.6.0 und zurück, jeweils mit No migrations to apply und healthy. Liegt eine Schemaänderung dazwischen, gehört zum Rollback zusätzlich der Dump von vor dem Update.

Verifizieren: docker compose ps zeigt das neue Image-Tag, das Log beginnt mit der neuen Versionsnummer, und die Issueliste ist unverändert.

Schritt 9: Bugsink vollständig entfernen

Achtung: Der folgende Befehl löscht das Datenbank-Volume und damit alle Issues, Ereignisse, Nutzer und Tokens unwiderruflich. Erstellen Sie vorher einen Dump, falls Sie die Daten noch brauchen.

cd /opt/bugsink
docker compose down -v
docker image rm bugsink/bugsink:2.6.1 postgres:17-alpine
cd / && rm -rf /opt/bugsink

Entfernen Sie danach den vHost im Proxy und die DSNs aus Ihren Anwendungen.

Verifizieren: docker ps -a und docker volume ls zeigen keine Einträge mit bugsink mehr.

Troubleshooting

  • Container startet nicht, SystemCheckError security.W009: SECRET_KEY ist kürzer als 50 Zeichen oder beginnt mit django-insecure. Neuen Schlüssel erzeugen und docker compose up -d ausführen.
  • HTTP 400 mit DisallowedHost im Log: Der Proxy reicht nicht den Hostnamen aus BASE_URL weiter. proxy_set_header Host $host setzen oder BASE_URL korrigieren.
  • CSRF-Fehler mit dem Hinweis wrong scheme: X-Forwarded-Proto fehlt oder BEHIND_HTTPS_PROXY steht nicht auf true.
  • HTTP 403 Project not found or key incorrect: Schlüssel oder Projektnummer im DSN stimmen nicht. DSN erneut aus der Projektseite kopieren.
  • Große Ereignisse kommen nicht an: Bugsink nimmt standardmäßig Ereignisse bis 1 MB an. Prüfen Sie zusätzlich client_max_body_size im Proxy.

Häufige Fragen

Funktionieren meine bestehenden Sentry-Integrationen?

Für das Einliefern von Fehlern ja, die SDKs sprechen dasselbe Protokoll. Bugsink konzentriert sich aber auf Error-Tracking. Performance-Tracing, Session-Replays und Profiling von Sentry bildet es nicht ab.

Reicht SQLite für kleine Teams?

Außerhalb von Containern ja. Im Docker-Betrieb rät der Hersteller wegen des WAL-Modus auf Volumes davon ab.

Darf ich Bugsink im Unternehmen kostenlos nutzen?

Für die interne Fehlererfassung erlaubt die PolyForm Shield License die Nutzung. Ausgeschlossen ist ein Angebot, das mit Bugsink konkurriert, etwa Error-Tracking als Dienstleistung für Kunden.

Wie halte ich die Datenbank klein?

Jedes Projekt hat eine Obergrenze für gespeicherte Ereignisse, ab Werk 10.000. Ist sie erreicht, verdrängt Bugsink nach einem Relevanzverfahren vor allem alte und sehr häufige gleichartige Ereignisse. Zusätzlich begrenzen Ratenlimits je Projekt den Zustrom, bei Überschreitung antwortet der Server mit HTTP 429.

Was ist mit Datenschutz?

Fehlerberichte können IP-Adressen, Nutzerkennungen und Formulardaten enthalten. Der Selbstbetrieb hält diese Daten im eigenen Haus. Der Hersteller empfiehlt für selbst gehostete Instanzen sogar send_default_pii=True, um mehr Kontext zu erhalten. Wägen Sie das gegen Ihre Datenschutzvorgaben ab.

Fazit

Bugsink liefert den Kern von Sentry, nämlich gruppierte Fehler mit Stacktrace und Variablen, in einem Paket, das auf jedem kleinen Docker-Host Platz findet. Installation, erster Fehlerbericht und Restore funktionierten im Test ohne Umwege. Wer kein Tracing braucht und mit der Shield-Lizenz leben kann, bekommt für die eigene Softwareentwicklung ein sehr pflegeleichtes Werkzeug.

Weiterführende Anleitungen und Quellen

BugsinkError-TrackingSentryDocker ComposeSelfhostingPostgreSQLBackup