Skip to main content
Updated May 8, 2026 Raff Object Storage controls access at three levels, and they combine. Default everything to private. Only flip something public when the data’s whole purpose is to be served to unauthenticated readers — and even then, prefer a per-object public override on a private bucket.

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 Permissions tab showing the Bucket Policy JSON editor with empty default policy and Policy Examples dropdown, plus the Access Control List section with current ACL "private" and a Change ACL button
The tab has two sections:
  • 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.
Change Bucket ACL dialog with 4 options: Private (selected), Public Read, Public Read/Write, Authenticated Read
Bucket-level ACL is bucket-wide. If you flip a bucket to Public Read, every object in it becomes publicly readable — current and future — unless that object has an explicit private override at the object level. Customer uploads, internal logs, anything you missed: all of it goes live.We do not recommend public ACL on a bucket unless the bucket’s entire purpose is public hosting. The safer pattern is to keep the bucket Private and override only the specific objects that need to be public on the object detail page.

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”
The default empty policy is {"Version": "2012-10-17", "Statement": []} — no rules. Add statements directly, or pick a template from the Policy Examples dropdown:
Policy Examples dropdown showing seven options: Public Read Only, Public Read + List, Deny Delete, IP Restricted Upload, Enforce HTTPS Only, Read-Only Public Write for Owner, Restrict to Folder Prefix

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. Replace BUCKET_NAME with your actual bucket name; replace IP / prefix placeholders where called out.

Public Read Only

Public Read + List

Deny Delete

IP Restricted Upload

Replace 192.168.1.0/24 with your office or CI runner CIDR.

Enforce HTTPS Only

Pair with one of the public-read templates for a public bucket that rejects cleartext traffic — combine the two Statement arrays in one policy.

Read-Only Public, Write for Owner

The “static site” pattern — anyone can GET, only your account can PUT/DELETE.

Restrict to Folder Prefix

Replace uploads/ with your actual prefix.
Limits the public access to one folder. Other prefixes (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 explicit Deny statements in a bucket policy, which override allows. Practical implications:
  • Adding a Public Read policy on top of a Private ACL → bucket is effectively public. The policy grants what the ACL doesn’t.
  • Adding a Deny Delete policy on top of any ACL → no one can delete, even the owner via console (use Delete Policy first if you need to clean up).
  • Enforce HTTPS Only is a hard filter — it doesn’t grant access, it blocks plain-HTTP requests entirely. Always safe to layer on.
If two layers conflict, the 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.
Object detail page with Object overview (owner, region, last modified, S3 URI, ETag, Object URL, key, type, size) and Access control list (ACL) at the bottom with a Private dropdown and Save button
The Object overview card gives you what you need to share or reference the object: 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’s generate_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
Use a public ACL or policy when:
  • 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 like bucket.with.dots.s3.raffusercloud.com. Use hyphens for public bucket names.
  • Open on 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.
  • Deny in a bucket policy locks the owner out too. A Deny Delete you forgot will block your own cleanup until you Delete Policy from 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.
Last modified on May 8, 2026