Skip to main content
speak-mintlify uploads generated audio files to S3-compatible storage for efficient delivery. This guide covers setup for AWS S3, Cloudflare R2, and self-hosted MinIO.

Storage Providers Overview

AWS S3

Industry standard, global CDN, pay-per-use pricing

Cloudflare R2

Zero egress fees, fast global delivery, simple pricing

MinIO

Self-hosted, full control, no vendor lock-in

AWS S3 Setup

1

Create an S3 bucket

  1. Log in to AWS Console
  2. Click Create bucket
  3. Choose a unique bucket name (e.g., my-docs-audio)
  4. Select a region close to your users (e.g., us-east-1)
  5. Uncheck “Block all public access” (we need public read access)
  6. Click Create bucket
2

Configure bucket policy

Add a bucket policy to allow public read access:
  1. Go to your bucket → Permissions → Bucket Policy
  2. Add this policy (replace YOUR_BUCKET_NAME):
This allows public read access to all files in the bucket. Only upload files you want to be publicly accessible.
3

Create IAM user

Create an IAM user with programmatic access:
  1. Go to IAM Console → Users
  2. Click Add users
  3. User name: speak-mintlify-uploader
  4. Select Access key - Programmatic access
  5. Click Next: Permissions
4

Attach permissions

Create an inline policy with these permissions:
Complete the user creation and save the Access Key ID and Secret Access Key.
5

Configure environment variables

Add credentials to your .env file:
.env

Optional: CloudFront CDN

For better performance, serve audio through CloudFront:
1

Create CloudFront distribution

  1. Go to CloudFront Console
  2. Click Create distribution
  3. Origin domain: Select your S3 bucket
  4. Origin access: Legacy access identities → Create new OAI
  5. Viewer protocol policy: Redirect HTTP to HTTPS
  6. Click Create distribution
2

Update bucket policy

CloudFront will update your bucket policy automatically. Remove the public access policy if using CloudFront exclusively.
3

Update S3_PUBLIC_URL

Use your CloudFront domain:
.env

Cloudflare R2 Setup

Cloudflare R2 offers zero egress fees and is more cost-effective for high-traffic sites.
1

Create R2 bucket

  1. Log in to Cloudflare Dashboard
  2. Go to R2 from the sidebar
  3. Click Create bucket
  4. Enter bucket name (e.g., docs-audio)
  5. Choose a location hint (optional)
  6. Click Create bucket
2

Enable public access

  1. Go to your bucket → Settings
  2. Scroll to Public access
  3. Click Allow Access and confirm
  4. Copy the Public bucket URL (e.g., https://pub-abc123.r2.dev)
3

Create API token

  1. Go to R2 → Manage R2 API Tokens
  2. Click Create API token
  3. Token name: speak-mintlify
  4. Permissions: Object Read & Write
  5. (Optional) Apply to specific buckets only
  6. Click Create API token
  7. Save the Access Key ID and Secret Access Key
4

Configure environment variables

Add R2 credentials to your .env file:
.env
Replace <account_id> with your Cloudflare account ID (found in R2 settings).

Custom Domain for R2

Use your own domain for cleaner URLs:
1

Add custom domain

  1. Go to your R2 bucket → Settings → Custom Domains
  2. Click Connect domain
  3. Enter your domain (e.g., audio.docs.com)
  4. Follow DNS setup instructions
2

Update S3_PUBLIC_URL

.env

MinIO Setup (Self-Hosted)

MinIO is perfect for self-hosted or on-premise deployments.
1

Install MinIO

2

Create bucket

  1. Access MinIO Console at http://localhost:9001
  2. Login with root credentials
  3. Go to Buckets → Create Bucket
  4. Bucket name: docs-audio
  5. Click Create Bucket
3

Set bucket to public

  1. Go to your bucket → Anonymous → Add Access Rule
  2. Prefix: * (all objects)
  3. Access: readonly
  4. Click Add
4

Create access key

  1. Go to Access Keys → Create access key
  2. Copy the Access Key and Secret Key
  3. Click Create
5

Configure environment variables

.env
For production, use HTTPS with a reverse proxy (nginx, Caddy) and a proper domain.

Testing Your Setup

Verify your storage configuration works:
Check that:
  1. Files upload successfully
  2. Public URLs are accessible
  3. Audio plays in your browser
  4. Cleanup correctly identifies orphaned files

Environment Variables Reference

string
required
Your S3 bucket name
string
required
S3 access key ID (or R2/MinIO equivalent)
string
required
S3 secret access key
string
required
Public URL where files are accessible. Examples:
  • AWS S3: https://bucket.s3.region.amazonaws.com
  • CloudFront: https://d123.cloudfront.net
  • R2: https://pub-abc.r2.dev
  • MinIO: https://minio.example.com/bucket
string
default:"us-east-1"
AWS region (or auto for R2)
string
Custom S3 endpoint (required for R2 and MinIO). Examples:
  • R2: https://abc123.r2.cloudflarestorage.com
  • MinIO: https://minio.example.com
  • Not needed for AWS S3

Troubleshooting

AWS S3:
  • Check IAM user has s3:PutObject permission
  • Verify bucket name in IAM policy matches actual bucket
  • Ensure access keys are correct
Cloudflare R2:
  • Verify API token has “Object Read & Write” permissions
  • Check token is applied to correct bucket
  • Ensure endpoint URL includes account ID
MinIO:
  • Check access key has write permissions
  • Verify bucket policy allows uploads
  • Check MinIO server is running
Check public access:
  • AWS S3: Verify bucket policy allows public read
  • R2: Ensure “Allow Access” is enabled
  • MinIO: Check anonymous access rules
Check URL format:
  • Remove trailing slashes from S3_PUBLIC_URL
  • Verify bucket name is correct
  • Test URL directly in browser
Add CORS configuration to your bucket:AWS S3:
Cloudflare R2: CORS is automatically configured for public buckets.MinIO:
  • Verify endpoint URL is correct (including protocol)
  • Check firewall/security groups allow connections
  • For MinIO, ensure server is accessible from CI/CD
  • Test with curl or aws s3 ls
  • Check S3_PUBLIC_URL matches actual public URL
  • Verify content-type is set correctly (audio/mpeg)
  • Check bucket/object ACLs (legacy AWS S3)
  • Test URL in incognito/private browser

Best Practices

Use separate buckets

Keep audio files in a dedicated bucket separate from other assets for easier management.

Enable versioning

Enable S3 versioning to recover from accidental deletions.

Set lifecycle policies

Automatically delete old versions or move to cheaper storage tiers.

Monitor costs

Track storage and bandwidth usage, especially with AWS S3.

Use CDN

Serve through CloudFront, Cloudflare, or similar for better performance.

Secure credentials

Never commit credentials. Use environment variables or secrets managers.

Cost Optimization

  • Storage: ~$0.023/GB/month (Standard)
  • Bandwidth: $0.09/GB egress (first 10TB/month)
  • Requests: Minimal cost for PUT/GET
Optimize:
  • Use S3 Intelligent-Tiering for infrequently accessed files
  • Enable CloudFront to reduce egress costs
  • Set lifecycle rules to delete old versions

Next Steps

Fish Audio Setup

Configure Fish Audio API and choose voices

CI/CD Integration

Automate audio generation in your workflow