Docs
Type to search every article.
  1. Docs
  2. Zones

Bucket origins

5 min read Updated

On this page
  1. Which buckets
  2. Public or private
  3. The bucket details
  4. Keys that can only read
  5. What the edge does
  6. What your viewers never see
  7. CORS on a bucket
  8. Cache lifetimes on a bucket

A bucket origin lets a zone pull its files from an S3 bucket, public or private: a public bucket is read as anyone could read it, a private one with a read-only key pair and every request signed.

Either way, nothing about the bucket, its keys or its error messages reaches your viewers.

Which buckets#

Amazon S3, and anything that speaks the same API: Bunny Storage, Backblaze B2, Cloudflare R2, DigitalOcean Spaces, MinIO. Caching, slicing, byte ranges, the origin shield, purging and statistics all work exactly as they do on a standard origin; only the request that leaves the edge is different.

Public or private#

Choose S3 bucket (public or private) as the origin type, then set Bucket Access:

  • Public: anyone can already read the bucket's files, for example an Amazon S3 bucket whose policy allows s3:GetObject to everyone. Requests are sent unsigned and the zone needs no region and no keys.
  • Private: only your keys can read the bucket. The zone takes a region and a read-only key pair, and signs every request with AWS Signature Version 4.

Use a bucket origin rather than a standard origin for a public bucket too: the edge then treats it as a bucket, with the protections listed below, and puts the bucket name in the path for you when it is addressed by path.

The bucket details#

Every bucket takes:

  • Bucket Endpoint: the store's address, such as https://s3.eu-west-1.amazonaws.com. A scheme, a hostname and an optional port, with no path.
  • Bucket Name: 3 to 63 characters of lower-case letters, digits, dots and hyphens.
  • Bucket Addressing: Path style fetches endpoint/bucket/file; Virtual hosted fetches bucket.endpoint/file and needs the endpoint to start with the bucket name. The zone page shows the URL a file would be fetched from as you type. Path style is the one to pick unless your provider's endpoint already begins with the bucket name.

A private bucket also takes:

  • Region: the one the bucket lives in, such as eu-west-1 or de. Type auto for Cloudflare R2 and other stores without regions of their own; most such stores also accept us-east-1. It goes into every signature, so a wrong one is refused by the store.
  • Access Key and Secret Key: a pair that can read this bucket and nothing else. The secret is stored once and never shown again; leave the field blank on a later save to keep it, or type a new one to replace it.

Two mistakes are caught at save time rather than as a stream of failed requests: virtual hosted addressing with an endpoint that does not start with the bucket name, and, on a shared store such as Amazon S3, path style with an endpoint that already does, which would ask for the bucket twice. A store on your own domain whose bucket happens to share its first label saves as it is.

Switching a private bucket to Public deletes its region and both keys in the same save. Switching a public bucket to Private asks for the region and both keys again.

Keys that can only read#

Give a private bucket's zone a key pair that can do nothing but read this one bucket. On Amazon S3 that is a policy like this one, attached to a user created for the purpose:

JSON
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::my-video-bucket/*"
    },
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": "arn:aws:s3:::my-video-bucket"
    }
  ]
}

The second statement is not there so the edge can list anything; it never does. Amazon answers a request for a file that does not exist with 403 rather than 404 when the key is not allowed to list the bucket, and a 403 from a private bucket becomes our error page rather than a plain not-found. Other stores have their own way of making a read-only key; the same rule applies.

What the edge does#

  • Every request to the bucket is a GET or a HEAD, signed with AWS Signature Version 4 on a private bucket and unsigned on a public one. Anything else a viewer sends is answered 405 with Allow: GET, HEAD (a POST is refused with 403 instead while Block POST Requests is on), so nothing can write to the bucket through the zone, and a browser's CORS preflight is refused too.
  • The viewer's query string is never sent to the bucket, public or private: it would reach the store's listing and versioning operations. It still tells one file from another in the cache, so ?v=2 works as a cache buster.
  • A viewer's own Authorization header and any x-amz-* header it sends are removed before the request leaves the edge.
  • A redirect from the bucket is never followed, and the Host header is always the bucket's own, so the Forward Host Header, Follow Redirects and Add Canonical Headers switches are unused and shown greyed.
  • On a private bucket the signature covers the request itself and not the conditional headers, so byte ranges and cache revalidation work as on any other origin.

What your viewers never see#

Every x-amz-* header is removed from the response; they name the bucket, its region and the store's request ids. A 401 or 403 from a private bucket, which carries your access key id and the whole request in its body, becomes our error page for an origin that is not responding, with a 502 status, and is never cached, so the next request tries again the moment the keys are fixed. A public bucket's 403 is its own answer for a file it does not publish, so it stays a 403. Every other answer keeps its status: a missing file is still a 404. Whatever the status, the viewer gets a one-line body instead of the store's XML.

CORS on a bucket#

Set CORS rules on the bucket as you would without us, and a player or page on another site is told what the bucket tells that site, from the cache too: the edge asks the bucket once per site, signed on a private bucket, and keeps the answer five minutes. See CORS and the cache in How caching works.

Cache lifetimes on a bucket#

A store sends no Cache-Control unless you set one on the object, so with the zone on Respect Origin Cache-Control the defaults in How caching works apply: seven days for video, audio, downloads and any file of 10 MB or more, a day for images, five minutes for JSON under an API-shaped path, 10 seconds for a playlist, and an hour for the rest. Set a Cache Expiration Time on the zone if you want one figure for everything.

Switching the origin type back to a standard origin clears the bucket name, region, addressing and both keys in the same save. From the API the zone reports S3_ACCESS as PUBLIC or PRIVATE, and S3_SECRET_KEY_SET as 1 or 0 and never the secret itself; see Zones.