The three layers
Layered access is most permissive — if any layer grants read, the read succeeds. Public bucket + private object usually still ends up public; private bucket + public object exposes that one object only.
A fourth option — presigned URLs — sits outside this model and is covered at the bottom.
Open the Permissions tab
All bucket-level access controls live on the bucket detail page’s Permissions tab.
- Bucket Policy — JSON-based access rules with 7 ready-to-use templates
- Access Control List (ACL) — coarse-grained bucket-wide permission level, four options
Bucket ACL — the four options
Click Change ACL to open the picker.
Bucket Policy — the JSON rules
The Bucket Policy section accepts an S3-style JSON policy document. It lets you express things ACLs can’t:- “Allow uploads only from these IP ranges”
- “Deny all delete operations on this bucket”
- “Force HTTPS — block plain HTTP requests”
- “Public for read, but only the owner can write”
- “Limit access to objects under one folder prefix”
{"Version": "2012-10-17", "Statement": []} — no rules. Add statements directly, or pick a template from the Policy Examples dropdown:

The seven policy templates
Pick a template, the editor fills in working JSON, you tweak (add your IP, your folder name, etc.), then Save Policy.
To remove a policy entirely, Delete Policy clears the document; access falls back to the bucket’s ACL alone.
What each template looks like as JSON
If you’d rather paste a template into your own infrastructure-as-code or write your own, here’s the JSON each one produces. ReplaceBUCKET_NAME with your actual bucket name; replace IP / prefix placeholders where called out.
Public Read Only
Public Read + List
Deny Delete
IP Restricted Upload
Replace192.168.1.0/24 with your office or CI runner CIDR.
Enforce HTTPS Only
Statement arrays in one policy.
Read-Only Public, Write for Owner
Restrict to Folder Prefix
Replaceuploads/ with your actual prefix.
private/, internal/) remain inaccessible without credentials.
How policies and ACLs interact
When both are set, S3 evaluates bucket policy + bucket ACL + object ACL and grants access if any of them allows it — except for explicitDeny statements in a bucket policy, which override allows.
Practical implications:
- Adding a
Public Readpolicy on top of aPrivateACL → bucket is effectively public. The policy grants what the ACL doesn’t. - Adding a
Deny Deletepolicy on top of any ACL → no one can delete, even the owner via console (useDelete Policyfirst if you need to clean up). Enforce HTTPS Onlyis a hard filter — it doesn’t grant access, it blocks plain-HTTP requests entirely. Always safe to layer on.
Deny wins. Use Deny carefully.
Object-level ACL — overriding for one file
Each object can carry its own ACL that opens it up even when the bucket is private. Open the object’s Details page from the bucket’s Objects tab → row Actions → Details.
At the bottom, the Access control list (ACL) dropdown sets per-object ACL:
Private or Public. Save and the change applies immediately.
The recommended pattern for an “almost-private” bucket: keep the bucket Private, then flip individual objects to Public only when needed. This is far safer than flipping the bucket public and trying to lock individual files back down.
Presigned URLs — the fourth option
Sometimes you want to share one file with one person without flipping any ACL. The dashboard’s per-object Share action (and the SDK’sgenerate_presigned_url / GetObjectPresign calls) generates a presigned URL — a long, time-limited HTTPS link that lets anyone download the object without credentials, until it expires.
Use a presigned URL when:
- The file should not be permanently public
- The recipient doesn’t have Raff access
- The link should self-expire — no cleanup required
- The file is permanently public (static assets, public docs)
- The link needs to work without expiring
- You’re building a CDN origin
Combination matrix
How the layers stack:
When in doubt, read all three layers before reasoning about who can access what.
New uploads — what ACL do they get?
Default behavior when you upload a new object:
Override at upload time via the SDK with
PutObject(ACL: ...). The dashboard upload always uses the bucket default — no per-upload picker today.
Common gotchas
- Periods in bucket names break HTTPS for public buckets. The wildcard cert covers
*.s3.raffusercloud.com, not nested dots likebucket.with.dots.s3.raffusercloud.com. Use hyphens for public bucket names. Openon the dashboard fails for private objects. That action uses the Object URL, which needs public access. Use Download or Share instead.- Switching a public bucket back to private doesn’t kill existing presigned URLs. They keep working until they expire. Rotate the signing access key if you need to revoke faster.
Denyin a bucket policy locks the owner out too. ADeny Deleteyou forgot will block your own cleanup until youDelete Policyfrom the dashboard.- Public buckets leak silently. There’s no daily report telling you a bucket is public — once it’s public, it’s public. Periodically audit the ACL column on the Buckets list.
Next steps
Generate access keys
S3 credentials with Full or Limited (per-bucket) scope.
Use the S3 SDK
Programmatic ACL changes and presigned URLs.
S3 compatibility
Which AWS S3 features work and which don’t.