mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-29 08:52:25 +00:00
Updates `content/upload-content.md` and `docs/storage-r2.md` to reflect the current manual configuration workflow for Cloudflare R2 storage. Key changes: - Removes deprecated instructions for generating "Admin Read & Write" or "Workers R2 Storage" automation tokens. - Documents the new requirement to manually create a bucket and enable "Public Access" (r2.dev subdomain) in the Cloudflare Dashboard. - Adds explicit instructions for manually configuring CORS policy via the Cloudflare Dashboard, providing the required JSON configuration. - Aligns the "Configure bitvid" steps with the application's current UI, which requires the "Public Bucket URL" as an explicit input. - Clarifies that "Object Read & Write" permissions are sufficient and recommended for security.
118 lines
6.1 KiB
Markdown
118 lines
6.1 KiB
Markdown
# Cloudflare R2 integration (r2Service)
|
|
|
|
## Purpose and scope
|
|
`js/services/r2Service.js` is the client-side coordinator for Cloudflare R2 uploads. It owns:
|
|
|
|
- Local persistence of Cloudflare credentials and bucket metadata used by the Upload modal.
|
|
- Uploading the selected video/HLS asset via multipart S3 uploads and publishing the resulting
|
|
public URL into the video note payload.
|
|
- Verifying public access via the configured Public Bucket URL.
|
|
|
|
The service is used from the Upload modal UI (via `js/ui/components/UploadModal.js`) and is not a
|
|
backend integration.
|
|
|
|
## Assets stored in R2
|
|
R2 is used as the URL-first playback source. The upload path supports a single file per upload, but
|
|
file types include:
|
|
|
|
- Video files (MP4/WebM/MOV/MKV/MPG/MPEG).
|
|
- HLS/DASH assets (manifest `.m3u8`/`.mpd` and segment files like `.ts`/`.m4s`).
|
|
- Related static media if the operator chooses to upload them separately (images, subtitles such as
|
|
`.vtt`/`.srt`), which benefit from cache-friendly headers set in the upload flow.
|
|
|
|
The object key format is generated by `buildR2Key()` in `js/r2.js` and looks like:
|
|
`u/<npub>/<YYYY>/<MM>/<slug>.<ext>`, which keeps uploads scoped by user and month.
|
|
|
|
## Setup Guide: Getting your Cloudflare Credentials
|
|
|
|
To enable R2 uploads, you must provide Cloudflare S3-compatible credentials and configure your bucket for public access and CORS.
|
|
|
|
### Step 1: Create Bucket & Enable Public Access
|
|
1. Log in to the **Cloudflare Dashboard**.
|
|
2. Navigate to **R2** -> **Create Bucket**.
|
|
3. In the bucket settings, enable **Public Access** (R2.dev subdomain) or connect a custom domain.
|
|
4. Copy the **Public Bucket URL** (e.g., `https://pub-xxxxxx.r2.dev`).
|
|
|
|
### Step 2: Configure CORS
|
|
Manually add a CORS policy in the bucket settings to allow uploads from your app's origin (or `*`).
|
|
(See `content/upload-content.md` for the recommended JSON configuration).
|
|
|
|
### Step 3: Create S3 Credentials
|
|
1. In the R2 dashboard, click **Manage R2 API Tokens**.
|
|
2. Click **Create API Token**.
|
|
3. Select **Object Read & Write** permissions (Minimal).
|
|
4. Copy the **Account ID**, **Access Key ID**, and **Secret Access Key**.
|
|
|
|
### Step 4: Configure the App
|
|
1. Open the Upload Modal in the app.
|
|
2. Expand **Storage Settings**.
|
|
3. Enter the **Account ID**, **Access Key ID**, **Secret Access Key**, and **Public Bucket URL**.
|
|
4. Click **Verify & Save**.
|
|
|
|
The app will attempt to upload a small test file to verify the credentials and public access configuration.
|
|
|
|
## Upload lifecycle
|
|
1. **Settings saved locally**
|
|
- The Upload modal calls `r2Service.saveSettings()` to persist Cloudflare credentials. Settings are stored in IndexedDB (`bitvidSettings` → `kv`)
|
|
with a localStorage fallback (`bitvid:r2Settings`).
|
|
|
|
2. **Bucket preparation**
|
|
- The service relies on the user ensuring the bucket exists and is configured for CORS.
|
|
- It attempts a "best-effort" auto-configuration using the S3 keys (requires broader permissions), but strictly supports the manual "Object Read & Write" flow.
|
|
|
|
3. **Upload and publish**
|
|
- The service builds the R2 object key and public URL.
|
|
- `multipartUpload()` uploads the file using S3 multipart uploads.
|
|
- On success, `publishVideoNote()` is called with the hosted URL, so playback can be URL-first
|
|
with magnet fallback.
|
|
|
|
4. **UI feedback**
|
|
- The Upload modal receives progress, status, and verification errors via `r2Service` events.
|
|
|
|
## Download / playback flow
|
|
There is no direct “download” API for R2 in `r2Service`. Instead, R2 provides the public URL that
|
|
gets saved into the video note payload. Playback uses that URL as the primary source and only falls
|
|
back to magnet/WebTorrent when needed, preserving the URL-first playback promise.
|
|
|
|
## Configuration keys and where they live
|
|
**Stored locally (IndexedDB / localStorage):**
|
|
- `accountId`: Cloudflare account ID.
|
|
- `accessKeyId`: R2 S3 access key ID.
|
|
- `secretAccessKey`: R2 S3 secret access key.
|
|
- `baseDomain`: The Public Bucket URL (e.g., `https://pub-xxxx.r2.dev`) used to generate file URLs.
|
|
- `buckets`: Cached map of `npub` → `{ bucket, publicBaseUrl, domainType, lastUpdated }`.
|
|
|
|
**Environment / global flags:**
|
|
- `globalThis.__BITVID_DISABLE_NETWORK_IMPORTS__`: disables the AWS SDK network import used by the
|
|
R2 S3 client loader (`js/storage/r2-s3.js`). When true, uploads will fail with a load error until
|
|
the SDK is bundled or otherwise provided.
|
|
|
|
**Config files:**
|
|
- There are no R2-specific keys in `config/` today; all R2 settings are entered through the UI and
|
|
stored locally in the browser.
|
|
|
|
## Retry and fallback behavior
|
|
- **Bucket/domain setup:**
|
|
- The system now relies on explicit user configuration for the Public Bucket URL (`baseDomain`). If this is missing or incorrect, verification will fail.
|
|
- **CORS:**
|
|
- The app attempts to set CORS if permissions allow, but largely assumes the user has configured it manually if using minimal tokens.
|
|
- **Multipart uploads:**
|
|
- There is no custom retry loop inside `multipartUpload()`. Failures propagate to the UI; the
|
|
caller can retry by re-initiating the upload.
|
|
|
|
## Security considerations
|
|
- **Credential storage:** R2 credentials are stored in browser storage. Treat them as
|
|
sensitive and avoid sharing browser profiles. Clear settings via the Upload modal when done.
|
|
- **Public exposure:** The generated URLs are public; uploaded assets should be safe for public
|
|
access. Use signed URLs only if you add a separate access layer.
|
|
- **CORS and origins:** Ideally, scope CORS rules to the current origin to avoid overly broad exposure, though `*` is often used for ease of setup.
|
|
- **Minimal Permissions:** We recommend "Object Read & Write" tokens to limit the scope of the keys to specific buckets and prevent admin actions.
|
|
|
|
## Impact on uploads and playback
|
|
- **Uploads:** Successful R2 uploads produce a hosted URL stored in the video note payload, enabling
|
|
URL-first playback. Metadata such as MIME type and the public URL are also stitched into the NIP-71
|
|
metadata block during publish.
|
|
- **Playback:** The hosted URL is the primary stream source. If it fails, playback can still fall
|
|
back to the magnet/WebTorrent path, so the R2 integration improves reliability without removing
|
|
P2P fallback.
|