LogoLaunchSaaS

Storage

Configure storage providers for file uploads

Storage

LaunchSaaS supports multiple storage providers with an extensible architecture. You can easily switch between S3-compatible providers or add custom implementations.

Supported Providers

  • S3 - AWS S3, Cloudflare R2, MinIO, and other S3-compatible services
  • Custom - Extend with your own storage provider

Configuration

Configure your storage provider in src/configuration/features.ts:

export const features: Features = {
  storage: {
    provider: "s3", // "s3" | "disabled"
  },
  // ... other features
};

Setup S3-Compatible Storage

  1. Go to Cloudflare Dashboard → R2
  2. Create a bucket
  3. Create an API token with R2 permissions
  4. Add to your .env:
S3_REGION="auto"
S3_BUCKET="your-bucket-name"
S3_ACCESS_KEY_ID="your-access-key-id"
S3_SECRET_ACCESS_KEY="your-secret-access-key"
S3_API_ENDPOINT="https://<account-id>.r2.cloudflarestorage.com"
S3_PUBLIC_ENDPOINT="https://pub-<id>.r2.dev"

AWS S3

  1. Go to AWS S3 Console
  2. Create a bucket
  3. Create an IAM user with S3 permissions
  4. Add to your .env:
S3_REGION="us-east-1"
S3_BUCKET="your-bucket-name"
S3_ACCESS_KEY_ID="your-access-key-id"
S3_SECRET_ACCESS_KEY="your-secret-access-key"
S3_API_ENDPOINT="https://s3.us-east-1.amazonaws.com"
S3_PUBLIC_ENDPOINT="https://your-bucket-name.s3.us-east-1.amazonaws.com"

MinIO (Self-Hosted)

  1. Deploy MinIO server
  2. Create a bucket
  3. Create access credentials
  4. Add to your .env:
S3_REGION="us-east-1"
S3_BUCKET="your-bucket-name"
S3_ACCESS_KEY_ID="your-access-key"
S3_SECRET_ACCESS_KEY="your-secret-key"
S3_API_ENDPOINT="https://your-minio-server.com"
S3_PUBLIC_ENDPOINT="https://your-minio-server.com/your-bucket-name"

Environment Variables

VariableDescription
S3_REGIONRegion (e.g., us-east-1, auto for R2)
S3_BUCKETBucket name
S3_ACCESS_KEY_IDAccess key ID
S3_SECRET_ACCESS_KEYSecret access key
S3_API_ENDPOINTS3 API endpoint URL
S3_PUBLIC_ENDPOINTPublic URL for accessing files

CORS Configuration

For browser uploads, configure CORS on your bucket:

[
  {
    "AllowedOrigins": ["https://yourdomain.com"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
    "AllowedHeaders": ["*"],
    "MaxAgeSeconds": 3600
  }
]

Custom Storage Provider

To add a custom storage provider:

  1. Create a new provider class in src/lib/storage/providers/ implementing the StorageProvider interface
  2. Register in src/lib/storage/factory.ts
  3. Add to the Features type in src/schemas/site-configuration.ts

Example:

import { StorageProvider } from "../provider";

export class CustomStorageProvider implements StorageProvider {
  async upload(file: File, path: string): Promise<string> {
    // Implement upload logic
    return "https://example.com/file.jpg";
  }

  async delete(path: string): Promise<void> {
    // Implement delete logic
  }

  async getSignedUrl(path: string, expiresIn?: number): Promise<string> {
    // Implement signed URL generation
    return "https://example.com/file.jpg?signature=...";
  }
}

Register in factory:

case "custom":
  return new CustomStorageProvider();

Disable Storage

To disable storage functionality:

export const features: Features = {
  storage: {
    provider: "disabled",
  },
};

When disabled, the system uses a no-op provider that logs storage operations to console instead of executing them.

References

Next Steps