Skip to content
smallPict

Dùng Bộ nhớ + CDN của Riêng bạn

Kết nối object storage và CDN của riêng bạn trên các gói API Velocity và Momentum: thiết lập theo từng nhà cung cấp, quyền tối thiểu, bước kiểm tra kết nối và điều gì xảy ra khi bạn chuyển chế độ.

Áp dụng cho: các gói API Velocity và Momentum. Không áp dụng cho Ignite (không có CDN), sandbox dành cho nhà phát triển (tệp trong sandbox là tạm thời) hoặc các gói WordPress (dùng CDN smallPict được quản lý).

Tóm tắt: Ở chế độ BYO, smallPict ghi ảnh gốc và ảnh đã tối ưu vào bucket của bạn, và CDN của bạn phân phối chúng. Bộ nhớ và CDN luôn được kết nối cùng nhau: bạn không thể dùng một phần mà thiếu phần còn lại.


BYO là gì

Velocity và Momentum có hai chế độ phân phối. Bạn chọn một chế độ trong Bảng điều khiển → CDN và lưu trữ.

  • Được quản lý (mặc định): smallPict giữ ảnh gốc của bạn trong bộ nhớ được mã hóa của mình (chuyển sang kho lưu trữ dài hạn sau 90 ngày) và phân phối ảnh đã tối ưu từ cdn.smallpict.app. Không cần thiết lập gì.
  • Dùng bộ nhớ + CDN của riêng bạn (BYO): bạn kết nối một bucket tương thích S3 trong tài khoản của mình và một CDN trong tài khoản của mình. Mỗi job mới ghi ảnh gốc và tệp đã tối ưu vào bucket của bạn, và API trả về URL trên tên miền CDN của bạn.

Quy tắc kết nối cùng nhau tồn tại vì smallPict phải thực hiện được cả hai nửa của việc phân phối: ghi tệp và xóa các bản sao cũ khỏi bộ nhớ đệm. Một bucket không có CDN thì yêu cầu xóa bộ nhớ đệm không có nơi để gửi; một CDN không có bucket thì không có gì để phân phối.


Được quản lý và BYO

Được quản lý (mặc định)Dùng bộ nhớ + CDN của riêng bạn
Ảnh gốcBộ nhớ được mã hóa của smallPictoriginals/<job_id>/<file> trong bucket của bạn
Tệp đã tối ưuPhân phối từ cdn.smallpict.appoptimized/<job_id>.<ext> trong bucket của bạn, phân phối từ tên miền CDN của bạn
Hạn mức lưu trữVelocity 50 GB, Momentum 100 GBKhông tính. Bạn trả tiền cho nhà cung cấp lưu trữ của mình.
Băng thông CDNVelocity 30 GB/tháng, Momentum 200 GB/thángKhông tính. Bạn trả tiền cho nhà cung cấp CDN của mình.
Lượt chuyển đổiTính vào gói của bạnTính vào gói của bạn
Bản sao smallPict giữ lạiCó, khi tài khoản của bạn còn hoạt độngKhông có. Chỉ có tệp tải lên tạm thời để xử lý, bị xóa trong vòng 24 giờ.
Xóa bộ nhớ đệmTự độngTự động, thông qua API của CDN của bạn
Hiệu năng, tên miền và chi phí CDNsmallPictBạn. smallPict không chịu trách nhiệm về hiệu năng, tên miền hay hóa đơn CDN của bạn.

Nhà cung cấp được hỗ trợ

Lưu trữ (đã khả dụng): Amazon S3, Cloudflare R2, Google Cloud Storage (khả năng tương thích S3), Alibaba Cloud OSS, Tencent Cloud COS, DigitalOcean Spaces, SumoPod Storage, MinIO và mọi dịch vụ tương thích S3 khác thông qua endpoint tùy chỉnh (ví dụ Hetzner, Vultr hoặc Wasabi).

CDN (đã khả dụng): Cloudflare và Amazon CloudFront.

