# R2 public access

By default, R2 buckets are never publicly accessible. Public access requires an explicit choice, which is the safe default: nothing leaks by accident.

## Two ways to expose a bucket

1. **Custom domain** (production): serve the bucket from a domain you control, e.g. `assets.example.com`. This is the production path.
2. **`r2.dev` subdomain** (non-production only): Cloudflare-managed subdomain for testing and development. Do not build production traffic on it.

## The failure modes

- Assuming a bucket is public because the Worker can read it: Worker access uses the R2 binding (private, authenticated), which has nothing to do with public HTTP access.
- Using r2.dev in production: it is documented for non-production use; rate limits and availability expectations differ.
- Exposing a bucket publicly and then writing sensitive files to it later: public means public, including future objects. Keep separate buckets for public assets and private data.

## Checklist

- One bucket for public assets, another for private data. Never mix.
- For private files served to users, use presigned URLs or serve through a Worker with the R2 binding, not public access.
- After enabling public access, verify from an unauthenticated session: `curl` the URL without any credentials.