ما هو Garage وما ليس عليه
Garage هو مخزن كائنات متوافق مع S3 مصمم للنشر الذاتي الصغير الحجم، مع إمكانية التوزيع عبر مواقع متعددة. يعمل داخل حاوية، ولا يحتاج إلى قاعدة بيانات مجاورة، ويستهلك على نظام أحادي العقدة بضعة ميغابايتات من الذاكرة في وضع الاستعداد.
ما ليس عليه، ينبغي قوله صراحةً: Garage لا يملك واجهة ويب. تمر الإدارة عبر أداة سطر الأوامر garage وواجهة برمجية للإدارة عبر HTTP. هذا ليس غياباً لميزة، بل خيار مقصود للإبقاء على الخدمة صغيرة وسطح هجومها ضيقاً. تقدم مشاريع مجتمعية واجهة في المتصفح فوق واجهة الإدارة لمن يحتاجها.
إن كنت تبحث عن هذه النقطة تحديداً لأن MinIO سحبت واجهتها من الإصدار المجتمعي عام 2025 — ثم توقفت عن نشر صور Docker المجتمعية — فالجواب الصريح هو أن Garage لن يعيد إليك تلك الواجهة. لكنه يمنحك مشروعاً رخصته AGPLv3 لا تحجب أي ميزة خلف إصدار مدفوع.
ما يتميز به Garage على خادم VPS
- واجهة S3 قياسية: متوافقة مع
awsCLI وrcloneوmcوresticوحزم SDK لـPython/Go/Rust وجميع عملاء S3 تقريباً. - بصمة ذاكرة ضئيلة: بضعة ميغابايتات في وضع الاستعداد — تتعايش دون احتكاك مع خادم ويب أو قاعدة بيانات أو بروكسي عكسي على نفس الـVPS.
- لا اعتمادية خارجية: لا PostgreSQL ولا Redis ولا etcd. محرك البيانات الوصفية مدمج (LMDB أو SQLite).
- نسخ احتياطي اختياري: في وضع العقدة الواحدة يكفي قرص واحد؛ في الوضع متعدد العقد يُكرر Garage الكائنات بين الأجهزة وعبر المواقع.
- رخصة AGPLv3 بلا قيود: لا ميزة محجوبة خلف إصدار مدفوع ولا حد على الحجم أو عدد الدلاء.
- نطاقات فرعية افتراضية: يدير Garage توجيه
<bucket>.s3.your-domain.com، وهو ما تتطلبه بعض عملاء S3 وحزم SDK.
المتطلبات الأولية: تحديد حجم الـVPS لـstorage bucket
Garage بحد ذاته خفيف — ما يحدد حجم القرص هو حجم البيانات التي تخزنها، لا الخدمة. يكفي VPS من الفئة الابتدائية لتشغيل العملية. لأعباء العمل الشائعة (نسخ احتياطية، أصول موقع):
- المعالج: يكفي vCPU واحد؛ Garage خفيف على الحوسبة.
- الذاكرة: 512 ميغابايت متاحة تكفي؛ يحتفظ محرك LMDB بفهرسه في ملفات مُعيَّنة على الذاكرة.
- القرص: SSD NVMe بحجم بياناتك مضافاً إليه 20 % هامشاً للبيانات الوصفية. العقدة الواحدة تحتفظ بـنسخة واحدة فقط من كائناتك — خطط وفق ذلك.
- نظام التشغيل: Debian 12 أو Ubuntu 22.04 LTS مع Docker وملحق Compose.
لتثبيت Docker بأمر واحد:
curl -fsSL https://get.docker.com | shالإعداد الأدنى لـstorage bucket
يقرأ Garage ملف garage.toml. للعقدة المنفردة، تكفي بضعة أسطر — لاحظ replication_factor = 1 الذي يُفصح صراحةً بغياب النسخ الاحتياطي:
metadata_dir = "/var/lib/garage/meta"
data_dir = "/var/lib/garage/data"
db_engine = "sqlite"
replication_factor = 1
rpc_bind_addr = "[::]:3901"
rpc_public_addr = "127.0.0.1:3901"
rpc_secret = "<64 حرفاً سداسي عشري>"
[s3_api]
s3_region = "garage"
api_bind_addr = "[::]:3900"
root_domain = ".s3.your-domain.com"
[admin]
api_bind_addr = "[::]:3903"
admin_token = "<رمز الإدارة>"يجب أن يتكون rpc_secret من 32 بايت أي 64 حرفاً سداسي عشري: openssl rand -hex 32.
نشر Garage وإنشاء أول bucket تخزين S3
إنشاء هيكل المجلدات
أنشئ مجلد عمل وملف الإعداد:
mkdir -p /opt/garage/config openssl rand -hex 32 # → الصقه في rpc_secret openssl rand -base64 32 | tr -d '=' | head -c 40 # → admin_tokenaكتب
garage.tomlفي/opt/garage/config/مع استبدال الرمزين المولَّدَين.كتابة ملف Compose وتشغيله
منذ الإصدار 2.3، يستطيع Garage تهيئة مجموعة عقدة واحدة وإنشاء أول دلو تلقائياً من متغيرات البيئة. هذا يتجنب تسلسل الأوامر اليدوية
layout assign/layout apply/bucket create/key create:services: garage: image: dxflrs/garage:v2.3.0 restart: unless-stopped command: ["/garage", "-c", "/etc/garage/garage.toml", "server", "--single-node", "--default-bucket"] environment: GARAGE_DEFAULT_BUCKET: my-bucket GARAGE_DEFAULT_ACCESS_KEY: GK<30 hex> GARAGE_DEFAULT_SECRET_KEY: <64 hex> ports: - "127.0.0.1:3900:3900" - "127.0.0.1:3903:3903" volumes: - ./config:/etc/garage - garage-meta:/var/lib/garage/meta - garage-data:/var/lib/garage/data volumes: garage-meta: garage-data:الصورة distroless: لا توجد قشرة أوامر ونقطة الدخول فارغة. يجب أن تُسمّي الأمرُ الملفَّ الثنائيَّ بمساره المطلق (
/garage) وتمرّر ملف الإعداد (-c).مفتاح الوصول S3 يجب أن يكون
GKيليه بالضبط 30 حرفاً سداسي عشري.docker compose up -dالتحقق من استجابة الواجهة البرمجية
يجب أن يُعيد استدعاء مجهول على واجهة S3 البرمجية 403 — العلامة الصحيحة على أن الخدمة تعمل وترفض الطلب غير الموقَّع:
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3900/ # 403 → الواجهة البرمجية تستجيبواجهة الإدارة تُعيد 200 بالرمز:
curl -H "Authorization: Bearer $ADMIN_TOKEN" http://127.0.0.1:3903/v2/ListBucketsكشف الواجهة البرمجية خلف nginx وشهادة TLS
لا تنشر المنفذ 3900 مباشرةً على الواجهة العامة. اربطه بالحلقة المحلية ودع nginx يتولى البروكسي والشهادة. كتلة nginx أدنى لـ
s3.your-domain.com:server { listen 443 ssl; server_name s3.your-domain.com *.s3.your-domain.com; ssl_certificate /etc/letsencrypt/live/s3.your-domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/s3.your-domain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3900; proxy_set_header Host $host; } }الاختبار بعميل S3
مع تعيين متغيرات البيئة، تعمل أداة
awsCLI دون تعديل:export AWS_ACCESS_KEY_ID=GK... export AWS_SECRET_ACCESS_KEY=... export AWS_DEFAULT_REGION=garage aws --endpoint-url https://s3.your-domain.com s3 ls aws --endpoint-url https://s3.your-domain.com s3 cp myfile.txt s3://my-bucket/لـrestic، عيّن
RESTIC_REPOSITORY=s3:https://s3.your-domain.com/my-bucketوشغّلrestic init.
حالات الاستخدام الشائعة لـstorage bucket ذاتي الاستضافة
يغطي storage bucket على Garage عدة احتياجات شائعة دون الاعتماد على سحابة خارجية.
ما يُنشر خلف Garage
- نسخ احتياطية restic أو Borg: عيّن
RESTIC_REPOSITORY=s3:https://s3.your-domain.com/backups. التوافق مع S3 في restic أصيل ولا يتطلب إضافات. - أصل موقع ثابت: خزّن أصول الواجهة الأمامية المُجمَّعة وقدّمها عبر nginx أو Cloudflare في وضع البروكسي.
- رفع ملفات التطبيقات: تكتب تطبيقات Laravel أو Django أو Rails إلى Garage عبر حزمة SDK الخاصة بها — لا يتغير سوى نقطة النهاية.
- إنتاج CI/CD: ترفع GitHub Actions أو GitLab CI نتائج البناء إلى Garage بـ
aws s3 cpتماماً كما مع S3 الخاص بـAWS. - أرشفة السجلات والمقاييس: تستطيع Loki وVector وFluentd الكتابة إلى مخزن كائنات متوافق مع S3 للأرشفة طويلة الأمد.
- مشاركة الملفات بين الخدمات: تصل حاويتان على نفس الـVPS أو على نظامَين مختلفَين إلى نفس الدلو عبر واجهة S3 البرمجية.
Garage مقابل بدائل S3 ذاتية الاستضافة
مرّر الجدول أفقيًا
| المعيار | Garage | MinIO (مجتمعي) |
|---|---|---|
| الرخصة | AGPLv3 — بدون قيود استخدام | AGPLv3، لكن الواجهة سُحبت من الإصدار المجاني عام 2025 |
| صور Docker | تُنشر بانتظام على Docker Hub (`dxflrs/garage`) | الصور المجتمعية متوقفة على Docker Hub منذ 2025 |
| واجهة الويب | غائبة (CLI + واجهة إدارة HTTP) | الواجهة محذوفة من الإصدار المجتمعي |
| متعدد المواقع | مُصمَّم أصلاً للمناطق الجغرافية | ممكن لكنه يستلزم مجموعة مخصصة |
| بصمة الذاكرة | بضعة ميغابايتات في الاستعداد | عشرات الميغابايتات كحد أدنى |
| توافق S3 | جيد على السطح الشائع | واسع جداً بما فيه امتدادات AWS الخاصة |
الدلاء ومفاتيح الوصول والصلاحيات
يدير Garage الوصول على مستوى المفتاح: يمكن تفويض كل مفتاح S3 على دلو واحد أو أكثر، قراءةً فقط أو قراءةً وكتابةً. لعمليات النسخ الاحتياطي الآلي، أنشئ مفتاحاً مخصصاً يصل إلى دلو النسخ الاحتياطي فقط لا إلى الخادم كله.
الأمر garage key create <name> ينشئ المفتاح، وgarage bucket allow --key <id> --read --write <bucket> يمنحه الصلاحيات. يمكنك أيضاً استخدام واجهة الإدارة HTTP لأتمتة ذلك في سكريبت.
نقاط يجب استيعابها
العقدة الواحدة ليست تكراراً. يستطيع Garage التكرار عبر أجهزة متعددة وعبر مواقع مختلفة — وهذا هدفه الأصلي. لكن طالما لديك عقدة واحدة، تتواجد كائناتك في نسخة واحدة على قرص واحد. احتفظ بانضباط النسخ الاحتياطي الذي تُطبّقه أصلاً.
اكشف الواجهة البرمجية خلف نطاق وشهادة TLS، لا على عنوان IP مجرد. عدة عملاء S3 يرفضون العمل بدون TLS، والتوجيه عبر النطاق الفرعي للدلو يستلزم شهادة wildcard.
توافق S3 يغطي السطح الشائع، لا كل امتداد خاص بـAWS. العملاء والمكتبات وأدوات النسخ الاحتياطي القياسية تعمل دون تعديل؛ إن كنت تعتمد على استدعاء غير شائع، تحقق من توثيق المشروع قبل الترحيل.
راقب مساحة القرص. دلو نسخ احتياطية يتنامى دون سياسة استبقاء يملأ القرص صامتاً. عيّن قاعدة دورة حياة أو مهمة cron لحذف اللقطات القديمة عبر garage bucket lifecycle.