Dự kiến: Azure Blob Storage và các CDN khác. Bạn có thể yêu cầu truy cập sớm trên trang Nhà cung cấp đám mây.


Trước khi bắt đầu

  1. Bạn đang dùng gói API Velocity hoặc Momentum và đã đăng nhập bằng tài khoản quản trị viên.
  2. Bạn có một bucket và một CDN phân phối tệp từ bucket đó qua HTTPS.
  3. Endpoint lưu trữ có thể truy cập từ internet qua HTTPS. Các endpoint riêng tư, nội bộ và HTTP thuần sẽ bị từ chối.
  4. Bạn đã tạo các khóa có phạm vi hẹp cho smallPict (xem Quyền tối thiểu bên dưới). Đừng dùng khóa root hoặc khóa quản trị của tài khoản.

Sau đó mở Bảng điều khiển → CDN và lưu trữ, chọn Dùng bộ nhớ + CDN của riêng bạn, điền cả hai phần và chọn Lưu bộ nhớ + CDN. smallPict sẽ chạy bước kiểm tra kết nối (mô tả bên dưới) và chỉ chuyển bạn sang BYO nếu kiểm tra thành công.


Hướng dẫn thiết lập

A. Amazon S3 + Amazon CloudFront

  1. Tạo bucket ở khu vực bạn muốn, ví dụ my-images ở ap-southeast-1. Giữ Block Public Access ở trạng thái bật.
  2. Tạo một distribution CloudFront với bucket làm origin. Dùng Origin access control (OAC) để CloudFront có thể đọc bucket trong khi bucket vẫn riêng tư, và áp dụng chính sách bucket mà CloudFront đề xuất.
  3. Tùy chọn: tên miền riêng của bạn. Thêm một tên miền thay thế (ví dụ images.example.com) và chứng chỉ vào distribution, rồi trỏ một bản ghi DNS đến distribution.
  4. Tạo người dùng (hoặc vai trò) IAM cho lưu trữ với chính sách sau:
