Skip to main content
Copy-ready configurations for common setups. Each one is a complete bunnyStorage(...) call — combine pieces as needed for your project. For option-by-option reference, see Configuration.
Starting from scratch? The setup wizard provisions your Bunny resources and prints a ready-to-paste config plus .env lines. Run it first, then use these examples to tune the result.

Basic setup

Storage only

payload.config.ts

With cache purging

See Cache purging.

Streaming video

Direct CDN vs Payload access control

Two ways to serve Stream videos, depending on whether the collection uses Payload’s access control.
Files bypass Payload’s access control and stream straight from Bunny.

TUS resumable uploads for large videos

See Stream: TUS resumable uploads.

Stream only, no storage

Stream webhook for encoding status

Bunny encodes MP4 renditions asynchronously. Point your Stream library’s webhook at the plugin so that, once encoding finishes, it fills in bunnyData.stream.resolutions. The secret is your library’s Read-Only API key, which Bunny signs each webhook with.
In your Bunny Stream library settings, set the webhook URL to https://your-site.com/api/storage-bunny/stream/webhook (no query secret). See Webhooks.

Secure access

Signed URLs

See Signed URLs.

IP-locked signed URLs

Bind each signed link to the requesting client’s IPv4 address, so a leaked URL stops working from any other IP. You supply the userIp callback because extracting the real client IP depends on your proxy chain.
Enforcement requires Token IP Validation enabled on the Bunny zone/library, and only IPv4 is supported. See IP locking.

URLs and thumbnails

Custom URL transforms

See URL transforms and Thumbnails.

Named-size thumbnails

payload.config.ts

Client uploads

Browser-direct client uploads

Send file bytes straight from the browser to Bunny, bypassing the Payload server — useful on serverless hosts with tight body-size limits and for large files. Configure it under storage.clientUploads; the transport is chosen automatically from the zone.
Presigned PUT straight to Bunny’s S3 endpoint. Requires a storage zone created with S3 compatibility — no Edge Script to deploy.
See Client uploads.

Multiple zones behind one Edge Script

One deployed Edge Script serves every non-s3 zone. Paste the same edge: { scriptUrl, secret } (printed by npx payload bunny:deploy-edge-script) into each non-s3 zone that enables client uploads; s3 zones presign directly and need no edge config.
Re-run npx payload bunny:deploy-edge-script whenever you add or remove a non-s3 zone, so the script’s zone map stays in sync. To deploy the production script from a dev machine, select the environment explicitly — e.g. npx payload bunny:deploy-edge-script --env-file .env.production. See Deploy the Edge Script.

Multiple collections

Per-collection zones and libraries

Point individual collections at their own Bunny storage zone and stream library. A collection whose storage/stream includes apiKey uses that config as its own zone/library, ignoring the global one. All of apiKey/hostname/zoneName (storage) or apiKey/hostname/libraryId (stream) are then required, and nothing — including tokenSecurityKey, mimeTypes, or tus — is inherited from the global config.
See Collection overrides and Multi-tenant.

Disable storage or stream per collection

See Collection overrides.

Different settings per collection

Working with stored data

Querying by bunnyData

See Stored data for the full shape and what is stored vs. computed.

Environment variables

.env
See Getting your credentials and Cache purging for where each key comes from.

Next steps

Multi-tenant

Per-tenant prefixes, per-tenant zones, and isolation with signed URLs.

Stored data

The bunnyData field shape and querying videos by videoId.

Stream collections

Organize videos into per-tenant Bunny Stream collections.

Media preview

Inline Stream video and audio previews in the admin panel.