This repository is Sentry's self-hosted packaging. It bundles upstream Sentry images (Sentry, Relay, Snuba, Symbolicator, and others) into a Docker Compose deployment with install/upgrade scripts, config templates, and optional patches. This repo does not contain the application code itself — changes to product behavior belong in the upstream repositories (see ## Where Changes Belong).
install.sh— install/upgrade entrypoint. Sets shell strictness and sources the steps ininstall/in order. Run it, don't edit-and-run individual steps.install/— sourced install steps and helpers (_lib.sh,parse-cli.sh,ensure-files-from-examples.sh,wrap-up.sh, …). These are not standalone executables.scripts/— standalone operator scripts (reset.sh,backup.sh,restore.sh) plus Craft-driven release helpers.docker-compose.yml,.env,*.example.*— deployment source: Compose service wiring, shipped defaults, and config templates._unit-test/— Bash assertion tests;_integration-test/— pytest end-to-end tests.optional-modifications/patches/— community patches ("plugin system") applied withpatch -p0.action.yaml,get-compose-action/— the GitHub Action downstream repos use to run self-hosted E2E tests.- Per-service dirs (
sentry/,relay/,snuba/,symbolicator/,taskbroker/,clickhouse/,geoip/,jq/) — config templates, patches, and helper images for that service. workstation/andsentry-admin.share unmaintained — do not derive changes from them.
The tools below are needed to run installs and tests, but are not hard requirements for every pull request.
- Docker Engine + Docker Compose (via the Docker plugin system). Install via your distribution's package manager (
aptfor Debian/Ubuntu,dnf/yumfor CentOS/Fedora/RHEL). - Python >=3.11
uvpackage manager — see uv installation docs.prekfor Git pre-commit hooks — see prek installation docs.
Install test dependencies with:
uv sync --frozenWARNING: Do NOT run
./install.sh,./unit-test.sh, or the integration tests on your laptop or personal workstation. They require Docker plus a dedicated Linux VM with substantial resources, and they are destructive:./unit-test.shcalls./scripts/reset.sh, which runsdocker compose down --volumes --remove-orphans --rmi localand deletes everysentry-*Docker volume. Only run them on a dedicated VM (cloud provider or controlled virtual environment like VirtualBox/Proxmox) or in CI.
Both suites need Docker Engine, mutate local Docker state (containers, images, volumes), and clone the working copy into a /tmp sandbox via _unit-test/_test_setup.sh. Re-read the warning above before running either locally.
CI=true ./unit-test.sh # whole suite
CI=true ./unit-test.sh _unit-test/error-handling-test.sh # single file
DEBUG=1 CI=true ./unit-test.sh _unit-test/error-handling-test.sh # keep the sandbox for debugging./unit-test.sh exits early unless CI=true is set; it builds a jq image and runs each Bash assertion file matching _unit-test/*-test.sh. It does not start the full self-hosted stack. _unit-test/error-handling-test.sh additionally diffs a captured error envelope against _unit-test/snapshots/sentry-envelope-<hash> — if you change error-reporting output, update that snapshot deliberately instead of treating the diff as noise.
uv run pytest -x --cov --junitxml=junit.xml _integration-test/Only run on the dedicated VM. Integration tests execute ./install.sh and docker compose up --wait, then verify event ingestion and querying. They require the full self-hosted stack running.
install.shis the entrypoint and setsset -eEuo pipefailplusumask 002. Files ininstall/are sourced by it: do not re-declareset/umask, and remember that a sourcedexit/returnaborts the entire install (onlyparse-cli.shdoes this intentionally, for--help/bad flags). Failures are surfaced by the trap installed ininstall/error-handling.sh. Standalonescripts/*.shset their own flags (e.g.scripts/_lib.shusesset -eEuo pipefail,scripts/bump-version.shusesset -eu).- Reuse helpers in
install/_lib.sh(ensure_file_from_example,vergte, …). New install steps must be sourced frominstall.shin the right order. - Wrap step output in
${_group}…${_endgroup}(defined ininstall/_lib.sh) so GitHub Actions renders collapsible sections instead of polluting the log stream. - Format and lint before committing:
prek run --all-files(theshfmthook runsmvdan/shfmtin a container). ShellCheck CI covers onlyinstall/_lib.sh,scripts/**/*.sh,unit-test.sh,optional-modifications/**/*.sh, andworkstation/**/*.sh— otherinstall/*.shhelpers are unchecked by CI, so keep them clean manually.
- Generated files are install outputs, not source of truth:
sentry/sentry.conf.py(fromsentry/sentry.conf.example.py)sentry/config.yml(fromsentry/config.example.yml)relay/config.yml(fromrelay/config.example.yml, created byinstall/ensure-relay-credentials.sh)symbolicator/config.yml(fromsymbolicator/config.example.yml)
- Edits to example files must be mirrored in
install/ensure-files-from-examples.shor the relevant install step if generation logic changes. .envis committed source, not generated and not secret: it holds the shipped defaults (Compose profiles, image tags, ports, retention). Per-operator overrides belong in.env.custom, which is gitignored and takes precedence —install/_lib.shsources.env.customfirst, then.env. Do NOT gitignore.envor treat its contents as install output.optional-modifications/patches/**/*.patchare excluded from pre-commit and apply to.env,docker-compose.yml, and*.example.*viapatch -p0. If you edit any of those targets, verify the patches still apply and refresh them withdiff -Naru(seeoptional-modifications/README.md).
See CONTRIBUTING.md for the authoritative source.
- Keep PRs small: one packaging concern at a time (one install fix, one config migration, one test, etc.).
- 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.
AI assistance is welcome, but the human opening the PR is responsible for the diff.
- Review every generated change, understand what it does, and make sure it matches the project's intent.
- Ask the user to write the PR description and problem statement in their own words; guide them on how to write it, but do not write it for them.
- The PR template at
.github/PULL_REQUEST_TEMPLATE.mdcontains a legal boilerplate that must remain intact and can only be confirmed by the actual contributor.
action.yaml/get-compose-action/define the GitHub Action that other Sentry repos use to run self-hosted E2E tests against their own images (relay, snuba, symbolicator, taskbroker, uptime-checker, vroom). Its inputs (project_name,image_url,compose_profiles,skip_backup_restore_test, …) are a public interface — do not rename or remove inputs without coordinating with those consumers, and keep default behavior backward compatible.- Releases are driven by Craft via
.craft.yml(calver versioning): Craft runsscripts/bump-version.shpre-release andscripts/post-release.shpost-release, and generatesCHANGELOG.md. Do NOT hand-editCHANGELOG.md, invoke those scripts manually, or hand-bump the*_IMAGEtags in.env— versioning belongs to the release pipeline.
This repo owns packaging and operating surface. Product bugs belong upstream:
| Problem area | Upstream repo |
|---|---|
| Sentry application behavior (especially frontend) | getsentry/sentry |
| Event ingestion, PII scrubbing, etc. | getsentry/relay |
| Long-term event storage / ClickHouse queries | getsentry/snuba |
| Native symbolication (Java, .NET, C, C++) | getsentry/symbolicator |
| Uptime monitoring checks | getsentry/uptime-checker |
| Task routing (replaced Celery) | getsentry/taskbroker |
| Mobile build distributions / size analysis / snapshots | getsentry/launchpad |
| File/object storage proxy or management | getsentry/objectstore |