Common Operations
While turbopuffer strives to be as low interaction as possible, there are certain manual operations you will have to perform in your BYOC deployment.
Securely partitioning your data
turbopuffer BYOC allows you to configure multiple organizations, each with their own set of API keys which you can use to scope data access. Currently, we only support creating admin API keys, that will apply to all namespaces in their organization. For this reason, if you need to ensure data is isolated we recommend creating multiple organizations instead. If this is a limitation, we recommend you contact us on Slack.
Generating org IDs and API keys
You can generate valid org IDs and API keys using any tooling that produces cryptographically random values. The format requirements are:
Org ID
- 24 character random string
- Alphabet:
[a-z0-9](lowercase alphanumeric only)
API Key
- Prefix:
tpuf_ - Followed by: 32 character random string from alphabet
[a-zA-Z0-9] - Full format:
tpuf_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Stored API Key Hash
- Format:
base64(sha256(full_api_key)) - The hash is computed over the complete API key including the
tpuf_prefix
Your BYOC kit includes a generate_secrets.py script that generates these values for you.
Storing org configuration
authentication:
allowed_api_keys_sha256:
"your24charorgidhere1234":
- "YourBase64EncodedSHA256HashHere+40CharactersTotal="
- "AnotherBase64EncodedSHA256HashHere+40CharactersTot="
Adding additional organizations
To add more organizations, generate new org ID and API key pairs and add them to the configuration:
authentication:
allowed_api_keys_sha256:
"existingorgid123456789012":
- "ExistingOrgKeyHash..."
- "AnotherExistingOrgKeyHash..."
"neworgid0987654321abcdef":
- "NewOrgKeyHash..."
- "AnotherNewOrgKeyHash..."
Adding a new API key to an existing organization
Each organization can have multiple API keys for key rotation, different services, or other access patterns. To add a new API key, use the apikey.py script from your BYOC kit and append the generated hash to the organization's key list:
authentication:
allowed_api_keys_sha256:
"existingorgid123456789012":
- "ExistingOrgKeyHash..."
- "NewlyAddedKeyHash..."
Bring your own bucket
You may want to store a customer's data in a bucket that the customer owns, often
called bring your own bucket (BYOB). This is configured by mapping the customer's
org to a dedicated bucket with
blob.bucket_overrides_by_org_id.
The bucket can live in a different GCP project than the turbopuffer cluster. Grant
the cluster's service account roles/storage.objectAdmin on the bucket.
blob:
bucket_overrides_by_org_id: # org ID -> bucket ID
"m3vjrpgnvlcm5x8olkguh1l2": customer-b-bucket
buckets:
customer-b-bucket:
bucket_url: "https://customer-b-turbopuffer.storage.googleapis.com"
provider: gcp-workload-identity
Customer managed encryption keys (CMEK)
Namespaces can be encrypted with a customer managed key. In BYOC the cluster's own identity accesses the key, so there is no turbopuffer service account to grant.
-
Create a symmetric Cloud KMS key in the same region as the bucket.
-
Grant
roles/cloudkms.cryptoKeyEncrypterDecrypteron the key to the Cloud Storage service agent of the project that owns the bucket. Cloud Storage encrypts and decrypts objects with this service agent, not with the cluster's service account.# Prints the service agent email, e.g. service-123456789012@gs-project-accounts.iam.gserviceaccount.com SERVICE_AGENT=$(gcloud storage service-agent --project BUCKET_PROJECT_ID) gcloud kms keys add-iam-policy-binding KEY --keyring KEYRING --location REGION \ --member "serviceAccount:$SERVICE_AGENT" \ --role roles/cloudkms.cryptoKeyEncrypterDecrypter -
Set
blob.cmek_enabledtotrueand apply the configuration change. The flag is per bucket. If the org's data lives in a bucket underblob.buckets(see bring your own bucket), set it on that entry, since entries do not inherit the top-level value:blob: cmek_enabled: true # default bucket buckets: customer-b-bucket: bucket_url: "https://customer-b-turbopuffer.storage.googleapis.com" provider: gcp-workload-identity cmek_enabled: true # required for orgs mapped to this bucket -
Write with
encryptionset to the key resource name.
Copying namespaces across clusters
You can use copy_from_namespace to copy
data between BYOC clusters. On the destination cluster:
- If the clusters use different org IDs, add an API key hash under the source's org ID in
authentication.allowed_api_keys_sha256. The org ID must match the data in the source bucket. You can register an existing source key or generate a new one. The destination cluster authenticates this key locally. - Define the source bucket under
blob.bucketsand map a source region name to it withblob.known_region_buckets. Match the source bucket'sprefix, if configured. Grant the destination cluster's cloud identity read access to the source bucket and any required encryption keys. - On the source bucket entry, set
enable_maintenance: falseto disable automatic maintenance, including garbage collection. Leave maintenance enabled on the source cluster. Setread_only: trueto prevent writes to the source bucket from the destination cluster.
Apply the changes using the Helm upgrade command, then
send a copy_from_namespace request to the
destination cluster. The destination namespace must not already exist:
curl "$DESTINATION_URL/v2/namespaces/destination-namespace" \
-H "Authorization: Bearer $DESTINATION_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"copy_from_namespace": {
"source_namespace": "source-namespace",
"source_region": "source-cluster",
"source_api_key": "<source API key registered on the destination cluster>"
}
}'
DESTINATION_API_KEY identifies the destination org. source_region must match a
key in blob.known_region_buckets and selects the source bucket for this copy.
source_api_key identifies the source org. Omit it when both clusters use the same
org ID. The region mapping does not change the bucket used for ordinary requests.
Do not configure a blob.bucket_overrides_by_org_id entry for the source org on
the destination cluster. Combining a source org override with source_region is
currently unsupported.
If the source namespace uses a customer-managed encryption key, specify destination
encryption in the copy request.
Creating additional clusters
You can create additional clusters by reusing your existing BYOC kit and control plane API key. Follow the deployment guide again with a unique cluster_name in values.yaml, and generate new turbopuffer org IDs and API keys for the new cluster with scripts/generate-secrets.py.
Applying configuration changes
After updating the configuration, apply the changes using the Helm upgrade command.