boto3, aws-cli, aws-sdk-go-v2, aws-sdk-js, rclone, s3cmd, mc, Cyberduck, etc. that work against AWS S3 work against Raff.
Under the hood, Raff Object Storage runs on Ceph RGW (the RADOS Gateway), the same battle-tested S3 implementation behind many production object stores at scale. Ceph RGW implements the S3 API directly, which is why the compatibility surface is broad — the constraints below mirror the standard S3 spec, not Raff-specific quirks.
This page covers what that actually means in practice. It’s not just “we accept S3 API calls” — there are practical compatibility lines that matter when you’re porting code from AWS or building against Raff for the first time.
What “S3-compatible” guarantees
The S3 API surface that’s effectively universal across compatible providers (AWS, DigitalOcean Spaces, Cloudflare R2, Backblaze B2, Wasabi, MinIO, Vultr, Raff):
Anything in this table works the same as it does on AWS. If your code uses these, it ports without changes beyond the endpoint and credentials swap.
What’s AWS-only — won’t work on Raff (or any S3-compatible provider)
These are AWS-specific extensions; they’re not part of the S3 API “spec” that compatible providers implement.
If your code calls any of these explicitly, you’ll need to remove or replace the call before targeting Raff.
Endpoint URL — virtual-host vs path style
AWS S3 (and Raff) primarily uses virtual-hosted style URLs:addressing_style="path" (or s3ForcePathStyle: true / usePathStyle: true in JS / Go SDK v2) when:
- Bucket names contain dots (the wildcard TLS cert doesn’t cover nested dots)
- You’re testing against a local S3-compatible server without DNS wildcards
- You hit
SSL: certificate verify failederrors that look TLS-related
Authentication — SigV4 and the region trap
Raff signs requests with AWS SigV4. The SDK handles the signing automatically once you give it the access key + secret. The thing to get right is region.us-east — not us-east-1 (AWS naming). This bites every new integration. Symptoms:
SignatureDoesNotMatcherrorsThe authorization header is malformed; the region '<x>' is wrong- Requests work intermittently, then break when the SDK tries a different code path
Don’t rely on the SDK’s default of
us-east-1 — it’s similar enough to silently mostly-work and then fail mysteriously.
Tooling — what works out of the box
Anything that speaks S3 with a configurable endpoint: Official AWS SDKs- Python —
boto3/aiobotocore - JavaScript / TypeScript — AWS SDK v2 and v3
- Go —
aws-sdk-go-v2 - Java — AWS SDK for Java
- .NET — AWS SDK for .NET
- Rust —
aws-sdk-s3 - Ruby —
aws-sdk-s3 - PHP — AWS SDK for PHP
aws-cli—aws s3andaws s3apicommandss3cmd— long-standing Python CLImc(MinIO Client) — fast, multi-cloud, scriptablerclone— best for syncs, mirrors, mass-copy operationss5cmd— high-performance bulk transfers
- Cyberduck — macOS / Windows
- Transmit — macOS
- WinSCP — Windows
- S3 Browser — Windows
- Cloudberry Explorer — Windows / macOS
How “compatible” is “fully compatible”?
S3 has many edge cases. Compatibility across providers is excellent for the operations you’ll actually use day-to-day, and degrades for the AWS-only extensions listed above. A practical rule:- If a tutorial uses only the basic API (
PutObject,GetObject, presigned URLs, ACLs, multipart) → it works on Raff with the endpoint + region change. - If it uses
s3:Select*,iam:-prefixed permissions, AWS-specific Storage Classes, or KMS-managed keys → it won’t, and you’ll need to redesign that portion.
Common pitfalls — read this once
These are the things that break first-time integrations:- Forgetting
endpoint_url— the SDK silently calls*.amazonaws.comand you get authentication errors that look weird. Every SDK call must point at the Raff endpoint. - Region not set to
us-east— SDKs default tous-east-1; SigV4 signs with the wrong region; requests fail withSignatureDoesNotMatch. - Virtual-host vs path style mismatch — buckets with dots in the name, or SDKs that don’t auto-detect, need
addressing_style="path". - Public-bucket assumptions don’t port — AWS needs both ACL and Block Public Access disabled; R2 needs a public binding; Raff needs the bucket ACL or a policy. “Just make it public” isn’t portable code.
- Multipart parts smaller than 5 MiB (except the last part) — providers reject
CompleteMultipartUploadwithEntityTooSmall; the upload silently bills storage until you abort it. Most SDKs default to ≥ 5 MiB parts; if you hand-roll multipart, respect the floor.
Related
Use the S3 SDK
Code samples for boto3, aws-cli, JS, Go, rclone.
Generate access keys
Get the credentials you’ll need.
Set public or private
Bucket-level and object-level ACL plus 7 ready-made policies.