DRM-X 6.0 dove 및 올리브 지점 로고DRM-X 6.0문서
◎ 한국어

Cloudflare R2: bucket, CORS and delivery

Create an R2 bucket, configure upload and playback CORS, connect a custom domain or r2.dev testing URL, and verify an upload through DRM-X 6.0.

Markdown 보기실행 예제Updated 2026-09-18

암호화된 동영상과 DRM 라이선스는 서로 다른 경로로 전달됩니다

CDN은 암호화된 동영상을 전달합니다. 백엔드가 접근 권한을 확인하고, DRM 라이선스 서비스가 호환 기기에서의 복호화를 승인합니다.

  1. 스토리지 / CDN

    암호화된 미디어를 플레이어에 전달합니다.

  2. 고객 백엔드

    시청 권한을 확인하고 DRM-X에 재생 승인을 요청합니다.

  3. DRM-X

    재생 승인 정보를 검증하고 DRM 라이선스 요청을 처리합니다.

  4. 플레이어 + 기기

    기기의 DRM 시스템으로 라이선스를 받아 암호화된 미디어를 재생합니다.

귀하의 백엔드가 접근을 결정합니다. DRM-X는 서명 된 정책을 시행합니다. 암호화 된 미디어 및 DRM 라이센스는 별도의 배송 경로를 따릅니다.

This step-by-step guide is currently available in English.

From a new bucket to a working uploadCreate an R2 bucket, configure browser CORS, choose a public HTTPS delivery URL, connect DRM-X, and upload and retrieve a test object. Keep original videos and private documents outside this delivery bucket. Publish only encrypted media and intended public assets.

Public delivery makes object bytes reachable by URL; DRM controls decryption of correctly packaged media. CORS is a browser compatibility rule, not authorization. These real console screenshots exclude account headers and personal identifiers. Menu wording may change.

1. Create your R2 bucket#

  1. Sign in to Cloudflare and choose the account that will own the bucket.
  2. Open Storage & databases → R2 Object Storage → Overview → Create bucket.
  3. Enter a unique bucket name, such as customer-drm-media-example. Select an appropriate location or jurisdiction. Use Standard storage for this walkthrough, then create the bucket.
  4. Open the bucket's Settings. Record the bucket name, Cloudflare account ID and General → S3 API endpoint.

For default jurisdiction, the API endpoint is https://<ACCOUNT_ID>.r2.cloudflarestorage.com. If Cloudflare shows a jurisdiction-specific hostname, use that exact hostname. Remove a trailing /bucket-name when entering the endpoint in DRM-X; the bucket name has its own field. This API endpoint is not a public playback URL.

2. Create bucket-scoped credentials#

  1. Return to R2 Overview and open Manage API tokens. Choose an R2 account token, or a user token if required by your organization.
  2. Select Create API token, give it a recognizable name, and choose Object Read & Write.
  3. Choose Apply to specific buckets only and select this bucket. Configure expiry according to your policy. For this walkthrough, leave optional IP filtering unset. If your security policy requires it, validate both DRM-X server access and direct uploads from customer browser networks.
  4. Create the token and securely record the Access Key ID and Secret Access Key for DRM-X.
Use the S3 credential pairThe separate Cloudflare Token value is not the S3 Secret Access Key. DRM-X does not need an account-wide administrative token. Manage CORS and domains yourself in Cloudflare.

3. Choose your public delivery URL#

R2 Settings: Add under Custom Domains, or Enable under Public Development URL.
1 — Production: Add a custom domain. 2 — Testing: Enable the public development URL.

Option A: connect your domain for production

  1. Have a domain with its DNS setup completed in the same Cloudflare account. Choose a subdomain such as media.example.com.
  2. In the bucket, open Settings → Custom Domains → Add. Enter the subdomain, review the DNS change, and connect it using this R2 workflow.
  3. Wait for the domain and HTTPS certificate to become active. Your delivery origin is https://media.example.com.

