Skip to content
Berth

Keep audiobooks in S3-compatible storage

Updated October 27, 2026

Berth can store books in any S3-compatible bucket instead of the server's disk. The server keeps the library and decides who may listen; the audio itself can travel from the bucket or a CDN straight to the phones.

Why object storage

Supported providers

Any S3-compatible service works. The admin has presets that fill in the endpoint and region for: AWS S3, Cloudflare R2, Yandex Cloud, Backblaze B2, Bunny Storage and MinIO. For Cloudflare R2 there is also a wizard that creates the bucket and keys for you.

Connect a bucket

  1. Create a bucket and an access key with read and write access to it in your provider's console.
  2. Add a CORS rule to the bucket: origin is your Berth address, methods GET, HEAD, PUT, headers *. The admin uploads files from the browser straight to the bucket, so this rule is required.
  3. In the Berth admin open the storage settings, add storage, choose “S3 bucket” and pick a preset or fill in the fields yourself.
  4. Fill in name, bucket, endpoint (empty for AWS), region (us-east-1 if empty), access key ID and secret access key. Turn on path-style addresses for MinIO; it is turned on by itself for an IP address or localhost.
  5. Press “Check connection”: Berth writes, reads back and deletes a small test file and checks CORS from your server addresses.
  6. Make the storage the default one: new books go to the default storage.

Keys are stored encrypted with the server key secret.key and are never shown again.

How audio reaches the phones

Without signing, files behind a CDN open by a link that never expires. Their names are SHA-256 hashes and cannot be guessed, but revoking a device does not close links it already has. Bunny CDN token authentication makes links expire after 6 hours.

ModeHow it worksWhen to use
Direct links (default)Phones get a signed link to the bucket that lasts 15 minutesTakes the load off the server
Through the serverThe server streams the file; links last 6 hours and stop working at once when a device is revokedPhones cannot reach the bucket
Through a CDNLinks point to a CDN or a public address of the bucketFastest when the bucket has a CDN

Good to know

Questions

Does Berth need public access to the bucket?

No. In the default mode the bucket stays private and phones get signed links that expire after 15 minutes.

The check says the bucket does not accept uploads from a browser. What now?

Add the CORS rule: origin is the Berth address, methods GET, HEAD, PUT, headers *. Then run the check again.