Hello! Thank you for considering contributing to the self-hosted project. That means a lot to us.
This repository packages Sentry and its supporting services for self-hosted deployment. Changes that belong here are changes to the packaging and operating surface: Docker Compose wiring, install and upgrade scripts, default config templates, optional self-hosted patches, and tests for those workflows. If your fix only requires changing image contents rather than this repo's packaging, open or route it upstream and link that context in your issue or PR here.
Here's a list of where to route problems:
- Product behavior inside the Sentry application image usually belongs in Sentry (especially if they're frontend changes).
- Event ingestion and light processing (PII scrubbing, etc) belongs in Relay.
- Long-term event storage (any queries or insertion to ClickHouse) belongs in Snuba.
- Event symbolication of native symbols (Java, .NET, C, C++, etc.) belongs in Symbolicator.
- Uptime monitoring checks belongs in Uptime Checker.
- Taskbroker belongs in Taskbroker. This is for routing Sentry's tasks; we replaced Celery with it.
- Any Emerge Tools-related code (mobile build distributions, mobile size analysis, and mobile snapshots) belongs in Launchpad.
- File/object storage proxy or management belongs in Objectstore.
Hi! We view self-hosted Sentry not just as something we maintain, but as a community we develop together. Contributing to self-hosted means more than code contributions; there are many ways to help!
- Answer user issues, bug reports, and requests via GitHub issues. It's easier to monitor them on the Self-Hosted Sentry Projects pane, which filters out issues with the "Waiting For: Product Owner" label. When someone with at least "Triage" access replies to the issue, the label will be removed. This helps prevent issues from being forgotten. Some issues may still take longer to reply to because they require regaining context or a deeper investigation.
- Answer user issues on the Discord channel. This is usually the place to go if someone has a problem that prevents their self-hosted Sentry from running, since it's real-time messaging.
- Write self-hosted documentation on sentry-docs. The easiest way is to transfer writeups of GitHub issues labeled "Category: Docs" to the
sentry-docsrepository. - Bump third-party dependencies (Postgres, Kafka, ClickHouse, etc.) when a security patch arrives. Note that we only upgrade a major version when SaaS (the cloud offering) does so; see current versions in
devservices/config.yml. - General improvements, including keeping feature flags in
sentry/sentry.conf.pyvalid, ensuring Bash scripts are free of bugs, and generally improving the self-hosted experience.
Any other contributions beyond those listed above are welcome!
Warning
Unless you have a very big machine, we don't recommend you to have a "local setup" on your own machine (your laptop or PC). We strongly recommend spawning a Linux virtual machine through a cloud provider or a controlled virtual environment (VirtualBox, Proxmox, etc.).
To get started, install these tools:
- Docker Engine and Docker Compose (via Docker plugin system). Refer to Docker Engine installation documentation. It's recommended to install via the distribution's package manager (
aptfor Debian/Ubuntu, anddnforyumfor CentOS/Fedora/RHEL). - Python v3.11 or higher.
- the
uvpackage manager. Refer to their installation documentation. prekfor Git pre-commit hooks. Refer to their installation documentation.
The install flow is driven by ./install.sh, which performs version checks, copies example config files, generates missing secrets, builds any local images, and prepares the database. When the install completes, the expected next step is docker compose up -d --wait.
Generated and managed config files live in the repo working tree:
.envis the default environment file.sentry/sentry.conf.pyis created fromsentry/sentry.conf.example.py.sentry/config.ymlis created fromsentry/config.example.yml.relay/config.ymlis created fromrelay/config.example.yml.symbolicator/config.ymlis created fromsymbolicator/config.example.yml.
Treat those generated files as install outputs first and manual edits second. If you are changing generation logic, verify both the example file and the install script behavior.
There are two kinds of tests:
- Unit tests: run specific bash scripts and ensure they're working as intended. Test files are under the
_unit-test/directory, and assertions are made using Bash. - Integration tests: run the entire self-hosted stack (using specific
COMPOSE_PROFILES) by running./install.shanddocker compose up --wait, then execute scenarios for logging in and verifying that events are ingested and queried correctly. Test files are under_integration-test/, and assertions are written in Python using thepytesttesting framework.
Specifically for integration tests, dependencies are managed through uv. To set up the environment and install testing dependencies, run:
uv sync --frozenThen, to run the integration tests, run:
uv run pytest -x --cov --junitxml=junit.xml _integration-test/Keep pull requests small enough that a reviewer can understand the full user impact in one pass. In this repo that usually means one packaging concern per PR: one install fix, one config migration, one test addition, or one optional modification.
Expectations:
- Include a clear problem statement, not just the fix.
- State whether the bug reproduces on a fresh install, upgrade, or both.
- Call out any generated files, config migrations, or operator-visible behavior changes.
- Include the exact validation you ran locally.
- Link upstream issues or PRs when the root cause is outside this repository.
- Keep commit history readable. A small number of focused commits is better than a long stream of fixups.
If you open an issue or PR, include enough context that someone unfamiliar with your machine can reproduce it: host OS, Docker and Compose versions, whether you used .env.custom, relevant COMPOSE_PROFILES, and the failing command or log excerpt.
You must understand your pull request. If you cannot explain what your changes do and how they interact with the rest of the system, your PR may be closed.
Using AI to open pull requests is fine. Submitting AI-generated slop without understanding it is not.
This section is not relevant to the general public; it provides an overview of what the release pipeline looks like. If you're an employee, refer to the Notion doc.
To perform a self-hosted release, you need to do the following things in order:
- Release all components (sentry, snuba, relay, etc) through
.github/actions/release.{yaml,yml}on each repository. It's triggered automatically every 15th of the month. You can also manually trigger it via "workflow dispatch". - It will trigger issue creation on the
getsentry/publishrepository; those issues need to be approved by adding the "accepted" label to each. If a CI check is red, retry the failing jobs and re-add the "accepted" label. If the CI checks are green, the release will be created. - After all components are released, release
self-hostedusing.github/actions/release.ymland approve it on thepublishrepository. - Optionally, update the release notes on the
self-hostedrepository to inform users about the changes.
To get help on contributing, reach out to #self-hosted on Sentry's Discord.
If you're a Sentry employee, reach out to #discuss-self-hosted on Slack.