Skip to content

Bring Your Own S3

Bring Your Own S3 (BYOS) points a repository at a bucket you own. The bytes stay in your cloud, under your credentials, your policies and your account. CAVS keeps only metadata, indexing, coordination and optimization.

Your data stays in your cloud, under your credentials, your policies and your account.

Reason What BYOS gives you
Data residency Choose the region and provider yourself
Compliance The bytes never leave your compliance boundary
Existing commitments Use the storage you already pay for
Cost control Your negotiated rates, your lifecycle policies
Exit Your objects are already in your bucket; nothing to migrate out

The trade-off: bucket configuration — encryption, versioning, lifecycle, public-access settings, IAM — becomes yours to get right.

aws_s3, r2 (Cloudflare R2), wasabi, b2 (Backblaze B2’s S3 API), minio, and generic for any other S3-compatible endpoint.

Azure Blob and native Google Cloud Storage are on the roadmap. GCS’s S3-interoperability endpoint works today as generic.

Your bucket must support:

  • Multipart uploads
  • Range GET — required for CAVS partial chunk fetches
  • Strong read-after-write consistency
  • List, put, get, delete
  • Presigned URL generation
  • Checksums

Versioning is recommended (it protects you from accidental deletion). Lifecycle rules are optional but useful.

Plan BYOS Connections
Free not available 0
Developer paid add-on, $29/mo 1
Team included 3 (+$25 each beyond)
Business included unlimited, plus per-repository storage

“Per-repository storage” means each repository can target a different connection. On Developer and Team, connections are organization-wide.

Enable the Developer add-on:

Terminal window
curl -sS -X POST "https://cavsnode.com/api/v1/organizations/acme-ai/billing/byos-addon" \
-H "Authorization: Bearer $CAVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'

Three options, in order of preference.

CAVS assumes an IAM role you create and exchanges it for temporary STS credentials. No long-lived secret is ever stored.

You provide: the role ARN, an external ID, and the bucket/prefix.

Trust policy on your role
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "AWS": "<the CAVS principal shown in the dashboard>" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "sts:ExternalId": "<the external id shown in the dashboard>" }
}
}]
}
Permission policy — scope it to the prefix
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::my-cavs-bucket",
"Condition": { "StringLike": { "s3:prefix": ["cavs/*"] } }
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:AbortMultipartUpload",
"s3:ListMultipartUploadParts"
],
"Resource": "arn:aws:s3:::my-cavs-bucket/cavs/*"
}
]
}
  1. Go to Organization settings → Storage → Connections → New connection.

  2. Choose the provider and fill in endpoint, region, bucket and an optional prefix. A prefix is strongly recommended — it keeps CAVS objects in their own sub-tree so a lifecycle rule or a cleanup script can’t reach anything else.

  3. Choose the auth method and supply the credentials or the role details.

  4. Save. CAVS immediately runs the connectivity suite and records the result as the connection’s health.

Over the API
curl -sS -X POST "https://cavsnode.com/api/v1/organizations/acme-ai/storage/connections" \
-H "Authorization: Bearer $CAVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "acme-prod-eu",
"provider": "aws_s3",
"region": "eu-central-1",
"bucket": "acme-cavs-prod",
"prefix": "cavs/",
"auth_method": "access_keys",
"access_key_id": "AKIA…",
"secret_access_key": "…"
}'

Requires storage.manageADMIN or OWNER.

Saving or testing a connection runs seven checks and measures round-trip latency:

  1. List the allowed prefix
  2. Write a temporary object
  3. Read it back (read-after-write)
  4. Range GET — required for CAVS partial fetch
  5. Multipart upload
  6. Presigned URL generation
  7. Delete the temporary object

Probe objects are always cleaned up. Re-run it any time:

Terminal window
curl -sS -X POST \
"https://cavsnode.com/api/v1/organizations/acme-ai/storage/connections/$CONN/test" \
-H "Authorization: Bearer $CAVS_TOKEN"

Choose it when creating a repository:

Terminal window
curl -sS -X POST "https://cavsnode.com/api/v1/organizations/acme-ai/repositories" \
-H "Authorization: Bearer $CAVS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "EU Models",
"storage_mode": "byos",
"storage_connection_id": "<connection uuid>"
}'

The mode is validated at creation: your plan must allow BYOS and the connection must be healthy. Object keys are the same as managed storage, additionally prefixed by the connection’s prefix:

<prefix><namespace>/objects/<xx>/<yy>/<oid>
<prefix><namespace>/cas/<relative path>

The worker re-probes every connection roughly every 10 minutes.

Status Meaning
HEALTHY All checks pass
DEGRADED Working, but slow or partially failing
AUTH_FAILED Credentials rejected — rotated, expired or revoked
PERMISSION_ERROR Authenticated, but the policy denies an operation
UNREACHABLE Endpoint or DNS failure
THROTTLED Provider rate-limiting
MISCONFIGURED Bucket, region or endpoint mismatch
UNKNOWN Not yet probed

Crossing the healthy/unhealthy boundary emits storage.connection.failed or storage.connection.restored, and notifies the organization by email and in-app.

Terminal window
curl -sS "https://cavsnode.com/api/v1/organizations/acme-ai/storage/connections" \
-H "Authorization: Bearer $CAVS_TOKEN"

BYOS changes what gets metered:

Managed BYOS
Physical storage billed as overage above the plan not billed — you pay your provider
Egress billed as overage above the plan not billed — you pay your provider
Reported in the dashboard yes yes

Cost accounting splits managed_* from byos_* bytes, so an organization mixing both gets a single invoice with each modality separated. BYOS is monetized through the plan fee, the Developer add-on and per-connection charges — not through your bytes.

Objects in your bucket are yours. CAVS never claims ownership, and your cloud account pays storage and egress throughout.

A connection cannot be deleted while repositories still reference it — move or delete those repositories first. Deleting the connection removes the encrypted credentials and the connection record from CAVS. It does not touch your bucket or your objects.

Terminal window
curl -sS -X DELETE \
"https://cavsnode.com/api/v1/organizations/acme-ai/storage/connections/$CONN" \
-H "Authorization: Bearer $CAVS_TOKEN"

After disconnecting, your objects remain under the prefix, content-addressed by oid. They are readable with any S3 client; the CAVS chunk tree under cas/ needs the open-source engine to reassemble, which is exactly why that engine is open source.

  • Encryption at rest — enable SSE (or SSE-KMS) on the bucket.
  • Versioning — recommended; it’s your protection against accidental deletion.
  • Public access — keep the bucket private. CAVS uses presigned URLs; it never needs public reads.
  • Lifecycle rules — be careful. A rule that transitions CAVS objects to a cold class breaks range reads and therefore breaks pulls.
  • Credential rotation — rotate keys and update the connection. Test after.
  • Capacity and cost — CAVS reports usage but enforces no ceiling.