Skip to content

feat: support custom CA certificates for all containers#4216

Open
aldy505 wants to merge 14 commits intomasterfrom
aldy505/feat/custom-ca-certificates
Open

feat: support custom CA certificates for all containers#4216
aldy505 wants to merge 14 commits intomasterfrom
aldy505/feat/custom-ca-certificates

Conversation

@aldy505
Copy link
Collaborator

@aldy505 aldy505 commented Mar 14, 2026

Closes #4193

Summary

This PR adds support for custom CA certificates for non-Sentry services without rebuilding images.

Instead of baking certs into locally rebuilt images, we now generate trust-store overlays on the host (from ./certificates/*.crt) and instruct users to mount those generated /etc/ssl/certs paths via docker-compose.override.yml.

What Changed

  • Added feature-flagged installer step: SETUP_CUSTOM_CA_CERTIFICATE=1
  • Added new script: install/setup-custom-ca-certificate.sh
    • Validates openssl availability
    • Validates each ./certificates/*.crt
    • For each target image (relay, symbolicator, snuba, vroom, taskbroker, uptime-checker):
      • copies baseline /etc/ssl/certs from the image
      • overlays custom certs
      • regenerates hash links via openssl rehash
    • Prints a ready-to-paste docker-compose.override.yml snippet
  • Added DEBUG-gated diagnostics in the script (DEBUG=1)
  • Hooked script into install.sh
  • Documented the flag in .env
  • Ignored generated artifacts in .gitignore (certificates/.generated/)
  • Added unit coverage: _unit-test/setup-custom-ca-certificate-test.sh
  • Updated unit-test paths to pull required images directly where pull_policy: never could skip compose pulls:
    • _unit-test/bootstrap-s3-profiles-test.sh
    • install/ensure-relay-credentials.sh

Behavior / UX

  • Default behavior is unchanged unless SETUP_CUSTOM_CA_CERTIFICATE=1 is set.
  • If no *.crt files are present, the script logs and returns cleanly.
  • On invalid cert input or missing openssl, it fails early with actionable output.
  • Users apply the printed override snippet once, then re-run install after cert changes.

Files in Scope

  • .env
  • .gitignore
  • _unit-test/bootstrap-s3-profiles-test.sh
  • _unit-test/setup-custom-ca-certificate-test.sh
  • docker-compose.yml
  • install.sh
  • install/ensure-relay-credentials.sh
  • install/setup-custom-ca-certificate.sh
  • install/update-docker-images.sh
  • .dockerignore

Validation

  • Unit tests for custom CA setup cover:
    • feature flag gating
    • invalid certificate failure path
    • generated bundle/hash outputs
    • idempotency
  • Latest PR CI checks are green after follow-up fixes.

@github-actions
Copy link

github-actions bot commented Mar 14, 2026

Changelog Preview

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

  • Support custom CA certificates for all containers by aldy505 in #4216
  • Remove 'vroom-cleanup' container by aldy505 in #4217

Internal Changes 🔧

Deps

  • Bump getsentry/craft from 2.23.2 to 2.24.1 by dependabot in #4221
  • Bump astral-sh/setup-uv from 7.2.1 to 7.5.0 by dependabot in #4220

🤖 This preview updates automatically when you update the PR.

<<: [*restart_policy, *pull_policy]
image: "symbolicator-self-hosted-local"
build:
context: ./local-image
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong build context breaks certificate COPY for five services

High Severity

The Dockerfile's COPY ./certificates/*.crt is relative to the build context. Snuba correctly uses context: . (repo root) with dockerfile: ./local-image/Dockerfile, so it finds ./certificates/. However, symbolicator, relay, taskbroker, vroom, and uptime-checker all use context: ./local-image, causing Docker to look for ./local-image/certificates/ — a directory that doesn't exist. These five builds will fail (or silently produce images without the custom CA certs).

Additional Locations (2)
Fix in Cursor Fix in Web

<<: [*restart_policy, *pull_policy]
image: "symbolicator-self-hosted-local"
build:
context: ./local-image
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The COPY ./certificates/* command will cause Docker builds to fail because the certificates directory is empty by default and has an incorrect build context for several services.
Severity: CRITICAL

Suggested Fix

Modify the local-image/Dockerfile to handle cases where the certificates directory is empty. Instead of using COPY ./certificates/*, which fails on no matches, consider copying the directory itself and then handling the contents within the container's entrypoint script. For example, use COPY certificates/ /usr/local/share/ca-certificates/ and then in the entrypoint, check if the directory contains .crt files before running update-ca-certificates. Additionally, correct the build context for the affected services in docker-compose.yml to be ..

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: docker-compose.yml#L481

Potential issue: The Docker build process will fail for multiple services due to the
`COPY ./certificates/*` instruction in `local-image/Dockerfile`. This failure is caused
by two issues. First, the `COPY` command with a glob pattern (`*`) fails when the source
directory (`./certificates/`) is empty, which is the default state for users who have
not added custom certificates. Second, several services (`symbolicator`, `relay`,
`taskbroker`, `vroom`, `uptime-checker`) are configured in `docker-compose.yml` with a
build `context` of `./local-image`. This prevents them from accessing the `certificates`
directory at the repository root, causing the build to fail. As a result, the system
will fail to start in the default configuration.

Did we get this right? 👍 / 👎 to inform future reviews.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

&& rm -rf /var/lib/apt/lists/*

# Put your custom certs here as *.crt (PEM). You can keep your repo folder name.
COPY ./certificates/* /usr/local/share/ca-certificates/
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

COPY glob fails when no custom certificates exist

High Severity

COPY ./certificates/* /usr/local/share/ca-certificates/ will fail when no custom CA certificates have been added. The certificates/ directory only contains .gitignore by default, and .dockerignore excludes that file from the build context. This leaves the glob matching zero files, causing Docker to error out. Since all services now build through this Dockerfile, a fresh default installation without custom CAs will fail at the build step. The existing cron/entrypoint.sh handles this correctly by checking if files exist first.

Additional Locations (1)
Fix in Cursor Fix in Web

@aldy505 aldy505 marked this pull request as draft March 15, 2026 03:28
@aldy505
Copy link
Collaborator Author

aldy505 commented Mar 21, 2026

@sentry review

@aldy505 aldy505 marked this pull request as ready for review March 21, 2026 07:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Make custom certificates to work with non-Sentry containers

1 participant