JSON
{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Action": [        "s3:PutObject",        "s3:GetObject",        "s3:DeleteObject"      ],      "Resource": "arn:aws:s3:::my-images/*"    }  ]}
  1. Tạo người dùng IAM cho CloudFront (có thể là cùng một người dùng) với chính sách sau. cloudfront:GetDistribution là tùy chọn; khi có quyền này, smallPict có thể phát hiện tên miền của distribution nếu bạn để trống tên miền CDN.
JSON
{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Action": [        "cloudfront:CreateInvalidation",        "cloudfront:GetDistribution"      ],      "Resource": "arn:aws:cloudfront::123456789012:distribution/E2QWRUHAPOMQZL"    }  ]}
  1. Trong bảng điều khiển:
    • Nhà cung cấp lưu trữ Amazon S3, bucket my-images, khu vực ap-southeast-1, endpoint để trống (dùng endpoint tiêu chuẩn của khu vực), cùng access key ID và secret cho lưu trữ.
    • CDN Amazon CloudFront, Distribution ID (ví dụ E2QWRUHAPOMQZL), access key ID và secret cho CloudFront, và tùy chọn tên miền CDN (https://images.example.com). Để trống tên miền để dùng tên miền *.cloudfront.net riêng của distribution.

B. Cloudflare R2 + Cloudflare

  1. Tạo một bucket R2, ví dụ my-images.
  2. Kết nối một tên miền tùy chỉnh với bucket (R2 → bucket của bạn → Settings → Custom Domains), ví dụ images.example.com, trên một zone trong cùng tài khoản Cloudflare. Các yêu cầu đến tên miền đó đi qua bộ nhớ đệm Cloudflare. Đừng dùng URL phát triển r2.dev cho môi trường production.
  3. Tạo một API token R2 (R2 → Manage API tokens) với quyền Object Read & Write, giới hạn chỉ cho bucket này. Sao chép Access Key ID và Secret Access Key được hiển thị.
  4. Tạo một API token Cloudflare (My Profile → API Tokens) cho zone với quyền Zone → Cache Purge → Purge. Zone → Zone → Read là tùy chọn.
  5. Trong bảng điều khiển:
    • Nhà cung cấp lưu trữ Cloudflare R2, bucket my-images, endpoint https://<account_id>.r2.cloudflarestorage.com (hiển thị trong phần thông tin S3 API của bucket), khu vực auto, cùng Access Key ID và Secret Access Key của R2.
    • CDN Cloudflare, Zone ID (trang Overview của tên miền, mục API), API token và tên miền CDN https://images.example.com.

C. Google Cloud Storage + Cloudflare

Google Cloud Storage được kết nối qua XML API tương thích S3 của nó với khóa HMAC.

  1. Tạo bucket, ví dụ my-images.
  2. Tạo một service account và cấp cho nó vai trò Storage Object User (roles/storage.objectUser) chỉ trên bucket này.
  3. Tạo khóa HMAC cho service account: Cloud Storage → Settings → Interoperability → Create a key for a service account. Sao chép access ID và secret.
  4. Cho phép CDN của bạn đọc các tệp đã tối ưu. Cloudflare lấy tệp từ Cloud Storage qua HTTPS, vì vậy các đối tượng trong optimized/ phải đọc được công khai. Với uniform bucket-level access, việc cấp vai trò Storage Object Viewer cho allUsers sẽ khiến toàn bộ bucket đọc được, kể cả originals/. Nếu ảnh gốc phải giữ riêng tư, hãy đặt một lớp xác thực phía trước (ví dụ một Cloudflare Worker ký các yêu cầu gửi đến bucket).
  5. Trỏ một bản ghi DNS Cloudflare có proxy đến Cloud Storage, ví dụ images.example.com. Hoặc đặt tên bucket theo hostname và dùng CNAME có proxy đến c.storage.googleapis.com, hoặc dùng một Cloudflare Origin Rule gửi yêu cầu đến storage.googleapis.com với tên bucket ở đầu đường dẫn.
  6. Tạo một API token Cloudflare cho zone với quyền Zone → Cache Purge → Purge (Zone → Zone → Read là tùy chọn).
  7. Trong bảng điều khiển: nhà cung cấp lưu trữ Google Cloud Storage, bucket, endpoint https://storage.googleapis.com, khu vực auto, access ID và secret HMAC; CDN Cloudflare, Zone ID, API token và tên miền CDN https://images.example.com.

D. MinIO hoặc bất kỳ bộ nhớ tương thích S3 nào + Cloudflare

Phần này áp dụng cho MinIO và các dịch vụ tương thích S3 như Hetzner, Wasabi, Vultr, SumoPod, Alibaba Cloud OSS, Tencent Cloud COS và DigitalOcean Spaces.

Nhà cung cấpChọn trong bảng điều khiểnEndpointGhi chú
MinIOMinIOMáy chủ của bạn, ví dụ https://minio.example.comBật yêu cầu path-style. Máy chủ phải truy cập được từ internet qua HTTPS.
Hetzner Object StorageTương thích S3 tùy chỉnhhttps://<location>.your-objectstorage.com
WasabiTương thích S3 tùy chỉnhhttps://s3.<region>.wasabisys.com
Vultr Object StorageTương thích S3 tùy chỉnhhttps://<region>.vultrobjects.com
SumoPod StorageSumoPod StorageLấy từ bảng điều khiển lưu trữ SumoPodPath-style bật mặc định.
Alibaba Cloud OSSAlibaba Cloud OSShttps://oss-<region>.aliyuncs.comChỉ kiểu virtual-hosted.
Tencent Cloud COSTencent Cloud COShttps://cos.<region>.myqcloud.comTên bucket chứa APPID của bạn, ví dụ my-images-1250000000.
DigitalOcean SpacesDigitalOcean Spaceshttps://<region>.digitaloceanspaces.com
  1. Tạo bucket và một khóa chỉ giới hạn cho bucket đó với quyền ghi, đọc và xóa đối tượng (xem Quyền tối thiểu bên dưới).
  2. Cho phép CDN của bạn đọc optimized/, ví dụ bằng một chính sách bucket cho phép s3:GetObject ẩn danh chỉ trên optimized/*. Trên MinIO:
JSON
{  "Version": "2012-10-17",  "Statement": [    {      "Effect": "Allow",      "Principal": {        "AWS": [          "*"        ]      },      "Action": [        "s3:GetObject"      ],      "Resource": [        "arn:aws:s3:::my-images/optimized/*"      ]    }  ]}
  1. Đặt Cloudflare phía trước bucket: một bản ghi DNS có proxy cho images.example.com trỏ đến host công khai của bucket. Nếu nhà cung cấp cần hostname riêng của họ trong yêu cầu, hãy thêm một Cloudflare Origin Rule ghi lại header Host (và, với host path-style, thêm tên bucket vào đường dẫn).
  2. Tạo một API token Cloudflare cho zone với quyền Zone → Cache Purge → Purge (Zone → Zone → Read là tùy chọn).
  3. Trong bảng điều khiển: chọn nhà cung cấp từ bảng, nhập bucket, endpoint, khu vực (auto nếu nhà cung cấp không có khu vực) và khóa; bật yêu cầu path-style ở nơi bảng yêu cầu; sau đó CDN Cloudflare, Zone ID, API token và tên miền CDN.

Quyền tối thiểu

Chỉ cấp cho smallPict các khóa làm được đúng những gì nó cần, trên một bucket.

Nhà cung cấpQuyền
Amazon S3s3:PutObject, s3:GetObject, s3:DeleteObject trên arn:aws:s3:::<bucket>/*
Amazon CloudFrontcloudfront:CreateInvalidation trên distribution; tùy chọn cloudfront:GetDistribution để có thể phát hiện tên miền
Cloudflare R2API token R2 với Object Read & Write, giới hạn trong bucket
Cloudflare (CDN)API token cho zone với Zone → Cache Purge → Purge; tùy chọn Zone → Zone → Read
Google Cloud StorageKhóa HMAC cho một service account có roles/storage.objectUser trên bucket
Alibaba Cloud OSSNgười dùng RAM có oss:PutObject, oss:GetObject, oss:DeleteObject trên bucket
Tencent Cloud COSNgười dùng con CAM có cos:PutObject, cos:GetObject, cos:DeleteObject trên bucket (tên bucket chứa APPID)
DigitalOcean SpacesSpaces access key giới hạn trong bucket với quyền đọc, ghi và xóa
MinIO / tương thích S3 tùy chỉnhGhi, đọc và xóa trên <bucket>/*; endpoint phải là HTTPS công khai

Bước kiểm tra kết nối

Mỗi lần bạn lưu (và khi bạn chọn Kiểm tra lại), smallPict kiểm tra toàn bộ kết nối trước khi dùng:

  1. Lưu trữ: ghi một tệp thử nhỏ vào .smallpict-probe/ trong bucket của bạn, đọc lại và xóa nó.
  2. Cloudflare: gửi một yêu cầu xóa bộ nhớ đệm thử cho một URL đến zone của bạn.
  3. CloudFront: tạo một invalidation thử cho đường dẫn /.smallpict-probe/.... Nó được tính vào số đường dẫn invalidation CloudFront trong tháng của bạn.

Nếu bất kỳ bước nào thất bại, không có gì được chuyển đổi. Bảng điều khiển hiển thị lý do bên cạnh trường liên quan, ví dụ tên bucket hoặc API token. Bước kiểm tra kết nối bị giới hạn ở 5 lần thử mỗi phút.


Quyền truy cập bucket cho CDN của bạn

  • optimized/ phải đọc được bởi CDN của bạn: hoặc cho phép đọc công khai trên tiền tố đó, hoặc dùng quyền truy cập origin của CDN vào bucket riêng tư (CloudFront origin access control, hoặc tên miền tùy chỉnh R2).
  • originals/ có thể giữ riêng tư. CDN của bạn không bao giờ cần đến nó.
  • CORS chỉ cần khi trình duyệt tải ảnh khác nguồn (cross-origin) từ JavaScript (ví dụ fetch() hoặc canvas). Thẻ <img> thông thường không cần. Nếu bạn cần, hãy cho phép GET và HEAD từ origin của trang web.

Bố cục đối tượng và URL

Nội dungKhóa trong bucket của bạnURL
Ảnh gốcoriginals/<job_id>/<file>Không phân phối
Tệp đã tối ưuoptimized/<job_id>.<ext><cdn_domain>/optimized/<job_id>.<ext>

Tên miền CDN có thể kèm tiền tố đường dẫn, ví dụ https://example.com/images; khi đó URL sẽ là https://example.com/images/optimized/<job_id>.<ext>.


Header bộ nhớ đệm

Tệp đã tối ưu được ghi với Cache-Control: public, max-age=31536000, immutable. Mỗi job có một khóa duy nhất, nên kết quả mới luôn có URL mới và hiếm khi cần xóa bộ nhớ đệm. Đừng để quy tắc bộ nhớ đệm của CDN ghi đè header này bằng thời gian ngắn hơn.


Xóa bộ nhớ đệm

  • Các yêu cầu xóa bộ nhớ đệm qua API (POST /v1/purge) được gửi theo lô đến CDN của bạn.
  • Trên Cloudflare, tệp được xóa theo URL. “Xóa tất cả” chỉ xóa host phân phối và tiền tố đường dẫn của bạn, không phải toàn bộ zone.
  • Trên CloudFront, tệp được xóa bằng invalidation. “Xóa tất cả” tạo một invalidation /*. Các đường dẫn invalidation vượt quá hạn mức miễn phí hàng tháng của CloudFront sẽ được AWS tính phí vào tài khoản của bạn.

Chuyển chế độ

Chuyển chế độ không di chuyển các tệp hiện có. Các tệp đã phân phối vẫn giữ URL hiện tại; chỉ các job mới dùng chế độ mới.

  • Được quản lý → BYO: các job mới được ghi vào bucket của bạn và được CDN của bạn phân phối. Các tệp đã có trên cdn.smallpict.app vẫn ở đó.
  • BYO → được quản lý: các job mới lại dùng lưu trữ và CDN được quản lý. Cài đặt và khóa BYO của bạn vẫn được lưu nhưng không dùng, nên bạn có thể chuyển lại mà không cần nhập lại, cho đến khi bạn chọn Ngắt kết nối.
  • Ngắt kết nối: xóa các khóa và cài đặt BYO đã lưu và đưa bạn về chế độ được quản lý. Các tệp trong bucket của bạn không bị ảnh hưởng.

Khi có sự cố

  • Nếu smallPict không thể ghi vào bucket của bạn, nó sẽ thử lại, sau đó đánh dấu job thất bại với lý do bạn có thể đọc trong phản hồi API.
  • Bảng điều khiển hiển thị lỗi gần nhất và thời điểm xảy ra, kèm nút Kiểm tra lại.
  • Bạn nhận một email cho mỗi sự cố, không phải một email cho mỗi job thất bại.
  • smallPict không bao giờ chuyển sang lưu trữ được quản lý thay thế. Tệp của bạn không bao giờ được lưu ở nơi bạn không chọn.

Bảo mật

  • Khóa được giữ trong kho bí mật được mã hóa. Chúng không bao giờ được hiển thị lại, không bao giờ được API trả về và không bao giờ được ghi vào log.
  • Để thay khóa, hãy nhập khóa mới và lưu; bước kiểm tra kết nối sẽ chạy với khóa mới. Để trống trường khóa để giữ khóa đã lưu.
  • Endpoint lưu trữ và CDN phải dùng HTTPS. Các endpoint phân giải tới địa chỉ riêng tư, loopback, link-local hoặc các địa chỉ nội bộ khác sẽ bị từ chối.
  • Hãy dùng các khóa riêng, phạm vi hẹp cho smallPict, và thu hồi chúng trong bảng điều khiển của nhà cung cấp nếu bạn ngừng dùng BYO.