* doc: Updated cloudflare R2 description * Apply suggestions from code review Co-authored-by: Shahed Nasser <shahednasser@gmail.com> * Update www/apps/resources/app/infrastructure-modules/file/s3/page.mdx Co-authored-by: Shahed Nasser <shahednasser@gmail.com> --------- Co-authored-by: Shahed Nasser <shahednasser@gmail.com>
446 lines
14 KiB
Plaintext
446 lines
14 KiB
Plaintext
import S3BucketAcl from "../../../troubleshooting/_sections/s3/aws-bucket-acl.mdx"
|
|
import CloudflareChecksum from "../../../troubleshooting/_sections/s3/cloudflare-checksum.mdx"
|
|
|
|
import {
|
|
Table,
|
|
Tabs,
|
|
TabsList,
|
|
TabsContent,
|
|
TabsContentWrapper,
|
|
TabsTrigger,
|
|
DetailsList,
|
|
} from "docs-ui"
|
|
|
|
export const metadata = {
|
|
title: `S3 File Module Provider`,
|
|
}
|
|
|
|
# {metadata.title}
|
|
|
|
The S3 File Module Provider integrates Amazon S3 and services following a compatible API (such as MinIO or DigitalOcean Spaces) to store files uploaded to your Medusa application.
|
|
|
|
<Note title="Looking for managed storage?">
|
|
|
|
Cloud offers a managed file storage solution with AWS S3 for your Medusa application. Refer to the [S3](!cloud!/s3) Cloud documentation for more details.
|
|
|
|
</Note>
|
|
|
|
## Prerequisites
|
|
|
|
<Tabs defaultValue="aws">
|
|
<TabsList>
|
|
<TabsTrigger value="aws">AWS S3</TabsTrigger>
|
|
<TabsTrigger value="minio">MinIO</TabsTrigger>
|
|
<TabsTrigger value="spaces">DigitalOcean Spaces</TabsTrigger>
|
|
<TabsTrigger value="supabase">Supabase S3 Storage</TabsTrigger>
|
|
<TabsTrigger value="cloudflare">Cloudflare R2</TabsTrigger>
|
|
</TabsList>
|
|
<TabsContentWrapper>
|
|
<TabsContent value="aws">
|
|
|
|
- [AWS account](https://console.aws.amazon.com/console/home?nc2=h_ct&src=header-signin).
|
|
- Create [AWS user with AmazonS3FullAccess permissions](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-and-attach-iam-policy.html).
|
|
- Create [AWS user access key ID and secret access key](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html#Using_CreateAccessKey).
|
|
- Create [S3 bucket](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html) with the "Public Access setting" enabled:
|
|
1. On your bucket's dashboard, click on the Permissions tab.
|
|
2. Click on the Edit button of the Block public access (bucket settings) section.
|
|
3. In the form that opens, don't toggle any checkboxes and click the "Save changes" button.
|
|
4. Confirm saving the changes by entering `confirm` in the pop-up that shows.
|
|
5. Back on the Permissions page, scroll to the Object Ownership section and click the Edit button.
|
|
6. In the form that opens:
|
|
- Choose the "ACLs enabled" card.
|
|
- Click on the "Save changes" button.
|
|
7. Back on the Permissions page, scroll to the "Access Control List (ACL)" section and click on the Edit button.
|
|
8. In the form that opens, enable the Read permission for "Everyone (public access)".
|
|
9. Check the "I understand the effects of these changes on my objects and buckets." checkbox.
|
|
10. Click on the "Save changes" button.
|
|
|
|
</TabsContent>
|
|
<TabsContent value="minio">
|
|
|
|
- [Install MinIO](https://min.io/docs/minio/linux/index.html).
|
|
- Change port to `9001` using the [console address](https://min.io/docs/minio/linux/reference/minio-server/minio-server.html#minio.server.-console-address) and [address](https://min.io/docs/minio/linux/reference/minio-server/minio-server.html#minio.server.-address) CLI options.
|
|
- Create MinIO access and secret access key:
|
|
- Go to User -> Access Keys
|
|
- Click on the Create Access Keys button.
|
|
- Click on the Create button.
|
|
- Copy the keys of the pop-up. Make sure to copy the secret key as it won't be shown again.
|
|
- Create a [MinIO bucket](https://min.io/docs/minio/linux/administration/console/managing-objects.html#creating-buckets) with public access policy. To add the policy:
|
|
- Go to the bucket's dashboard from Administrator -> Buckets.
|
|
- Under the Summary section, click on the pencil icon next to Access Policy.
|
|
- In the pop-up, choose Custom from the dropdown.
|
|
- In the editor, enter the following:
|
|
|
|
```json highlights={[["15", "{bucketname}", "Replace with the bucket's name."]]}
|
|
{
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Action": [
|
|
"s3:GetObject"
|
|
],
|
|
"Effect": "Allow",
|
|
"Principal": {
|
|
"AWS": [
|
|
"*"
|
|
]
|
|
},
|
|
"Resource": [
|
|
"arn:aws:s3:::{bucketname}/*"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
Make sure to replace `{bucket_name}` with the name of the bucket you created. You can edit the access policy under the Summary section of your bucket's dashboard.
|
|
|
|
</TabsContent>
|
|
<TabsContent value="spaces">
|
|
|
|
- Create [DigitalOcean account](https://cloud.digitalocean.com/registrations/new).
|
|
- Create [DigitalOcean Spaces bucket](https://docs.digitalocean.com/products/spaces/how-to/create/).
|
|
- Create [DigitalOcean Spaces access and secret access keys](https://docs.digitalocean.com/products/spaces/how-to/manage-access/#access-keys).
|
|
|
|
</TabsContent>
|
|
<TabsContent value="supabase">
|
|
|
|
- [Supabase account](https://supabase.com/dashboard/sign-in) with a project.
|
|
- Create [New Public S3 bucket](https://supabase.com/docs/guides/storage/buckets/creating-buckets?queryGroups=language&language=dashboard).
|
|
- Create [New S3 Access Keys](https://supabase.com/docs/guides/storage/s3/authentication?queryGroups=language&language=javascript#s3-access-keys).
|
|
- Create [Storage Policy](https://supabase.com/docs/guides/storage/security/access-control).
|
|
1. On your bucket's dashboard, click on Policies under the Configuration sidebar.
|
|
2. Click on New Policy under "Other policies under storage.objects".
|
|
3. Click get started quickly, choose "insert access for authenticated users only", and click the "Use this template" button.
|
|
4. Click ALL for "Allowed Operations", click the "Review" button, then the "Save policy" button.
|
|
|
|
</TabsContent>
|
|
<TabsContent value="cloudflare">
|
|
1. Create a [Cloudflare account](https://dash.cloudflare.com/sign-up).
|
|
2. Set up your R2 bucket:
|
|
- Navigate to R2 Object Storage in your dashboard. You may need to provide your credit-card information.
|
|
- Click "Create bucket"
|
|
- Enter a unique bucket name
|
|
- Select "Automatic" for location
|
|
- Choose "Standard" for storage class
|
|
- Confirm by clicking "Create bucket"
|
|
3. Configure public access:
|
|
- Make sure you have a [domain configured in your Cloudflare account](https://developers.cloudflare.com/dns/manage-dns-records/how-to/create-dns-records/).
|
|
- On your bucket's dashboard, click on the Settings tab.
|
|
- In the General Section look for Custom Domains (recommended for production use)
|
|
- Click on the Add button to add your domain name.
|
|
- Enter the domain name you want to connect to and select Continue.
|
|
- Review the new record that will be added to the DNS table and select Connect Domain.
|
|
4. Retrieve credentials:
|
|
- [Go to API tokens page](https://dash.cloudflare.com/?to=/:account/r2/api-tokens):
|
|
- Click "Create User API token"
|
|
- Edit the "R2 Token" name
|
|
- Under Permissions, select Object Read & Write permission types
|
|
- You can optionally specify the buckets that this API token has access to under the "Specify bucket(s)" section.
|
|
- Once done, click the "Create User API Token" button.
|
|
- Copy the jurisdiction-specific endpoint for S3 clients to S3_ENDPOINT into your environment variables.
|
|
- Copy the Access Key ID and Secret Access Key to the corresponding fields into your environment variables.
|
|
- Copy your custom domain to `S3_FILE_URL` with leading https:// into your environment variables.
|
|
|
|
</TabsContent>
|
|
|
|
</TabsContentWrapper>
|
|
</Tabs>
|
|
|
|
---
|
|
|
|
## Register the S3 File Module
|
|
|
|
Add the module into the `providers` array of the File Module:
|
|
|
|
<Note>
|
|
|
|
The File Module accepts one provider only.
|
|
|
|
</Note>
|
|
|
|
```ts title="medusa-config.ts"
|
|
import { Modules } from "@medusajs/framework/utils"
|
|
|
|
// ...
|
|
|
|
module.exports = {
|
|
// ...
|
|
modules: [
|
|
// ...
|
|
{
|
|
resolve: "@medusajs/medusa/file",
|
|
options: {
|
|
providers: [
|
|
{
|
|
resolve: "@medusajs/medusa/file-s3",
|
|
id: "s3",
|
|
options: {
|
|
file_url: process.env.S3_FILE_URL,
|
|
access_key_id: process.env.S3_ACCESS_KEY_ID,
|
|
secret_access_key: process.env.S3_SECRET_ACCESS_KEY,
|
|
region: process.env.S3_REGION,
|
|
bucket: process.env.S3_BUCKET,
|
|
endpoint: process.env.S3_ENDPOINT,
|
|
// other options...
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
}
|
|
```
|
|
|
|
### Additional Configuration for MinIO and Supabase
|
|
|
|
If you're using MinIO or Supabase, set `forcePathStyle` to `true` in the `additional_client_config` object.
|
|
|
|
For example:
|
|
|
|
```ts title="medusa-config.ts"
|
|
module.exports = defineConfig({
|
|
// ...
|
|
modules: [
|
|
{
|
|
resolve: "@medusajs/medusa/file",
|
|
options: {
|
|
providers: [
|
|
{
|
|
resolve: "@medusajs/medusa/file-s3",
|
|
id: "s3",
|
|
options: {
|
|
// ...
|
|
additional_client_config: {
|
|
forcePathStyle: true,
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
})
|
|
```
|
|
|
|
### S3 File Module Options
|
|
|
|
<Table>
|
|
<Table.Header>
|
|
<Table.Row>
|
|
<Table.HeaderCell>Option</Table.HeaderCell>
|
|
<Table.HeaderCell>Description</Table.HeaderCell>
|
|
<Table.HeaderCell>Default</Table.HeaderCell>
|
|
</Table.Row>
|
|
</Table.Header>
|
|
<Table.Body>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`file_url`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
The base URL to upload files to.
|
|
|
|
- For AWS S3, the endpoint is of the format `https://{bucket}.s3.{region}.amazonaws.com`
|
|
- For MinIO, it's the URL to the MinIO server with the bucket's name. For example, `https://{server-domain}/{bucket}`. Locally, it may be something like `http://192.168.0.123:9001/{bucket}`.
|
|
- For DigitalOcean Spaces, it's either the Origin Endpoint or the CDN endpoint of your Spaces Object Storage bucket.
|
|
- for Supabase, it's `https://{uniqueID}.supabase.co/storage/v1/object/public/{bucket}`. You can retrieve the `uniqueID` from [Storage Settings](https://supabase.com/docs/guides/storage/s3/authentication?queryGroups=language&language=javascript#s3-access-keys) page in the Endpoint URL.
|
|
- For Cloudflare R2, it's your `Custom Domain` (recommended for production use) or `Public R2.dev Bucket URL` (for development).
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`access_key_id`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
The AWS or (S3 compatible) user's access key ID.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`secret_access_key`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
The AWS or (S3 compatible) user's secret access key.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`region`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
The bucket's region code.
|
|
|
|
For MinIO, use `us-east-1`.
|
|
|
|
For Cloudflare, use `auto`.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`bucket`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
The bucket's name.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`endpoint`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
The URL to the AWS S3 (or compatible S3 API) server.
|
|
|
|
- For AWS S3, the endpoint is of the format `https://s3.{region}.amazonaws.com`
|
|
- For MinIO, it's the URL to the MinIO server. For example, locally, it may be something like `http://192.168.0.123:9001`.
|
|
- For DigitalOcean Spaces, it's the Spaces Origin Endpoint of the format `https://{region}.digitaloceanspaces.com`.
|
|
- For Supabase, it's the Endpoint URL in the [Storage Settings](https://supabase.com/docs/guides/storage/s3/authentication?queryGroups=language&language=javascript#s3-access-keys).
|
|
- For Cloudflare, it's the endpoint for S3 clients `https://{your-account-id}.r2.cloudflarestorage.com`.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`prefix`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
A string to prefix each uploaded file's name.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`cache_control`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
A string indicating how long objects remain in the AWS S3 (or compatible S3 API) cache.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
`public, max-age=31536000`
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`download_file_duration`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
A number indicating the expiry time of presigned URLs in seconds.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
`3600` (An hour)
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
<Table.Row>
|
|
<Table.Cell>
|
|
|
|
`additional_client_config`
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
Any additional configurations to pass to the S3 client.
|
|
|
|
Refer to [this AWS API reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Config.html) for a full list of accepted configuration.
|
|
|
|
</Table.Cell>
|
|
<Table.Cell>
|
|
|
|
\-
|
|
|
|
</Table.Cell>
|
|
</Table.Row>
|
|
|
|
</Table.Body>
|
|
</Table>
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
<DetailsList
|
|
sections={[
|
|
{
|
|
title:
|
|
"AWS: The bucket does not allow ACLs (Enabling public access to bucket)",
|
|
content: <S3BucketAcl />,
|
|
},
|
|
{
|
|
title: "Cloudflare: Checksum error",
|
|
content: <CloudflareChecksum />,
|
|
},
|
|
]}
|
|
/>
|