File storage
Files can be uploaded using any S3 compatible storage provider (S3, Cloudflare R2, DigitalOcean Spaces etc.). There is a simple interface defined in app/services/storage/types.ts
which allows you to swap out and configure the underlying storage provider implementation without updating your entire app. By default, Launchway comes with drivers for S3 itself and Cloudflare R2. The Cloudflare R2 implementation is ultimately just a really light wrapper around the S3 SDK implementation with some different properties, as it would also be for DigitalOcean Spaces or Backblaze R2.
# If using S3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
# If using Cloudflare R2
CLOUDFLARE_TOKEN=
CLOUDFLARE_R2_ACCESS_KEY_ID=
CLOUDFLARE_R2_ACCESS_SECRET_KEY=
CLOUDFLARE_R2_ENDPOINT=
Configuring your S3 bucket
Cloudflare
There is official documentation here (opens in a new tab), but if you want the quickstart you can follow the steps below.
- Go to Cloudflare R2 in the dashboard (opens in a new tab), go to R2 and click
"Create bucket"
- Name your bucket and save
- Edit the CORS policy to this
[
{
"AllowedOrigins": [
"http://localhost:3000",
"https://<your-live-environment-url>"
],
"AllowedMethods": [
"GET",
"HEAD",
"PUT",
"POST",
"DELETE"
],
"AllowedHeaders": [
"*"
],
"MaxAgeSeconds": 3000
}
]
- Go to
"Manage R2 API Tokens"
and create a new token with"Object Read & Write"
permissions and take note of the values - Set the following environment variables
USER_UPLOADS_BUCKET_NAME=<your-bucket-name> CLOUDFLARE_TOKEN=<your-token-value> CLOUDFLARE_R2_ACCESS_KEY_ID=<your-token-access-key> CLOUDFLARE_R2_ACCESS_SECRET_KEY=<your-token-secret-key> CLOUDFLARE_R2_ENDPOINT=https://<your-cloudflare-account-id>.r2.cloudflarestorage.com
S3
Operations
The interface comes with four simple operations that are standard across S3-compatible storage providers
generateSignedUploadUrl()
This is used to generate a one-time upload link to your S3-compatible storage bucket. With this you can block all public access to your bucket but still allow authenticated users to upload objects to it.
generateSignedGetUrl()
This is needed for private bucket objects. Like the pre-signed upload URL, it allows you to grant temporary access to an object in a bucket without having to expose the bucket to the internet.
uploadFile()
This is for server-side uploads of files not provided explicitly by the user. An example would be a report that is generated on behalf of the user and uploaded for later viewing.
deleteFile()
Remove a file. This should be handled with caution and you should always ensure the user owns has write access to the object first.