Skip to content

S3 Storage

br\u016bhi Cloud can store and serve audio files from any S3-compatible object storage service. This allows you to maintain a large media library without worrying about the disk space on your server.

ServiceS3-compatibleNotes
AWS S3Yes (native)Standard endpoint s3.amazonaws.com
Cloudflare R2YesNo egress fees; endpoint: https://{accountid}.r2.cloudflarestorage.com
MinIOYesSelf-hosted; endpoint: your MinIO URL
Backblaze B2YesS3-compatible API; endpoint: https://s3.{region}.backblazeb2.com

Set these environment variables before starting the Docker container:

S3_ENDPOINT_URL=https://your-endpoint.example.com
S3_ACCESS_KEY=your-access-key-id
S3_SECRET_KEY=your-secret-access-key
S3_BUCKET=bruhi-media
S3_REGION=us-east-1

For Cloudflare R2, the region is always auto:

S3_ENDPOINT_URL=https://ACCOUNT_ID.r2.cloudflarestorage.com
S3_REGION=auto

For MinIO (self-hosted):

S3_ENDPOINT_URL=http://minio.internal:9000
S3_REGION=us-east-1

MinIO ignores the region value but requires it to be present.

Once configured, the S3 Media Browser appears in the Content Library tab of the dashboard (backed by the server s3_media module). You can:

  • Navigate your bucket by folder prefix
  • Filter by filename or metadata tags
  • Preview file metadata (duration, sample rate, bitrate, last modified)
  • Load files directly into deck queues or cartwall pads
  • Perform single or bulk track deletions with database cleanup

brūhi Cloud generates presigned URLs when serving S3 files to the browser:

  • Files are served directly from S3 to the browser — the brūhi server is not a proxy bottleneck.
  • Presigned URLs expire after 1 hour and are refreshed automatically.
  • Your S3 bucket does not need public access privileges.

Deleting media via the S3 browser or Media API (/api/media/delete) safe-deletes object references and performs database cleanup:

DELETE /api/media/delete
Content-Type: application/json
{
"key": "tracks/ambient-01.mp3",
"clean_metadata": true
}

When you add an S3 file to a playlist or queue, br\u016bhi stores the S3 key (object path) rather than a presigned URL. A fresh presigned URL is generated at playback time.

You can mix local files (uploaded to the Docker volume) and S3 files in the same playlist with no special configuration.

After a recording session, you can upload the WAV file to S3:

POST /api/stations/{id}/recordings/{filename}/upload-to-s3

The file is uploaded to the configured bucket under a recordings/ prefix:

bruhi-media/recordings/station-1/bruhi-recording-2026-05-08-14-32-07.wav

If S3 environment variables are not set, the S3 Media Browser does not appear in the dashboard. All media is served from the local Docker volume only. This is fine for small deployments or when using a network-attached storage volume.