استخدم التخزين + CDN الخاص بك
اربط تخزين الكائنات وشبكة CDN الخاصين بك في خطتي API Velocity وMomentum: الإعداد لكل مزوّد، والحد الأدنى من الصلاحيات، وفحص الاتصال، وما يحدث عند تبديل الوضع.
متاح في: خطتي API Velocity وMomentum. غير متاح في Ignite (لا تتضمن CDN)، ولا في بيئة الاختبار للمطورين (ملفات بيئة الاختبار مؤقتة)، ولا في خطط WordPress (تستخدم شبكة smallPict CDN المُدارة).
باختصار: في وضع BYO يكتب smallPict صورك الأصلية والمحسّنة في حاويتك أنت، وتقدّمها شبكة CDN الخاصة بك أنت. يُربط التخزين وCDN معًا دائمًا: لا يمكنك إحضار أحدهما دون الآخر.
ما هو BYO
تتضمن خطتا Velocity وMomentum وضعين للتوصيل. تختار أحدهما من لوحة التحكم ← شبكة CDN والتخزين.
- مُدار (الافتراضي): يحفظ smallPict صورك الأصلية في تخزينه المشفّر (وتُنقل إلى أرشيف طويل الأمد بعد 90 يومًا)، ويقدّم الصور المحسّنة من
cdn.smallpict.app. لا حاجة لأي إعداد. - استخدم التخزين + CDN الخاص بك (BYO): تربط حاوية متوافقة مع S3 في حسابك وشبكة CDN في حسابك. تكتب كل مهمة جديدة الملف الأصلي والملف المحسّن في حاويتك، وتُرجع API عناوين URL على نطاق CDN الخاص بك.
توجد قاعدة الربط المزدوج لأن smallPict يجب أن يتمكن من تنفيذ نصفي التوصيل معًا: كتابة الملفات، وإزالة النسخ القديمة من ذاكرة التخزين المؤقت. فالحاوية بلا CDN تترك طلبات مسح ذاكرة التخزين المؤقت بلا وجهة، وشبكة CDN بلا حاوية لن يكون لديها ما تقدّمه.
المُدار مقابل BYO
| مُدار (افتراضي) | استخدم التخزين + CDN الخاص بك | |
|---|---|---|
| الصور الأصلية | تخزين smallPict المشفّر | originals/<job_id>/<file> في حاويتك |
| الملفات المحسّنة | تُقدَّم من cdn.smallpict.app | optimized/<job_id>.<ext> في حاويتك، وتُقدَّم من نطاق CDN الخاص بك |
| حصة التخزين | Velocity 50 غيغابايت، Momentum 100 غيغابايت | لا تُحتسب. تدفع لمزوّد التخزين الخاص بك. |
| سعة نقل CDN | Velocity 30 غيغابايت/شهريًا، Momentum 200 غيغابايت/شهريًا | لا تُحتسب. تدفع لمزوّد CDN الخاص بك. |
| التحويلات | تُحتسب ضمن خطتك | تُحتسب ضمن خطتك |
| نسخة يحتفظ بها smallPict | نعم، ما دام حسابك نشطًا | لا شيء. فقط ملف الرفع المؤقت للمعالجة، ويُحذف خلال 24 ساعة. |
| مسح ذاكرة التخزين المؤقت | تلقائي | تلقائي، عبر API الخاصة بشبكة CDN لديك |
| أداء CDN ونطاقها وتكاليفها | smallPict | أنت. لا يتحمل smallPict مسؤولية أداء شبكة CDN الخاصة بك أو نطاقاتها أو فواتيرها. |
المزوّدون المدعومون
التخزين (متاح الآن): Amazon S3 وCloudflare R2 وGoogle Cloud Storage (توافق S3) وAlibaba Cloud OSS وTencent Cloud COS وDigitalOcean Spaces وSumoPod Storage وMinIO، وأي خدمة أخرى متوافقة مع S3 عبر نقطة نهاية مخصّصة (مثل Hetzner أو Vultr أو Wasabi).
CDN (متاح الآن): Cloudflare وAmazon CloudFront.
مخطط له: Azure Blob Storage وشبكات CDN أخرى. يمكنك طلب وصول مبكر من صفحة مزوّدو الخدمات السحابية.
قبل أن تبدأ
- أنت مشترك في خطة API Velocity أو Momentum ومسجّل الدخول بصفتك مسؤولًا عن الحساب.
- لديك حاوية، وشبكة CDN تقدّم الملفات من تلك الحاوية عبر HTTPS.
- يمكن الوصول إلى نقطة نهاية التخزين من الإنترنت عبر HTTPS. تُرفض نقاط النهاية الخاصة والداخلية وتلك التي تعمل عبر HTTP العادي.
- أنشأت مفاتيح محدودة الصلاحيات لـ smallPict (راجع الحد الأدنى من الصلاحيات أدناه). لا تستخدم مفاتيح الجذر أو مفاتيح المسؤول الخاصة بحسابك.
بعد ذلك افتح لوحة التحكم ← شبكة CDN والتخزين، واختر استخدم التخزين + CDN الخاص بك، واملأ الجزأين، ثم اختر حفظ التخزين + CDN. يجري smallPict فحص الاتصال (الموضح أدناه)، ولا ينقلك إلى وضع BYO إلا إذا نجح.
أدلة الإعداد
أ. Amazon S3 + Amazon CloudFront
- أنشئ الحاوية في المنطقة التي تريدها، مثل
my-imagesفيap-southeast-1. أبقِ خيار Block Public Access مفعّلًا. - أنشئ توزيع CloudFront تكون الحاوية مصدره. استخدم Origin access control (OAC) حتى يتمكن CloudFront من قراءة الحاوية مع بقائها خاصة، وطبّق سياسة الحاوية التي يقترحها عليك CloudFront.
- اختياري: نطاقك الخاص. أضف إلى التوزيع اسم نطاق بديلًا (مثل
images.example.com) وشهادة، ووجّه سجل DNS إلى التوزيع. - أنشئ مستخدم IAM (أو دورًا) للتخزين بهذه السياسة:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::my-images/*" } ]}- أنشئ مستخدم IAM لـ CloudFront (يمكن أن يكون المستخدم نفسه) بهذه السياسة. الصلاحية
cloudfront:GetDistributionاختيارية؛ وبوجودها يستطيع smallPict اكتشاف نطاق التوزيع عندما تترك نطاق CDN فارغًا.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "cloudfront:CreateInvalidation", "cloudfront:GetDistribution" ], "Resource": "arn:aws:cloudfront::123456789012:distribution/E2QWRUHAPOMQZL" } ]}- في لوحة التحكم:
- مزوّد التخزين Amazon S3، والحاوية
my-images، والمنطقةap-southeast-1، ونقطة النهاية فارغة (تُستخدم نقطة النهاية القياسية للمنطقة)، وAccess key ID والمفتاح السري الخاصان بالتخزين. - شبكة CDN Amazon CloudFront، وDistribution ID (مثل
E2QWRUHAPOMQZL)، وAccess key ID والمفتاح السري الخاصان بـ CloudFront، ونطاق CDN اختياريًا (https://images.example.com). اترك النطاق فارغًا لاستخدام نطاق*.cloudfront.netالخاص بالتوزيع نفسه.
- مزوّد التخزين Amazon S3، والحاوية
ب. Cloudflare R2 + Cloudflare
- أنشئ حاوية R2، مثل
my-images. - اربط نطاقًا مخصّصًا بالحاوية (R2 ← حاويتك ← Settings ← Custom Domains)، مثل
images.example.com، على منطقة (Zone) في حساب Cloudflare نفسه. تمر الطلبات إلى هذا النطاق عبر ذاكرة التخزين المؤقت لـ Cloudflare. لا تستخدم عنوان التطويرr2.devفي بيئة الإنتاج. - أنشئ رمز API لـ R2 (R2 ← Manage API tokens) بصلاحية Object Read & Write، مقصورًا على هذه الحاوية فقط. انسخ Access Key ID وSecret Access Key اللذين يظهران لك.
- أنشئ رمز API لـ Cloudflare (My Profile ← API Tokens) للمنطقة بصلاحية Zone → Cache Purge → Purge. صلاحية Zone → Zone → Read اختيارية.
- في لوحة التحكم:
- مزوّد التخزين Cloudflare R2، والحاوية
my-images، ونقطة النهايةhttps://<account_id>.r2.cloudflarestorage.com(تظهر في تفاصيل S3 API لحاويتك)، والمنطقةauto، وAccess Key ID وSecret Access Key الخاصان بـ R2. - شبكة CDN Cloudflare، وZone ID (صفحة Overview للنطاق، قسم API)، ورمز API، ونطاق CDN
https://images.example.com.
- مزوّد التخزين Cloudflare R2، والحاوية
ج. Google Cloud Storage + Cloudflare
يُربط Google Cloud Storage عبر واجهة XML API المتوافقة مع S3 باستخدام مفاتيح HMAC.
- أنشئ الحاوية، مثل
my-images. - أنشئ حساب خدمة وامنحه دور Storage Object User (
roles/storage.objectUser) على هذه الحاوية فقط. - أنشئ مفتاح HMAC لحساب الخدمة: Cloud Storage ← Settings ← Interoperability ← Create a key for a service account. انسخ معرّف الوصول والمفتاح السري.
- اجعل الملفات المحسّنة قابلة للقراءة من شبكة CDN. يجلب Cloudflare الملفات من Cloud Storage عبر HTTPS، لذا يجب أن تكون الكائنات ضمن
optimized/قابلة للقراءة للعامة. ومع الوصول الموحّد على مستوى الحاوية، فإن منحallUsersدور Storage Object Viewer يجعل الحاوية كلها قابلة للقراءة، بما فيهاoriginals/. إذا كان يجب أن تبقى صورك الأصلية خاصة، فضع أمامها طبقة مصادقة (مثل Cloudflare Worker يوقّع الطلبات المرسلة إلى الحاوية). - وجّه سجل DNS في Cloudflare مفعّلًا عليه الوكيل (proxied) إلى Cloud Storage، مثل
images.example.com. إما أن تسمّي الحاوية باسم المضيف وتستخدم سجل CNAME عبر الوكيل يشير إلىc.storage.googleapis.com، أو تستخدم Origin Rule في Cloudflare ترسل الطلبات إلىstorage.googleapis.comمع اسم الحاوية في بداية المسار. - أنشئ رمز API لـ Cloudflare للمنطقة بصلاحية Zone → Cache Purge → Purge (صلاحية Zone → Zone → Read اختيارية).
- في لوحة التحكم: مزوّد التخزين Google Cloud Storage، والحاوية، ونقطة النهاية
https://storage.googleapis.com، والمنطقةauto، ومعرّف الوصول والمفتاح السري لـ HMAC؛ وشبكة CDN Cloudflare، وZone ID، ورمز API، ونطاق CDNhttps://images.example.com.
د. MinIO أو أي تخزين متوافق مع S3 + Cloudflare
يغطي هذا القسم MinIO والخدمات المتوافقة مع S3 مثل Hetzner وWasabi وVultr وSumoPod وAlibaba Cloud OSS وTencent Cloud COS وDigitalOcean Spaces.
| المزوّد | ما تختاره في لوحة التحكم | نقطة النهاية | ملاحظات |
|---|---|---|---|
| MinIO | MinIO | خادمك، مثل https://minio.example.com | طلبات path-style مفعّلة. يجب أن يكون الخادم قابلًا للوصول من الإنترنت عبر HTTPS. |
| Hetzner Object Storage | مخصّص متوافق مع S3 | https://<location>.your-objectstorage.com | |
| Wasabi | مخصّص متوافق مع S3 | https://s3.<region>.wasabisys.com | |
| Vultr Object Storage | مخصّص متوافق مع S3 | https://<region>.vultrobjects.com | |
| SumoPod Storage | SumoPod Storage | من لوحة تحكم التخزين في SumoPod | path-style مفعّل افتراضيًا. |
| Alibaba Cloud OSS | Alibaba Cloud OSS | https://oss-<region>.aliyuncs.com | نمط virtual-hosted فقط. |
| Tencent Cloud COS | Tencent Cloud COS | https://cos.<region>.myqcloud.com | يتضمن اسم الحاوية معرّف APPID الخاص بك، مثل my-images-1250000000. |
| DigitalOcean Spaces | DigitalOcean Spaces | https://<region>.digitaloceanspaces.com |
- أنشئ الحاوية ومفتاحًا مقصورًا عليها بصلاحيات put وget وdelete على الكائنات (راجع الحد الأدنى من الصلاحيات أدناه).
- اجعل
optimized/قابلًا للقراءة من شبكة CDN، مثلًا بسياسة حاوية تسمح بـs3:GetObjectالمجهول علىoptimized/*فقط. على MinIO:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": [ "*" ] }, "Action": [ "s3:GetObject" ], "Resource": [ "arn:aws:s3:::my-images/optimized/*" ] } ]}- ضع Cloudflare أمام الحاوية: سجل DNS عبر الوكيل لـ
images.example.comيشير إلى المضيف العام للحاوية. إذا كان المزوّد يتطلب اسم المضيف الخاص به في الطلب، فأضف Origin Rule في Cloudflare تعيد كتابة ترويسة Host (وتضيف اسم الحاوية إلى المسار في مضيفات path-style). - أنشئ رمز API لـ Cloudflare للمنطقة بصلاحية Zone → Cache Purge → Purge (صلاحية Zone → Zone → Read اختيارية).
- في لوحة التحكم: اختر المزوّد من الجدول، وأدخل الحاوية ونقطة النهاية والمنطقة (
autoإذا لم يكن لدى المزوّد مناطق) والمفاتيح؛ وفعّل طلبات path-style حيث يشير الجدول إلى ذلك؛ ثم شبكة CDN Cloudflare، وZone ID، ورمز API، ونطاق CDN.
الحد الأدنى من الصلاحيات
امنح smallPict مفاتيح لا تستطيع إلا تنفيذ ما يحتاج إليه، على حاوية واحدة.
| المزوّد | الصلاحيات |
|---|---|
| Amazon S3 | s3:PutObject وs3:GetObject وs3:DeleteObject على arn:aws:s3:::<bucket>/* |
| Amazon CloudFront | cloudfront:CreateInvalidation على التوزيع؛ وcloudfront:GetDistribution اختيارية لاكتشاف النطاق |
| Cloudflare R2 | رمز API لـ R2 بصلاحية Object Read & Write، مقصور على الحاوية |
| Cloudflare (CDN) | رمز API للمنطقة بصلاحية Zone → Cache Purge → Purge؛ وZone → Zone → Read اختيارية |
| Google Cloud Storage | مفتاح HMAC لحساب خدمة لديه roles/storage.objectUser على الحاوية |
| Alibaba Cloud OSS | مستخدم RAM لديه oss:PutObject وoss:GetObject وoss:DeleteObject على الحاوية |
| Tencent Cloud COS | مستخدم فرعي في CAM لديه cos:PutObject وcos:GetObject وcos:DeleteObject على الحاوية (يتضمن اسم الحاوية معرّف APPID) |
| DigitalOcean Spaces | مفتاح وصول Spaces مقصور على الحاوية بصلاحيات القراءة والكتابة والحذف |
| MinIO / مخصّص متوافق مع S3 | put وget وdelete على <bucket>/*؛ ويجب أن تكون نقطة النهاية HTTPS عامة |
فحص الاتصال
في كل مرة تحفظ فيها (وعندما تختار إعادة الفحص)، يفحص smallPict الاتصال بالكامل قبل استخدامه:
- التخزين: يكتب ملف اختبار صغيرًا ضمن
.smallpict-probe/في حاويتك، ثم يقرؤه ويحذفه. - Cloudflare: يرسل طلب مسح اختباريًا واحدًا لعنوان URL واحد إلى منطقتك.
- CloudFront: ينشئ طلب إبطال (invalidation) اختباريًا واحدًا لمسار
/.smallpict-probe/.... ويُحتسب ضمن مسارات الإبطال في CloudFront لهذا الشهر.
إذا فشلت أي خطوة، فلن يُبدَّل شيء. تعرض لوحة التحكم السبب بجوار الحقل المعني، مثل اسم الحاوية أو رمز API. يقتصر فحص الاتصال على 5 محاولات في الدقيقة.
وصول شبكة CDN إلى الحاوية
optimized/يجب أن يكون قابلًا للقراءة من شبكة CDN: إما بقراءة عامة على هذه البادئة، أو بوصول CDN إلى المصدر في حاوية خاصة (Origin access control في CloudFront، أو نطاق مخصّص في R2).originals/يمكن أن يبقى خاصًا. لا تحتاج إليه شبكة CDN أبدًا.- CORS مطلوب فقط إذا كانت المتصفحات تجلب الصور من مصدر مختلف عبر JavaScript (مثل
fetch()أو canvas). وسوم<img>العادية لا تحتاج إليه. وإن احتجت إليه، فاسمح بـGETوHEADمن مصدر موقعك.
بنية الكائنات وعناوين URL
| العنصر | المفتاح في حاويتك | URL |
|---|---|---|
| الأصلي | originals/<job_id>/<file> | لا يُقدَّم |
| الملف المحسّن | optimized/<job_id>.<ext> | <cdn_domain>/optimized/<job_id>.<ext> |
يمكن أن يتضمن نطاق CDN بادئة مسار، مثل https://example.com/images؛ ويصبح عنوان URL حينئذٍ https://example.com/images/optimized/<job_id>.<ext>.
ترويسات ذاكرة التخزين المؤقت
تُكتب الملفات المحسّنة مع Cache-Control: public, max-age=31536000, immutable. تحصل كل مهمة على مفتاح فريد، لذا يكون للنتيجة الجديدة دائمًا عنوان URL جديد، ونادرًا ما يلزم المسح. احرص على ألا تستبدل قواعد التخزين المؤقت في شبكة CDN هذه الترويسة بمدة أقصر.
مسح ذاكرة التخزين المؤقت
- تُرسَل طلبات المسح التي تُجرى عبر API (
POST /v1/purge) إلى شبكة CDN الخاصة بك أنت، على دفعات. - على Cloudflare تُمسح الملفات حسب عنوان URL. ولا يمسح خيار «Purge all» إلا مضيف التوصيل وبادئة المسار الخاصين بك، لا منطقتك بالكامل.
- على CloudFront تُمسح الملفات بطلبات الإبطال. وينشئ خيار «Purge all» طلب إبطال
/*. وتفوتر AWS حسابك على مسارات الإبطال التي تتجاوز الحصة الشهرية المجانية في CloudFront.
تبديل الوضع
لا يؤدي تبديل الوضع إلى نقل الملفات الموجودة. تحتفظ الملفات التي سبق تقديمها بعناوين URL الحالية؛ ولا تستخدم الوضع الجديد إلا المهام الجديدة.
- المُدار ← BYO: تذهب المهام الجديدة إلى حاويتك وتقدّمها شبكة CDN الخاصة بك. تبقى الملفات الموجودة بالفعل على
cdn.smallpict.appفي مكانها. - BYO ← المُدار: تعود المهام الجديدة إلى استخدام التخزين وCDN المُدارين. تبقى إعدادات BYO ومفاتيحك محفوظة لكن غير مستخدمة، فتستطيع العودة دون إدخالها مجددًا، إلى أن تختار قطع الاتصال.
- قطع الاتصال: يحذف المفاتيح وإعدادات BYO المحفوظة ويعيدك إلى الوضع المُدار. لا تُمَس الملفات الموجودة في حاويتك.
عند حدوث خطأ
- إذا تعذّر على smallPict الكتابة في حاويتك، فإنه يعيد المحاولة، ثم يُفشل المهمة مع سبب يمكنك قراءته في استجابة API.
- تعرض لوحة التحكم آخر خطأ ووقت حدوثه، مع زر إعادة الفحص.
- تتلقى رسالة بريد إلكتروني واحدة لكل حادثة، لا رسالة لكل مهمة فاشلة.
- لا يلجأ smallPict أبدًا إلى التخزين المُدار كبديل. لا تُخزَّن ملفاتك أبدًا في مكان لم تختره.
الأمان
- تُحفظ المفاتيح في مخزن أسرار مشفّر. لا تُعرض مرة أخرى أبدًا، ولا تُرجعها API أبدًا، ولا تُكتب في السجلات أبدًا.
- لتدوير مفتاح، أدخل المفتاح الجديد واحفظ؛ يُجرى فحص الاتصال بالمفتاح الجديد. اترك حقل المفتاح فارغًا للاحتفاظ بالمفتاح المحفوظ.
- يجب أن تستخدم نقاط نهاية التخزين وCDN بروتوكول HTTPS. تُرفض نقاط النهاية التي تشير إلى عناوين خاصة أو عناوين loopback أو link-local أو أي عناوين داخلية أخرى.
- استخدم مفاتيح منفصلة ومحدودة الصلاحيات لـ smallPict، وألغِها من وحدة تحكم مزوّدك إذا توقفت عن استخدام BYO.