Skip to main content
These settings control who and what can reach your self-hosted data plane, and what they can touch. Most are optional and default to permissive behavior suitable for trusted, single-organization deployments.

Secure sensitive customer data

Braintrust’s servers and employees do not require access to your data plane for it to operate successfully. That means that you can protect it behind a firewall or VPN and physically isolate it from access. When you use the Braintrust web application, it communicates directly with the data plane (via CORS), and the data does not flow through any intermediate systems (the control plane, or otherwise) before reaching your browser. While the data plane does send metrics and status telemetry to the control plane, it does not send logs, traces, or customer data. Because of this architecture, our self-hosted customers do not generally list us as a subprocessor. Like any third-party software, it is important that you establish the appropriate controls to ensure that your deployment is secure, and Braintrust can help you do so. Ultimately, the goal of the control plane and data plane split is to provide you with the highest levels of security and compliance.

Grant browser permissions

This is a client-side step performed by end-users in their browser, not a Terraform or Helm setting. The only deployment-side control is the Data plane is on a private network toggle in organization settings.
If your data plane is deployed behind a VPN or on a private network (not accessible from the public internet), users will need to grant browser permissions to access it. When you enable the Data plane is on a private network setting in organization settings, the Braintrust UI will check for Chrome’s Local Network Access permission. When users access your Braintrust org for the first time and a private network data plane has been configured, Chrome will display a permission prompt. Users must click Allow to grant permission for the Braintrust UI to communicate with your data plane. If permissions are blocked, we will display a modal with the steps to correct the issue.
Local Network Access is a Chrome security feature that protects users from malicious websites accessing resources on their private networks. For more information, see Chrome’s Private Network Access documentation.
If you encounter connectivity issues, ensure that your browser is up to date, any corporate proxies or network policies allow browser access to the data plane, and CORS is properly configured on your data plane deployment (automatically handled by Braintrust Terraform modules).

Configure organization authorization

By default, any Braintrust organization can authenticate against your self-hosted data plane. Use the following settings to restrict access to specific organizations. You can find an organization’s ID in the Braintrust UI. See Find your organization ID.
Set allowed_org_ids to a comma-separated list of Braintrust organization UUIDs (available in Terraform module v5.8.1 or later):
Only organizations whose IDs appear in the list can use the deployment. Leave the variable empty (the default) to impose no restriction. Organization IDs must be UUIDs, not organization names.
If braintrust_org_name is set to a specific organization name, include that organization’s ID in allowed_org_ids for forward compatibility.

Configure URL security

Braintrust backends validate user-supplied URLs (such as webhook targets and external endpoints invoked by scorers or tools) before making outbound requests, to prevent server-side request forgery (SSRF). By default, requests that resolve to private or reserved IP ranges are allowed and logged with a warning rather than blocked. To block them, set the URL request mode to reject.
The following Terraform variables configure URL security (available in module v5.8.1 or later):To block all requests to private or reserved addresses:
To allow a specific internal CIDR while warning on other private ranges:
Setting the URL request mode to off disables all URL security checks and allows outbound requests to private and reserved IP ranges. Avoid off for internet-facing deployments.

Enable audit headers

Audit headers are a legacy feature, retained for existing integrations. They predate Braintrust’s audit logging feature, which is the recommended way to track administrative actions and data access. Audit headers are enabled per request by the API client rather than through Terraform or Helm.
When actions must be attributed to specific users or tracked for compliance, enable audit headers. These headers add metadata about the request and the resources it touched to the API response. To enable audit headers, include the x-bt-enable-audit: true header in your API request. When this header is present, the API response will include the following additional headers:
  • x-bt-audit-user-id: The ID of the user who made the request (based on the provided API key or impersonation).
  • x-bt-audit-user-email: The email of the user who made the request.
  • x-bt-audit-normalized-url: A normalized representation of the API endpoint path that was called. Path parameters like object IDs are replaced with placeholders (for example, /v1/project/[id]).
  • x-bt-audit-resources: A JSON-encoded, gzipped, and base64-encoded string containing a list of Braintrust resources (like projects, experiments, datasets, etc.) that were accessed or modified by the request. Each resource object includes its type, id, and name.
The x-bt-audit-resources header requires specific parsing due to its encoding. Here’s an example of how to parse it using the Python SDK:
This feature is useful for building audit logs or understanding resource usage patterns within your applications that interact with the Braintrust API.

Enable S3 attribute-based access control

On AWS, IAM policies for the S3 buckets the module manages grant access by bucket ARN. To base access decisions on bucket tags instead, set the enable_s3_bucket_abac Terraform variable to true (available in Terraform module v5.3.0 or later). This supports tag-based governance or service control policies that gate access by resource tags.
When enabled, you can reference bucket tags in IAM authorization policies, and managing those tags requires the s3:TagResource, s3:UntagResource, and s3:ListTagsForResource permissions. This variable is disabled by default.

Pod security contexts and storage limits

This section applies to GCP and Azure deployments using the Helm chart (6.2.2+).
Starting in Helm chart 6.2.2, you can harden Braintrust pods by configuring pod- and container-level security contexts, explicit ephemeral storage requests and limits, emptyDir size limits, and writable /tmp volumes for the API and all Brainstore roles (brainstore.reader, brainstore.fastreader, brainstore.writer). By default, the Braintrust manifests don’t set these fields, so configure them only if you want to enforce a stricter security posture. Some hardened clusters require these settings. They enforce admission policies, often written as Common Expression Language (CEL) constraints, that reject any workload unless its pods declare a non-root, read-only security context and bounded storage. GKE Autopilot is one such environment, so a deployment that doesn’t set these fields is blocked until you add them.
The settings in this section apply to any GCP or Azure Helm deployment. For a complete reference, see the examples/google-autopilot-cel/values.yaml example in the Helm chart, which configures them for GKE Autopilot.

Security contexts

Set a container-level securityContext on the API and each Brainstore role to enforce a read-only root filesystem, disallow privilege escalation, and drop all Linux capabilities:
You can also set an optional pod-level podSecurityContext (for example, api.podSecurityContext or brainstore.reader.podSecurityContext) to apply settings such as runAsNonRoot or fsGroup to the entire pod. Both contexts are omitted from the rendered manifests unless you set them.

Writable /tmp volumes

When you enable readOnlyRootFilesystem: true, the container can no longer write to its root filesystem. Enable a tmpVolume for each affected component to mount a writable emptyDir at /tmp:
Any component with readOnlyRootFilesystem: true must also set tmpVolume.enabled: true. Without a writable /tmp volume, processes that write temporary files fail at runtime.

Ephemeral storage and cache volume limits

Each Brainstore role accepts an ephemeralStorage budget and a volume.sizeLimit for its cache emptyDir:
  • ephemeralStorage.request sets the pod-local storage budget that GKE Autopilot reserves. ephemeralStorage.limit sets the corresponding cap.
  • volume.sizeLimit caps the cache emptyDir. Match it to objectStoreCacheFileSize so the cache cannot exceed its allotted space.
How the ephemeral storage request is applied depends on your cloud and mode: