diff --git a/README.md b/README.md index 1968658b..848e9e11 100644 --- a/README.md +++ b/README.md @@ -83,24 +83,27 @@ Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used a - Setup CORS under bucket settings: ```json [{ - "AllowedHeaders": ["*"] - "AllowedOrigins": [ - "http://localhost:3000", - "https://{VERCEL_PROJECT_NAME}*.vercel.app", - "{PRODUCTION_DOMAIN}" - ], + "AllowedHeaders": ["*"], "AllowedMethods": [ "GET", "PUT" ], + "AllowedOrigins": [ + "http://localhost:3000", + "https://{VERCEL_PROJECT_NAME}*.vercel.app", + "{PRODUCTION_DOMAIN}" + ] }] ``` + - Enable public hosting by doing one of the following: + - Select "Connect Custom Domain" and choose a Cloudflare domain + - Select "Allow Access" from R2.dev subdomain - Enable R2.dev subdomain (necessary in order to serve files publicly without a custom domain) - - Store configuration: + - Store public configuration: - `NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET`: bucket name - `NEXT_PUBLIC_CLOUDFLARE_R2_ACCOUNT_ID`: account id (found on R2 overview page) - - `NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN`: r2.dev subdomain, e.g., "pub-jf90908..." -2. Setup credentials + - `NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_DOMAIN`: e.g., either "pub-jf90908...r2.dev" or "custom-domain.com" +2. Setup private credentials - Create API token by selecting "Manage R2 API Tokens," and clicking "Create API Token" - Select "Object Read & Write," choose "Apply to specific buckets only," and select the bucket created in Step 1. - Store credentials (⚠️ _Ensure access keys are not prefixed with `NEXT_PUBLIC`_): @@ -127,10 +130,10 @@ Only one storage adapter—Vercel Blob, Cloudflare R2, or AWS S3—can be used a "ExposeHeaders": [] }] ``` - - Store configuration + - Store public configuration - `NEXT_PUBLIC_AWS_S3_BUCKET`: bucket name - `NEXT_PUBLIC_AWS_S3_REGION`: bucket region, e.g., "us-east-1" -2. Setup credentials +2. Setup private credentials - [Create IAM policy](https://console.aws.amazon.com/iam/home#/policies) using JSON editor: ```json { diff --git a/next.config.js b/next.config.js index bd880f53..622bcafa 100644 --- a/next.config.js +++ b/next.config.js @@ -7,9 +7,7 @@ const VERCEL_BLOB_HOSTNAME = VERCEL_BLOB_STORE_ID : undefined; const CLOUDFLARE_R2_HOSTNAME = - process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN - ? `${process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN}.r2.dev` - : undefined; + process.env.NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_DOMAIN; const AWS_S3_HOSTNAME = process.env.NEXT_PUBLIC_AWS_S3_BUCKET && diff --git a/src/services/storage/cloudflare-r2.ts b/src/services/storage/cloudflare-r2.ts index 7866005a..a38bf87e 100644 --- a/src/services/storage/cloudflare-r2.ts +++ b/src/services/storage/cloudflare-r2.ts @@ -11,8 +11,8 @@ const CLOUDFLARE_R2_BUCKET = process.env.NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET ?? ''; const CLOUDFLARE_R2_ACCOUNT_ID = process.env.NEXT_PUBLIC_CLOUDFLARE_R2_ACCOUNT_ID ?? ''; -const CLOUDFLARE_R2_DEV_SUBDOMAIN = - process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN ?? ''; +const CLOUDFLARE_R2_PUBLIC_DOMAIN = + process.env.NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_DOMAIN ?? ''; const CLOUDFLARE_R2_ACCESS_KEY = process.env.CLOUDFLARE_R2_ACCESS_KEY ?? ''; const CLOUDFLARE_R2_SECRET_ACCESS_KEY = @@ -20,12 +20,12 @@ const CLOUDFLARE_R2_SECRET_ACCESS_KEY = const CLOUDFLARE_R2_ENDPOINT = `https://${CLOUDFLARE_R2_ACCOUNT_ID}.r2.cloudflarestorage.com`; +export const CLOUDFLARE_R2_BASE_URL_PUBLIC = + `https://${CLOUDFLARE_R2_PUBLIC_DOMAIN}`; + export const CLOUDFLARE_R2_BASE_URL_PRIVATE = `${CLOUDFLARE_R2_ENDPOINT}/${CLOUDFLARE_R2_BUCKET}`; -export const CLOUDFLARE_R2_BASE_URL_PUBLIC = - `https://${CLOUDFLARE_R2_DEV_SUBDOMAIN}.r2.dev`; - export const cloudflareR2Client = () => new S3Client({ region: 'auto', endpoint: CLOUDFLARE_R2_ENDPOINT, diff --git a/src/site/config.ts b/src/site/config.ts index d6db47dd..ced3bf09 100644 --- a/src/site/config.ts +++ b/src/site/config.ts @@ -40,7 +40,7 @@ export const HAS_VERCEL_BLOB_STORAGE = export const HAS_CLOUDFLARE_R2_STORAGE_CLIENT = (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_BUCKET ?? '').length > 0 && (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_ACCOUNT_ID ?? '').length > 0 && - (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_DEV_SUBDOMAIN ?? '').length > 0; + (process.env.NEXT_PUBLIC_CLOUDFLARE_R2_PUBLIC_DOMAIN ?? '').length > 0; export const HAS_CLOUDFLARE_R2_STORAGE = HAS_CLOUDFLARE_R2_STORAGE_CLIENT && (process.env.CLOUDFLARE_R2_ACCESS_KEY ?? '').length > 0 &&