Do not create a CNAME pointing to an r2.dev address. Use R2's Custom Domains workflow. The development URL can stay disabled when a custom domain is connected.

Option B: enable Cloudflare's URL for testing

  1. Open Settings → Public Development URL → Enable.
  2. Review the public-access notice, type allow when requested, and confirm.
  3. Copy the actual https://pub-….r2.dev URL displayed by Cloudflare. Do not construct it from your account ID or bucket name.

The r2.dev endpoint is rate-limited and intended for development. Use a custom domain for production, caching and Cloudflare security features.

4. Configure browser upload and playback CORS#

R2 CORS Policy panel with Edit, allowed origins, methods and headers.
1: choose Add CORS policy for a new bucket, or Edit. 2: confirm the saved origin, methods and headers. This screenshot shows a Console-only diagnostic rule; use the complete two-rule example below for your player websites.
  1. Open Settings → CORS Policy → Add CORS policy (or Edit).
  2. Paste the JSON below in the editor. Replace https://www.example.com with the origin of the website that embeds your player. An origin includes HTTPS and the hostname, but no page path such as /watch.
  3. Preserve other required rules if the bucket already has a policy, then select Save.
  4. Allow time for propagation, then retry the upload. If custom-domain objects have old CORS headers cached, purge the affected paths and test again.
[
  {
    "AllowedOrigins": [
      "https://6.drm-x.com"
    ],
    "AllowedMethods": [
      "PUT"
    ],
    "AllowedHeaders": [
      "Content-Type",
      "x-amz-meta-drmx-sha256"
    ],
    "ExposeHeaders": [
      "ETag"
    ],
    "MaxAgeSeconds": 3600
  },
  {
    "AllowedOrigins": [
      "https://6.drm-x.com",
      "https://multi-drm.drm-x.com",
      "https://www.example.com"
    ],
    "AllowedMethods": [
      "GET",
      "HEAD"
    ],
    "AllowedHeaders": [
      "Range"
    ],
    "ExposeHeaders": [
      "ETag",
      "Content-Length",
      "Content-Range",
      "Accept-Ranges"
    ],
    "MaxAgeSeconds": 3600
  }
]

The first rule allows signed PUT uploads from DRM-X Console. The second allows GET/HEAD from your player website and DRM-X test pages. R2 custom domains use the bucket's CORS policy. CORS does not grant anonymous upload access.

Generate your CORS and matching URL fields

This tool runs in your browser. Enter public origins only; it does not ask for access keys.

Replace the example. Separate multiple HTTPS origins with spaces or commas. Use the website embedding your player, without a page path. DRM-X Console and Playback Lab are included automatically.Enter your connected custom domain, enabled r2.dev URL, or CloudFront origin. Omit the folder here.

5. Connect R2 in DRM-X 6.0#

Open Cloud Storage → Connect storage and choose Cloudflare R2.

FieldWhat to enter
Display nameA friendly label, such as Production R2.
Bucket nameThe exact bucket name, without a URL or folder.
Cloudflare account IDThe ID of the account that owns this bucket.
S3 API endpointLeave blank for default jurisdiction, or enter the account/jurisdiction endpoint without the bucket path.
Protected-content base pathprotected, or blank for bucket-root uploads.
Public URL prefixhttps://media.example.com/protected or your enabled https://pub-….r2.dev/protected URL.
Access key ID / Secret access keyThe S3 credential pair from step 2.

The examples use a folder called protected. The bucket name is not automatically a folder. With the direct domain-to-bucket mapping used here, include the same storage folder exactly once in the public URL prefix.

Bucket:                      customer-drm-media-example
Protected-content base path: protected
Public URL prefix:           https://media.example.com/protected
File selected for upload:    sample.encrypted.bin
Object key in the bucket:    protected/sample.encrypted.bin
Preview URL:                 https://media.example.com/protected/sample.encrypted.bin

To use the bucket root, leave the base path blank and enter only the delivery origin as the public prefix. Do not append a bucket name unless you deliberately use it as a folder. Leave CloudFront Origin path empty for this mapping.

