ما هو Garage، وما ليس هو
Garage مخزن كائنات متوافق مع S3 صُمّم للنشرات الصغيرة الذاتية الاستضافة، وربما الموزّعة على مواقع متعدّدة. يتّسع في حاوية واحدة، ولا يحتاج خادم قواعد بيانات إلى جانبه، وفي النشر أحادي العقدة يستهلك بضعة ميغابايتات من الذاكرة في وضع السكون.
وما ليس هو ينبغي قوله فوراً: لا يملك Garage لوحة تحكّم عبر المتصفح. تمرّ الإدارة عبر أداة سطر الأوامر garage وعبر واجهة إدارة HTTP. هذا خيار تصميمي لا ميزة منسية — تبقى الخدمة صغيرة وسطح تشغيلها ضيّقاً. وتوفّر مشاريع مجتمعية واجهة في المتصفح فوق واجهة الإدارة إن أردت.
وإن كنت تقرأ هذا لأن MinIO أزالت لوحتها من الإصدار المجتمعي سنة 2025، ثم توقّفت عن نشر صور Docker المجتمعية أصلاً، فالجواب الصادق أن Garage لن يعيد إليك تلك اللوحة. ما يمنحك إياه بدلاً منها مشروع لا تحجز رخصته AGPLv3 أي ميزة لإصدار مدفوع.
تهيئة الخادم
يعمل Garage في حاوية. على خادم Debian أو Ubuntu محدَّث، كل ما تحتاجه هو Docker وإضافة Compose:
curl -fsSL https://get.docker.com | shأما الحجم، فـ Garage نفسه مقتصد: ما يحدّد الحاجة هو حجم البيانات التي تخزّنها لا الخدمة ذاتها. يكفي خادم من الفئة الأولى لتشغيل الخدمة؛ احسب القرص بحسب ما تنوي إيداعه، وتذكّر أن العقدة الواحدة تحفظ نسخة واحدة من كائناتك.
الإعداد الأدنى
يقرأ 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.garage.localhost"
[admin]
api_bind_addr = "[::]:3903"
admin_token = "<رمز الإدارة>"يجب أن يكون rpc_secret بطول 32 بايت، أي 64 حرفاً ست عشرياً: openssl rand -hex 32.
التشغيل والحصول على بيانات اعتماد S3
منذ الإصدار 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...
GARAGE_DEFAULT_SECRET_KEY: ...
ports:
- "127.0.0.1:3900:3900"
volumes:
- ./config:/etc/garage
- garage-meta:/var/lib/garage/meta
- garage-data:/var/lib/garage/dataيستحق فخّان أن يُسمّيا، لأن كلّاً منهما يكلّف نصف ساعة. الصورة distroless: لا تملك صدفة، ونقطة دخولها فارغة — لذا يجب أن تسمّي الأوامرُ الملفَّ التنفيذي بمساره المطلق (/garage) وملفَّ الإعداد (-c)، وإلا دار الحاوية في حلقة على رسالة No such file or directory. كما يجب أن يأخذ مفتاح وصول S3 الشكل الذي يتوقّعه Garage: البادئة GK متبوعةً بـ 30 حرفاً ست عشرياً.
التحقّق من أنه يعمل
يجب أن يردّ الاستدعاء المجهول على واجهة S3 برمز 403 ورسالة Garage does not support anonymous access yet. وهذه علامة جيدة: الخدمة حيّة وترفض طلباً غير موقّع.
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من هنا يعمل أي عميل S3: aws --endpoint-url أو mc أو rclone، أو restic مباشرةً لنسخك الاحتياطية.
ما ينبغي تذكّره
العقدة الواحدة ليست تكراراً للبيانات. يستطيع Garage النسخ المتماثل بين أجهزة عدّة، وربما بين مواقع مختلفة — وهذا سبب وجوده أصلاً. لكن ما دمت تملك عقدة واحدة، فكائناتك موجودة بنسخة واحدة على قرص واحد. حافظ على انضباط النسخ الاحتياطي الذي كنت ستعتمده على أي حال.
اعرض الواجهة خلف نطاق وتشفير TLS لا على عنوان IP عارٍ: انشر المنفذ على الواجهة المحلية ودع nginx يتولّى الوساطة والشهادة. وهذا ما يفعله التنصيب بنقرة واحدة من المتجر.
تشمل توافقية S3 السطح الشائع لا كل امتداد خاص بـ AWS. تعمل العملاء وحزم التطوير وأدوات النسخ الاحتياطي القياسية دون تعديل؛ وإن كنت تعتمد على استدعاء غير معتاد، فتحقّق منه في وثائق المشروع قبل الترحيل.