Skip to content

Add AWS S3 and MinIO (S3-compatible) Storage Provider Support #1124

@kaumudpa

Description

@kaumudpa

🔖 Feature description

Add native support for AWS S3 and S3-compatible storage services (like MinIO, DigitalOcean Spaces, Backblaze B2) as an alternative to the existing Cloudflare R2 and local storage options.

Key capabilities:

  • Generic s3 storage provider using AWS SDK v3
  • Support for custom endpoints (MinIO, self-hosted S3-compatible services)
  • Multipart upload support for large files (videos up to 1GB)
  • Date-based directory organization (YYYY/MM/DD/filename) matching local storage pattern
  • Automatic file deletion from storage when media is deleted in Postiz
  • Full backward compatibility with existing local and cloudflare providers

🎤 Why is this feature needed ?

1. Infrastructure flexibility:
Many self-hosted users already have existing S3-compatible storage infrastructure (AWS S3, MinIO, DigitalOcean Spaces) and prefer not to set up a separate Cloudflare R2 account just for Postiz.

2. Cost optimization:

  • AWS S3 may be cheaper for users already in the AWS ecosystem
  • MinIO allows completely self-hosted object storage with no external dependencies
  • Organizations with existing S3 buckets can reuse them

3. Data sovereignty:
Self-hosted MinIO allows users to keep all media files on their own infrastructure, which is critical for:

  • GDPR compliance
  • Enterprise security requirements
  • Air-gapped environments

4. Vendor neutrality:
Currently Postiz only supports Cloudflare R2 for cloud object storage. Adding S3 support provides users with more choices.

✌️ How do you aim to achieve this?

New environment variables:

STORAGE_PROVIDER="s3"
S3_ENDPOINT=""              # Optional: Custom endpoint for MinIO/compatible services
S3_ACCESS_KEY="your-key"
S3_SECRET_KEY="your-secret"
S3_BUCKET="your-bucket"
S3_REGION="us-east-1"
S3_BUCKET_URL=""            # Optional: Custom public URL (CDN/proxy)

Implementation approach:

  1. Create S3Storage class implementing existing IUploadProvider interface
  2. Create S3Uploader class for multipart uploads (mirroring R2 uploader)
  3. Add 's3' case to UploadFactory (factory pattern)
  4. Route uploads in MediaController based on STORAGE_PROVIDER env var
  5. Frontend uses same AwsS3Multipart Uppy plugin (S3 API compatible)

Configuration examples:

AWS S3:

STORAGE_PROVIDER="s3"
S3_ACCESS_KEY="AKIAIOSFODNN7EXAMPLE"
S3_SECRET_KEY="wJalrXUtnFEMI/..."
S3_BUCKET="my-postiz-bucket"
S3_REGION="us-west-2"
S3_BUCKET_URL="https://my-postiz-bucket.s3.us-west-2.amazonaws.com"

MinIO (self-hosted):

STORAGE_PROVIDER="s3"
S3_ENDPOINT="https://minio.example.com"
S3_ACCESS_KEY="minioadmin"
S3_SECRET_KEY="minioadmin"
S3_BUCKET="postiz"
S3_REGION="us-east-1"
S3_BUCKET_URL="https://minio.example.com/postiz"

🔄️ Additional Information

Backward compatibility:

  • Existing local and cloudflare providers remain unchanged
  • No database migrations required
  • Same media table schema (stores full URLs)

Bug fixes included:

  • Enabled actual file deletion from Cloudflare R2 (was previously a no-op)
  • Added file deletion from local storage when media is deleted
  • Fixed URL trailing slash handling for all providers

Requirements for MinIO /S3 users:

  • Bucket must have public read access enabled: mc anonymous set download myminio/bucket-name
  • This is similar to R2's public access requirement

Testing performed:

  • ✅ Local storage upload/delete
  • ✅ AWS S3 upload/delete
  • ✅ MinIO upload/delete
  • ✅ Multipart upload for large videos
  • ✅ Cloudflare R2 regression test

👀 Have you spent some time to check if this feature request has been raised before?

  • I checked and didn't find similar issue

Are you willing to submit PR?

Yes I am willing to submit a PR!

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions