تثبيت MinIO على VPS بنظام Ubuntu 24.04
شغّل MinIO على VPS واحد مع S3 تملكه: ثبّت الملف الثنائي وتحقّق منه، أنشئ وحدة systemd، استخدم mc والروابط الموقّتة، واجعل restic هدف النسخ الاحتياطي.
ما الذي يوفّره لك تخزين الكائنات المستضاف ذاتياً باستخدام MinIO
MinIO هو تخزين كائنات مستضاف ذاتياً ويتحدث عبر Amazon S3 API. وجّه restic أو أي S3 SDK إلى خادمك، وغيّر إعداد endpoint واحداً، ولن يتمكن العميل من تمييز الفرق. ينشئ هذا الدليل عقدة واحدة على Ubuntu 24.04: ملفاً ثنائياً تم التحقق منه، ومستخدم نظام مخصصاً، ووحدة systemd تُبقي بيانات اعتماد root خارج ملف الوحدة، وbucket ينسخ restic البيانات إليه.
إنّ S3 (خدمة التخزين البسيط) عبارة عن HTTP API وليست نظام ملفات. تضع كائناً في bucket تحت key باستخدام PUT، ثم تسترجعه باستخدام GET، ولا توجد كتابة جزئية ولا عملية إعادة تسمية. تناسب هذه الآلية أدوات النسخ الاحتياطي، لأن الكائن إما أن يصل كاملاً أو لا يصل.
تحتفظ عقدة واحدة بنسخة واحدة من بياناتك. هذه هي المقايضة التي تختارها. تحصل على endpoint لـS3 تتحكم فيه مقابل تكلفة VPS، كما تتحمل كل مهمة كان موفر السحابة ينفذها، بدءاً من استبدال قرص فاشل وصولاً إلى تصحيح برنامج الخادم. يوضح القسم القريب من النهاية بوضوح متى تكون هذه المقايضة مناسبة.
حالة إصدار المجتمع من MinIO في يوليو 2026
اقرأ هذا القسم قبل أن تعتمد عليه، لأن الوضع تغيّر مؤخراً. في مايو 2025 أزالت MinIO ميزات الإدارة من وحدة تحكم الويب في إصدار المجتمع. ما تبقّى في المتصفح هو متصفح للكائنات، لذلك تُدار buckets ومفاتيح الوصول باستخدام عميل سطر الأوامر mc بدلاً من ذلك.
لاحقاً في 2025 توقفت MinIO عن نشر ملفات ثنائية مُجمّعة مسبقاً لإصدار المجتمع. يذكر ملف README للمشروع الآن أن إصدار المجتمع يُوزَّع على شكل شفرة مصدر فقط. ما تزال عناوين التنزيل الأقدم تعمل. وحتى يوليو 2026، توفّر هذه العناوين build الخادم RELEASE.2025-09-07T16-13-09Z وbuild العميل RELEASE.2025-08-13T08-35-41Z، ولم يظهر أي build أحدث للمجتمع. لذلك فإن الملف الثنائي أدناه حقيقي ويعمل، لكنه ثابت. ولا تتضمنه إصلاحات الأمان المنشورة بعد سبتمبر 2025.
هذه الحقيقة تحدد بقية هذا الدليل. ولهذا يستمع MinIO هنا على 127.0.0.1 ولا يصل إلى الإنترنت إلا عبر proxy تتحكم فيه. إذا كنت تفضّل متابعة الإصلاحات، فابنِه من الشفرة المصدرية. يقدّم README الخاص بالمورّد أمراً واحداً هو go install github.com/minio/minio@latest، ويتطلب Go toolchain ويكتب الملف الثنائي إلى ~/go/bin/minio. ثبّت ذلك الملف الثنائي في /usr/local/bin/minio، وستبقى كل الخطوات الأخرى هنا دون تغيير.
ثبّت ملف MinIO التنفيذي وتحقق من التنزيل
نزّل الإصدار المثبّت وملف checksum المنشور له. يجعل الخيار -f الأمر curl يفشل عند حدوث خطأ HTTP بدلاً من حفظ صفحة الخطأ بالاسم الذي طلبته، وهو ما يؤدي إلى تثبيت صفحة 404 ثم التساؤل عن سبب عدم تنفيذها.
cd /tmp
REL=RELEASE.2025-09-07T16-13-09Z
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.$REL" -o minio
curl -fsSL "https://dl.min.io/server/minio/release/linux-amd64/archive/minio.$REL.sha256sum" -o minio.sha256sumقارن قيمتي hash، وقارن قيم hash فقط.
published=$(awk '{print $1}' minio.sha256sum)
downloaded=$(sha256sum minio | awk '{print $1}')
[ "$published" = "$downloaded" ] && echo "checksum ok"لا تستخدم sha256sum -c minio.sha256sum هنا. التسمية المكتوبة بعد قيمة hash داخل ذلك الملف هي minio.RELEASE.2025-09-07T16-13-09Z، بينما حفظنا التنزيل باسم minio، لذلك يبحث -c عن ملف غير موجود. يعرض No such file or directory ثم WARNING: 1 listed file could not be read، ما قد يبدو كأن التنزيل تالف، لكنه ليس كذلك. التسمية مجرد اسم. أما hash فهو الجزء الذي يوفّر الضمان.
يجب أن تكون واضحاً بشأن ما يثبته هذا التحقق. يأتي الملف التنفيذي وملف hash من المورّد نفسه عبر الاتصال نفسه، لذلك يثبت التطابق أن التنزيل اكتمل ولم يتلف أو يتغير أثناء النقل. لكنه لا يثبت أن المورّد موثوق. هذه مشكلة مختلفة، ولا يحلها أي أمر sha256sum.
sudo install -o root -g root -m 755 minio /usr/local/bin/minio
minio --versionيطبع minio --version القيمة minio version RELEASE.2025-09-07T16-13-09Z متبوعة بسطرَي build تقريباً. تعني Permission denied هنا أن الوضع غير صحيح، بينما تعني command not found أن /usr/local/bin غير موجود على PATH لديك.
إنشاء مستخدم نظام ودليل بيانات
يستقبل MinIO الرفوعات من الشبكة، لذلك يجب ألا يعمل بصفة root. امنحه حساباً بلا دليل home وبلا shell لتسجيل الدخول.
sudo groupadd -r minio-user
sudo useradd -M -r -g minio-user -s /usr/sbin/nologin minio-user
sudo mkdir -p /var/lib/minio/data
sudo chown -R minio-user:minio-user /var/lib/minio
sudo chmod 750 /var/lib/minioينشئ -r حساب نظام بمعرّف UID أقل من 1000، ما يبقيه خارج النطاق المستخدم لحسابات الأشخاص. يتخطى -M إنشاء دليل home، لأن الحساب الذي لا يسجّل الدخول مطلقاً لا يحتاج إلى تخزين أي شيء فيه. تحقّق من النتيجة باستخدام id minio-user، وباستخدام stat -c '%U %a' /var/lib/minio الذي يجب أن يطبع minio-user 750.
يجب أن يكون دليل البيانات قابلاً للكتابة من ذلك المستخدم، لا قابلاً للقراءة فقط. عند التشغيل لأول مرة، ينشئ MinIO دليلاً .minio.sys داخل وحدة التخزين للاحتفاظ بإعداده الخاص، لذلك يؤدي امتلاك root للدليل إلى خروج MinIO أثناء بدء التشغيل برسالة تنتهي بـ permission denied. تنطبق القاعدة نفسها على كل خدمة تشغّلها بهذه الطريقة، ويوضح مستخدمو خدمات أقل الصلاحيات على VPS هذه النقطة بالتفصيل.
ضع بيانات اعتماد root في ملف بيئة
تمنح بيانات اعتماد root صلاحية الوصول إلى كل bucket، لذلك لا مكان لها في ملف الوحدة، لأنه مقروء عالمياً. أنشئ الملف بالصلاحيات الصحيحة أولاً، ثم اكتب البيانات فيه ثانياً، حتى لا تبقى كلمة المرور في ملف مقروء ولو للحظة واحدة.
sudo install -o root -g root -m 600 /dev/null /etc/default/minio
printf 'MINIO_ROOT_USER=minio-root\nMINIO_ROOT_PASSWORD=%s\nMINIO_VOLUMES="/var/lib/minio/data"\nMINIO_OPTS="--address 127.0.0.1:9000 --console-address 127.0.0.1:9001"\n' "$(openssl rand -base64 24)" | sudo tee /etc/default/minio > /dev/null
sudo sed -n 's/^MINIO_ROOT_PASSWORD=//p' /etc/default/minioيؤدي tee إلى اقتطاع ملف موجود بدلاً من إنشائه من جديد، لذلك تبقى الصلاحيات عند 600 ويبقى المالك هو root. هذا مقصود. يقرأ systemd ملف EnvironmentFile بصفته root قبل خفض الامتيازات إلى User=، ولذلك لا يحتاج حساب الخدمة إلى قراءة بيانات اعتماده بنفسه. بعد تشغيل الخدمة، أثبت ذلك باستخدام sudo -u minio-user cat /etc/default/minio. يجب أن يطبع هذا الأمر Permission denied.
هناك سلوكان في MinIO ينبغي معرفتهما قبل تشغيله. عند عدم وجود MINIO_ROOT_USER وMINIO_ROOT_PASSWORD في بيئته، لا يرفض MinIO التشغيل. بل يبدأ باستخدام بيانات الاعتماد الافتراضية الموثقة minioadmin:minioadmin، وهي أول زوج تجربه أي أداة فحص، ويبدو سليماً تماماً أثناء ذلك. أما كلمة المرور التي تقل عن 8 محارف فيُرفض استخدامها بدلاً من ذلك: يخرج MinIO عند بدء التشغيل مع رسالة خطأ تفيد بأن بيانات الاعتماد غير صالحة، لأن مفتاح الوصول يحتاج إلى 3 محارف على الأقل، ويحتاج المفتاح السري إلى 8 محارف على الأقل.
يمثل MINIO_VOLUMES مسار البيانات، بينما يحتوي MINIO_OPTS على الخيارات. ويعني الربط بـ127.0.0.1 أن أي جهة خارج هذا VPS لا تستطيع الوصول إلى S3 API بعد، وهذا هو الإعداد الافتراضي المناسب. تفتحه لاحقاً بشكل مقصود، عبر proxy يحمل شهادة.
إنشاء وحدة systemd
أنشئ /etc/systemd/system/minio.service:
[Unit]
Description=MinIO object storage
Documentation=https://github.com/minio/minio
Wants=network-online.target
After=network-online.target
[Service]
User=minio-user
Group=minio-user
EnvironmentFile=/etc/default/minio
ExecStart=/usr/local/bin/minio server $MINIO_VOLUMES $MINIO_OPTS
Restart=always
RestartSec=5
LimitNOFILE=65536
NoNewPrivileges=true
[Install]
WantedBy=multi-user.targetلا توجد بادئة - في EnvironmentFile، وهذا قرار مقصود وليس خطأ مطبعياً. عند استخدام الشرطة، يتجاهل systemd الملف المفقود ويشغّل MinIO على أي حال. لذلك، يؤدي حذف الملف أو كتابة المسار بشكل خاطئ بصمت إلى تشغيل خادم باستخدام minioadmin:minioadmin. من دون الشرطة، يؤدي غياب الملف إلى فشل الوحدة قبل تشغيل MinIO، ويعرض journalctl -u minio القيمة Failed to load environment files: No such file or directory. ومن الأسهل بكثير ملاحظة وحدة ترفض التشغيل من ملاحظة خادم يقبل كلمة المرور الافتراضية بصمت.
استخدام $MINIO_VOLUMES و$MINIO_OPTS من دون علامات اقتباس مقصود، لأن systemd يقسّم المتغيرات غير المحاطة بعلامات اقتباس عند المسافات البيضاء إلى وسيطات منفصلة. هكذا تتحول الكلمات الأربع في MINIO_OPTS إلى أربع وسيطات لـ minio server. يرفع LimitNOFILE=65536 حد واصفات الملفات، لأن كل اتصال مفتوح وكل ملف بيانات مفتوح يستهلك واصفاً واحداً، وينفد الحد الافتراضي البالغ 1024 تحت الحمل.
sudo systemctl daemon-reload
sudo systemctl enable --now minio
systemctl is-active minio
curl -fsS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:9000/minio/health/liveينبغي أن يطبع is-active القيمة active، وينبغي أن تستجيب نقطة الصحة بالقيمة 200. يعرض journalctl -u minio -n 20 --no-pager عنوان API الذي يستمع إليه الخادم. إذا استمرت الوحدة في إعادة التشغيل، يتوقف systemd عن المحاولة ويسجّل Start request repeated too quickly. وهذا يعني أن MinIO يخرج عند كل محاولة. يظهر السبب في الأسطر السابقة لهذه الرسالة، لذا اقرأ السجل إلى الأعلى.
لمزيد من العزل، أضف ProtectSystem=full وProtectHome=true إلى قسم [Service]. يحتاج كلاهما إلى مساحات أسماء للـmount من نواة المضيف. في المحاكاة الافتراضية المعتمدة على الحاويات والتي تشارك نواة المضيف، مثل OpenVZ أو LXC، قد يفشل هذان الخياران، وعندها تعرض الوحدة status=226/NAMESPACE. احذف هذين السطرين وستبدأ الوحدة. الوحدة نفسها وحدة عادية، ويغطي خدمات systemd والمؤقتات على VPS بقية التوجيهات.
ثبّت mc وأثبت نجاح رحلة الذهاب والإياب
عميل MinIO هو mc. لا تثبّته باستخدام apt install mc. تلك الحزمة هي Midnight Commander، وهو مدير ملفات لا علاقة له بـMinIO.
cd /tmp
curl -fsSL https://dl.min.io/client/mc/release/linux-amd64/mc -o mc
curl -fsSL https://dl.min.io/client/mc/release/linux-amd64/mc.sha256sum -o mc.sha256sum
[ "$(awk '{print $1}' mc.sha256sum)" = "$(sha256sum mc | awk '{print $1}')" ] && echo "checksum ok"
sudo install -o root -g root -m 755 mc /usr/local/bin/mcسجّل الخادم كاسم مستعار، ثم انقل كائناً عبره.
MINIO_PASS=$(sudo sed -n 's/^MINIO_ROOT_PASSWORD=//p' /etc/default/minio)
mc alias set local http://127.0.0.1:9000 minio-root "$MINIO_PASS"
mc mb local/backups
echo "hello object storage" > /tmp/hello.txt
mc cp /tmp/hello.txt local/backups/hello.txt
mc ls local/backups
mc cat local/backups/hello.txtيجب أن يعرض mc ls قائمة hello.txt مع حجمه، ويجب أن يطبع mc cat القيمة hello object storage. تثبت رحلة الذهاب والإياب هذه فعلياً من عمل الخادم، لأنها تنفذ طلبات S3 الموقعة نفسها التي سينفذها أي عميل آخر. يطبع mc admin info local حالة الخادم إذا أردت تحققاً إضافياً.
أجرِ فحصاً آخر الآن، ما دام الخادم لا يحتوي على بيانات بعد.
mc alias set defaultcheck http://127.0.0.1:9000 minioadmin minioadminيجب أن يفشل هذا الأمر. إذا نجح، فهذا يعني أن ملف البيئة لم يصل إلى العملية وأن الخادم يعمل ببيانات الاعتماد الافتراضية. أصلح ذلك قبل أن يتصل أي شيء آخر بالجهاز.
يخزّن mc الأسماء المستعارة في ~/.mc/config.json بنص عادي، لذلك تبقى بيانات الاعتماد في الدليل المنزلي للمستخدم الذي نفّذ الأمر. يؤدي تشغيل mc باستخدام sudo إلى وضع بيانات اعتماد root في /root/.mc/config.json. أبقِ الاسم المستعار الخاص بـroot في حساب مسؤول واحد، وامنح كل تطبيق مفتاحه الخاص.
إنشاء رابط موقّع مسبقاً لكائن واحد
رابط URL موقّع مسبقاً هو رابط HTTPS عادي مرفق بتوقيع ومدة انتهاء. يمكن لأي شخص يملك الرابط جلب ذلك الكائن من دون حساب ومن دون استخدام عميل.
mc share download --expire 12h local/backups/hello.txtيحتوي الناتج على X-Amz-Signature وX-Amz-Expires في سلسلة الاستعلام. هناك أمران قد يفاجئان المستخدمين. يُنشأ الرابط باستخدام نقطة النهاية في الاسم المستعار الذي استخدمته، لذلك فإن الاسم المستعار على 127.0.0.1 ينتج رابطاً لا يمكن فتحه إلا من هذا الجهاز. أنشئ اسماً مستعاراً ثانياً على اسم المضيف العام للروابط التي تنوي إرسالها. ولا يوجد زر لإلغاء الرابط. يبقى التوقيع صالحاً حتى انتهاء مدته، لذلك فإن ضبط مدة قصيرة هو وسيلة التحكم الوحيدة المتاحة. ويمثل Seven days الحد الأقصى الذي يسمح به تنسيق توقيع S3.
امنح restic مفتاحاً وbucket مستقلين
يمكن لبيانات اعتماد root قراءة كل bucket وحذفه، لذلك يجب ألا تحتفظ بها مهمة النسخ الاحتياطي. أنشئ bucket، وسياسة تقتصر على ذلك الـbucket، ومستخدماً لا يحصل على أي صلاحيات أخرى.
mc mb local/restic
cat > /tmp/restic-rw.json <<'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket", "s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::restic"]
},
{
"Effect": "Allow",
"Action": ["s3:GetObject", "s3:PutObject", "s3:DeleteObject"],
"Resource": ["arn:aws:s3:::restic/*"]
}
]
}
EOF
RESTIC_KEY=$(openssl rand -base64 24)
mc admin policy create local restic-rw /tmp/restic-rw.json
mc admin user add local restic-backup "$RESTIC_KEY"
mc admin policy attach local restic-rw --user restic-backupيوفّر MinIO سياسة readwrite مضمّنة، وكانت ستختصر الأمر بخطوة واحدة، لكنها تمنح وصولاً كاملاً إلى كل bucket على الخادم. تذكر السياسة أعلاه اسم الـbucket مرتين عمداً: مرة بصيغة arn:aws:s3:::restic حتى يعمل سرد محتويات الـbucket، ومرة بصيغة arn:aws:s3:::restic/* للكائنات الموجودة داخله. في S3، يُعدّ الـbucket وكائناته موردين منفصلين، لذلك تفشل السياسة التي تذكر أحدهما فقط بطريقة تبدو كأن العميل معطّل.
اختبر حدود الصلاحيات قبل الاعتماد عليها.
mc alias set resticuser http://127.0.0.1:9000 restic-backup "$RESTIC_KEY"
mc ls resticuser/restic
mc ls resticuser/backupsينجح الأمر الأول ls، ويفشل الأمر الثاني مع Access Denied. السياسة التي لم تختبرها ليست سوى تخمين.
وجّه restic الآن إلى الـbucket. يقرأ restic بيانات اعتماد S3 من متغيرات البيئة القياسية الخاصة بـAWS، لذلك لا يوجد ملف بيانات اعتماد خاص بـrestic.
sudo apt install -y restic
export AWS_ACCESS_KEY_ID=restic-backup
export AWS_SECRET_ACCESS_KEY="$RESTIC_KEY"
restic -r s3:http://127.0.0.1:9000/restic init
restic -r s3:http://127.0.0.1:9000/restic backup /etc
restic -r s3:http://127.0.0.1:9000/restic snapshotsيطلب restic init كلمة مرور للمستودع. تشفّر كلمة المرور هذه المستودع، لذلك لا يخزّن MinIO سوى نص مشفّر، وفقدان كلمة المرور يعني فقدان النسخة الاحتياطية. لا يملك التشغيل الذي يبدأه مؤقت systemd طرفية لإدخال كلمة المرور، لذلك اضبط RESTIC_PASSWORD_FILE على ملف بصلاحيات mode 600 للنسخ الاحتياطية المجدولة.
هناك قاعدة لوضع المستودع أهم من أي أمر سبق. إن وضع مستودع restic على VPS نفسه الذي توجد عليه البيانات التي يحميها ينقذك من rm سيئ، ولا يحميك من أي شيء آخر. يجب أن تكون عقدة MinIO على جهاز مختلف، ويفضل أن تكون في منطقة مختلفة. يشرح النسخ الاحتياطية باستخدام restic على VPS جدولة النسخ والاحتفاظ بها استناداً إلى ذلك.
إنهاء TLS باستخدام nginx
يعمل MinIO على localhost، لذلك يمثّل nginx الواجهة العامة. أصدِر الشهادة أولاً كما هو موضح في شهادات Let's Encrypt باستخدام certbot وnginx، ثم استخدم كتلة الخادم التالية.
server {
listen 443 ssl;
server_name s3.example.com;
ignore_invalid_headers off;
client_max_body_size 0;
proxy_buffering off;
proxy_request_buffering off;
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 300;
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding off;
proxy_pass http://127.0.0.1:9000;
}
}بعض هذه الأسطر ضرورية لعمل الإعداد. يلغي client_max_body_size 0 الحد الافتراضي لحجم نص الطلب، وهو 1 MB، إذ يرفض أي رفع أكبر باستخدام 413 Request Entity Too Large قبل أن يرى MinIO الطلب أصلاً. يمرّر proxy_request_buffering off الرفع مباشرة، لأن الإعداد الافتراضي يكتب الطلب بالكامل أولاً في ملف مؤقت، ما يعني أن الكائن الكبير يحتاج إلى مساحة على القرص مرتين. أما proxy_set_header Host $http_host فهو السطر الدقيق: يوقّع S3 على ترويسة Host، لذلك يؤدي proxy يعيد كتابتها إلى فشل كل طلب باستخدام SignatureDoesNotMatch، بينما يعرض access log وصول طلب عادي.
أبلغ MinIO أيضاً باسمه العام، حتى تشير الروابط التي ينشئها إلى proxy بدلاً من localhost.
echo 'MINIO_SERVER_URL=https://s3.example.com' | sudo tee -a /etc/default/minio
sudo systemctl restart minioتبقى إعدادات جدار الحماية محدودة. اسمح بـSSH وHTTPS، ولا تضف أي قاعدة للمنفذين 9000 و9001، لأن العنوان المرتبط بـ127.0.0.1 لا يمكن الوصول إليه من جهاز آخر مهما كانت إعدادات جدار الحماية. تتضمن أساسيات جدار الحماية ufw على VPS الأوامر اللازمة.
متى يكفي MinIO على عقدة واحدة، ومتى تحتاج إلى S3 فعلي
تعني العقدة الواحدة هنا استخدام قرص واحد من دون أي تكافؤ. تصف وثائق MinIO الخاصة هذا التخطيط بأنه مناسب للاختبار ولأحمال العمل الصغيرة التي لا تتطلب التوافر. لا توجد نسخة ثانية داخل عملية النشر، لذلك تعتمد متانة كل كائن على متانة قرص VPS واحد. أما الميزات التي تفترض وجود خلفية موزعة بترميز المحو، ومنها نسخ الحاويات المتماثل وقفل الكائنات، فهي مخصصة لعمليات النشر متعددة الأقراص. لذلك لا تعد أحداً بسياسة احتفاظ غير قابلة للتغيير على هذا الإعداد.
يناسب هذا الإعداد استخدامه كهدف لـrestic على VPS ثانٍ في منطقة أخرى، وكـS3 endpoint لأعمال التطوير وقطع CI الأثرية، حيث لا يكلفك فقدان حاوية سوى إعادة بنائها. كما يناسب رفع ملفات المستخدمين في تطبيق صغير، ما دمت تملك خطة للاسترداد واختبرت استعادة فعلية.
اختر S3 مُداراً عندما يطلب عقد أو جهة تنظيمية قفل الكائنات أو المتانة عبر مناطق متعددة، أو عندما تفضل ألا تكون الشخص الذي يتلقى تنبيهاً عند الساعة 03:00 لأن أحد الأقراص امتلأ. والبنية المتوقفة سبب صريح آخر. اعتباراً من July 2026، يعود تاريخ الملف التنفيذي المجمّع مسبقاً للمجتمع إلى September 2025 ولا يتلقى أي إصلاحات. لذلك يعني تشغيله قبول هذا الوضع، أو البناء من المصدر ومتابعة المشروع بنفسك.
من المفيد توضيح حدّ يتكرر السؤال عنه. تخزين الكائنات ليس قاعدة بيانات. كل عملية كتابة تستبدل كائناً كاملاً، لذلك يكون ملف SQL حي داخل حاوية S3 بطيئاً وغير آمن. أبقِ قاعدة البيانات على القرص المحلي، وانسخها احتياطياً إلى الحاوية بدلاً من ذلك: يشرح تشغيل SQLite في بيئة الإنتاج على VPS هذا الفصل.
أوضاع الفشل والرسائل التي ستظهر
تفشل الوحدة مباشرة بعد systemctl enable --now. اقرأ journalctl -u minio -n 30 --no-pager. يعني Failed to load environment files: No such file or directory أن /etc/default/minio مفقود أو أن مساره مكتوب خطأ في الوحدة. تعني الرسالة التي تنتهي بـ permission denied أن مجلد البيانات غير قابل للكتابة بواسطة حساب الخدمة، فتحقق من أن stat -c '%U' /var/lib/minio/data يعرض minio-user.
لا يزال minioadmin:minioadmin يسجّل الدخول. لم يصل ملف البيئة إلى العملية. تأكد من أن الوحدة تتضمن EnvironmentFile=/etc/default/minio، وشغّل sudo systemctl daemon-reload، ثم أعد تشغيل الخدمة. يقرأ MinIO بيانات اعتماد root مرة واحدة عند بدء التشغيل، لذلك لا يغيّر تعديل ذلك الملف شيئاً من دون إعادة التشغيل.
Address already in use عند بدء التشغيل. توجد عملية أخرى تستخدم المنفذ 9000. اعثر عليها باستخدام sudo ss -ltnp | grep :9000 قبل تغيير منفذ MinIO.
تفشل عمليات الرفع التي تتجاوز 1 MB عبر الـproxy. أعاد nginx الاستجابة 413 Request Entity Too Large، ولم ير MinIO الطلب. اضبط client_max_body_size 0 في كتلة server.
SignatureDoesNotMatch. إما أن المفتاح السري غير صحيح، أو أن شيئاً بين العميل وMinIO أعاد كتابة ترويسة Host التي تغطيها التوقيعة.
RequestTimeTooSkewed. ساعة العميل أو الخادم غير صحيحة. يحمل كل طلب S3 طابعاً زمنياً، ويُرفض خارج نافذة مدتها 15 دقيقة. تحقق من timedatectl وتأكد من أن مزامنة الوقت مفعّلة.
Access Denied على bucket تعرف أنه موجود. المفتاح مقيّد بـbucket مختلف. اعرض ما تسمح به السياسة فعلياً باستخدام mc admin policy info local restic-rw، وقارن اسم bucket في أسطر المورد.
FAQ
هل تكفي عقدة MinIO واحدة للنسخ الاحتياطية الفعلية؟
تكفي كهدف لـ restic يعمل على جهاز منفصل عن البيانات التي يحميها. لكنها لا تكفي باعتبارها النسخة الوحيدة. لا يوفر النشر على محرك واحد أي تكافؤ، لذلك لا توجد نسخة ثانية داخل MinIO. وإذا فقد قرص VPS البيانات، فستفقد الكائنات. احتفظ بهدف ثانٍ في مكان آخر، ونفّذ الاستعادة من الهدفين مرة واحدة على الأقل حتى تتأكد من أن العملية تعمل.
لماذا يفشل sha256sum -c في ملف checksum الخاص بـ MinIO؟
لأن التسمية التي تأتي بعد التجزئة داخل ذلك الملف تسمّي الإصدار، minio.RELEASE.2025-09-07T16-13-09Z، بينما يُسمّى الملف الذي نزّلته عادةً minio. يبحث sha256sum -c عن ملف بالاسم المكتوب داخل ملف checksum، ولا يعثر عليه، ثم يعرض No such file or directory وWARNING: 1 listed file could not be read. عملية التنزيل سليمة. قارن سلاسل التجزئة مباشرةً وتجاهل التسمية، لأنها لا تحمل أي دلالة أمنية.
أين اختفت وحدة تحكم إدارة MinIO على الويب؟
أزالت MinIO ميزات الإدارة من وحدة تحكم إصدار المجتمع في May 2025، وأبقت متصفحاً للكائنات في واجهة الويب. تُدار الحاويات والمستخدمون الآن باستخدام عميل mc، عبر أوامر مثل mc admin user add وmc admin policy attach. هذا هو المسار المدعوم في إصدار المجتمع، وليس حلاً التفافياً، ولذلك ينفّذ هذا الدليل كل شيء من سطر الأوامر.
كيف أوجّه restic إلى MinIO باعتباره backend لـ S3؟
اضبط AWS_ACCESS_KEY_ID وAWS_SECRET_ACCESS_KEY على مفتاح وصول MinIO وسرّه، ثم استخدم سلسلة مستودع بالصيغة s3:https://s3.example.com/restic، حيث يكون آخر عنصر في المسار هو اسم الحاوية. أنشئ الحاوية أولاً باستخدام mc mb، لأن المفتاح المقيّد بحاوية واحدة لا يملك صلاحية إنشاء الحاويات. يشفّر restic كل شيء باستخدام كلمة مرور المستودع الخاصة به قبل الرفع، لذلك يخزّن MinIO نصاً مشفراً ولا يطّلع على ملفاتك مطلقاً.
هل يجب أن أشغّل MinIO خلف nginx؟
تحتاج إلى TLS (أمان طبقة النقل) عندما لا يكون العميل على الجهاز نفسه، لأن بيانات اعتماد S3 وبيانات الكائنات تنتقل داخل الطلب. ويُعدّ استخدام Proxy على المنفذ 443 مع شهادة من certbot أبسط طريقة لتحقيق ذلك، كما أنه يُبقي تجديد الشهادة بعيداً عن MinIO. يمكن لـ MinIO أيضاً إنهاء TLS بنفسه إذا وجّهت --certs-dir إلى دليل يحتوي على public.crt وprivate.key، لكن حساب الخدمة سيحتاج إلى صلاحية قراءة المفتاح الخاص المُجدَّد، وهذا عمل إضافي لتحقيق النتيجة نفسها.