Choose Use as default CLI upload destination if desired. Select Save and verify. Credentials are encrypted at rest and are not returned after saving. Continue to the real upload test even if verification succeeds.

6. Upload a file and verify that it works#

  1. Open Cloud Storage, select this destination and choose Verify location. Success means the DRM-X server can list the bucket. It does not establish write permission, browser CORS or public delivery.
  2. Select Upload encrypted files and choose one small encrypted segment from an existing DRM-X package. If you do not have a package, use the disposable encrypted diagnostic below. Do not upload an original video or personal document.
  3. Wait for the success message. Check that the filename and size appear in Cloud Storage. Find the same object under protected/ in your provider console.
  4. Click Preview URL, and test that same object in a private browser window. It should download or return HTTP 200 without an AWS or Cloudflare login. Test an actual object: a domain's root can return 403/404 even when object delivery works.
  5. Check cross-origin delivery from your player website. Its browser Network panel should show Access-Control-Allow-Origin matching the player page's origin. A direct address-bar download does not test CORS. The terminal example below also checks the headers.
  6. Remove only your disposable diagnostic object when done. Then follow the Desktop Packager guide, select this storage destination in Package content, and upload the complete encrypted package. Manually uploading a file does not register a Published Content ID.
  7. Test the resulting Published file in Universal Playback Lab and your own player website. Verify video, audio, seeking and your required devices. A successful binary download is not proof of DRM playback.
No encrypted sample? Create a disposable test file on Windows

Run this in Windows PowerShell in a temporary folder you control. It encrypts a short non-personal message with a one-use AES key held only in memory. The output is a storage diagnostic, not playable media; it contains no DRM content key or customer data.

$samplePath = Join-Path (Get-Location) 'drmx-storage-check.encrypted.bin'
if (Test-Path -LiteralPath $samplePath) { throw 'Choose a new folder; this test file already exists.' }
$aes = [System.Security.Cryptography.Aes]::Create()
try {
    $aes.GenerateKey()
    $aes.GenerateIV()
    $encryptor = $aes.CreateEncryptor()
    try {
        $bytes = [Text.Encoding]::UTF8.GetBytes('DRM-X disposable storage check')
        $encrypted = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length)
        [IO.File]::WriteAllBytes($samplePath, $encrypted)
    } finally { $encryptor.Dispose() }
} finally { $aes.Dispose() }
Get-Item -LiteralPath $samplePath | Select-Object Name, Length

Upload drmx-storage-check.encrypted.bin, verify its size and Preview URL, then remove it from the bucket.

curl.exe -I -H "Origin: https://www.example.com" "https://media.example.com/protected/sample.encrypted.bin"

Replace both URLs. Expect HTTP 200 and an allowed origin matching your player website. For range delivery, a GET request with Range: bytes=0-15 should return HTTP 206 and a valid Content-Range header. Preserve media MIME types: DASH manifests use application/dash+xml, HLS playlists use application/vnd.apple.mpegurl, and media files must use their appropriate media type.

7. Troubleshoot your result#

ResultAction
Verify passes; browser upload failsInspect the browser Console and Network panels. Allow PUT CORS from the exact Console origin and Content-Type. Also check connectivity and retry for a fresh presigned URL.
Upload returns 403Check object write permission, bucket/folder scope, endpoint, region, request expiry and clock. Do not share signed upload URLs.
Upload succeeds; public URL returns 403Check whether public delivery is enabled and the domain/distribution has finished deploying.
Public URL returns 404Compare the full URL against the exact object key. Check missing or duplicated folders and filename case.
URL opens directly; player fetch failsAdd the player page origin to GET/HEAD CORS. Check CDN response headers and invalidate affected stale cached responses.
Download succeeds; playback failsCheck package publication, manifest paths, MIME types and DRM license authorization. See playback troubleshooting.

Official references#

Using AWS? Follow Amazon S3 and CloudFront setup.