SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-10-21

راهنمای نصب و راه‌اندازی MinIO روی Ubuntu 24.04

آموزش گام‌به‌گام نصب MinIO روی VPS با Ubuntu 24.04. این راهنما شامل کامپایل باینری، تنظیمات systemd، مدیریت bucket با mc و اتصال restic برای پشتیبان‌گیری امن است.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

مزایای استفاده از MinIO به عنوان فضای ذخیره‌سازی شیء (Object Storage) خودمیزبان

MinIO یک فضای ذخیره‌سازی شیء خودمیزبان است که از API سرویس Amazon S3 پشتیبانی می‌کند. کافی است restic یا یک S3 SDK را به سرور خود متصل کنید و یک تنظیم endpoint را تغییر دهید؛ برای عملیات روزمره مانند خواندن، نوشتن، لیست کردن اشیاء و ایجاد لینک‌های presigned، همین تغییر کافی است. البته سازگاری به معنای یکسان بودن کامل نیست. برای مثال، MinIO از ACLهای اشیاء آمازون پشتیبانی نمی‌کند و توسعه‌دهندگان آن اعلام کرده‌اند که قصدی برای پیاده‌سازی آن ندارند؛ بنابراین، برنامه‌ای که به رفتار ACL وابسته است، به چیزی فراتر از تغییر یک endpoint نیاز دارد. این راهنما یک نود تکی را روی Ubuntu 24.04 راه‌اندازی می‌کند: یک باینری کامپایل‌شده از سورس تأییدشده، یک کاربر سیستمی اختصاصی، یک unit فایل systemd که اعتبارنامه‌های root را خارج از فایل unit نگه می‌دارد، و یک bucket که restic در آن پشتیبان‌گیری می‌کند.

سرویس S3 (Simple Storage Service) یک API مبتنی بر HTTP است و نه یک سیستم فایل. شما یک شیء را با یک کلید در یک bucket قرار می‌دهید (PUT) و آن را دریافت می‌کنید (GET)؛ در یک bucket استاندارد، امکان نوشتن جزئی (partial write) یا تغییر نام وجود ندارد. استثنای این مورد، directory bucketهای S3 Express One Zone آمازون هستند که فراخوانی‌های خاص خود را برای الحاق (append) و تغییر نام دارند، اما این تنها یک کلاس ذخیره‌سازی است و هیچ بخشی از این راهنما به آن وابسته نیست. ابزارهای پشتیبان‌گیری، مدل استاندارد را ترجیح می‌دهند، زیرا یک شیء یا به‌طور کامل منتقل شده است یا اصلاً منتقل نشده است.

یک نود، تنها یک نسخه از داده‌های شما را نگهداری می‌کند. این همان معامله‌ای است که انجام می‌دهید. شما در ازای هزینه یک VPS، یک endpoint S3 تحت کنترل خود به دست می‌آورید و در عین حال، تمام وظایفی که قبلاً بر عهده ارائه‌دهنده ابری بود، از تعویض دیسک خراب گرفته تا وصله‌کردن نرم‌افزار سرور، به عهده شما خواهد بود. بخش انتهایی این راهنما به‌صراحت توضیح می‌دهد که چه زمانی این معامله انتخاب مناسبی است.

وضعیت نسخه Community از MinIO در اکتبر 2026

پیش از آنکه بر اساس این راهنما اقدام کنید، این بخش را مطالعه کنید، زیرا اخیراً تغییراتی ایجاد شده است. در مه 2025، MinIO قابلیت‌های مدیریتی را از کنسول وب در نسخه Community حذف کرد. آنچه در مرورگر باقی مانده، صرفاً یک مرورگر آبجکت (object browser) است، بنابراین مدیریت باکت‌ها و کلیدهای دسترسی اکنون باید با استفاده از کلاینت خط فرمان mc انجام شود.

در اواخر سال 2025، MinIO انتشار فایل‌های باینری پیش‌کامپایل‌شده برای نسخه Community را متوقف کرد. در فایل README این پروژه ذکر شده است که نسخه Community تنها به صورت سورس‌کد توزیع می‌شود و از آوریل 2026، مخزن minio/minio تحت عنوان THIS REPOSITORY IS NO LONGER MAINTAINED آرشیو شده است. سرور دانلود قدیمی نیز دیگر فایل‌های مربوط به نسخه Community را ارائه نمی‌دهد. در بررسی انجام‌شده در 20 اکتبر 2026، تمامی مسیرهای dl.min.io که این راهنما قبلاً برای دانلود باینری سرور، باینری کلاینت و فایل‌های checksum از آن‌ها استفاده می‌کرد، پاسخ 410 Gone را برمی‌گردانند که نشان‌دهنده حذف عمدی است و نه یک قطعی موقت. تنها باینری mc که همچنان روی آن سرور موجود است، AIStor Client در مسیر /aistor/mc/release/ است که به خط تولید تجاری تعلق دارد. صفحه دانلود در min.io اکنون شامل AIStor Server، AIStor Client، AIStor SDK و چند افزونه AIStor است، به همراه یک سطح رایگان از AIStor که برای توسعه‌دهندگان، محققان و سازمان‌های کوچکی که استقرار مستقل (standalone) دارند معرفی شده است، و هیچ نسخه Community در آن دیده نمی‌شود.

سورس‌کد همچنان در دسترس است و از آخرین نسخه باینری جدیدتر است. آخرین نسخه منتشرشده Community، نسخه RELEASE.2025-10-15T17-29-55Z است که در 16 اکتبر 2025 به عنوان یک نسخه امنیتی منتشر شد: این نسخه یک آسیب‌پذیری ارتقای سطح دسترسی (privilege escalation) از طریق دور زدن سیاست نشست (session policy bypass) در حساب‌های سرویس و STS را برطرف می‌کند و یادداشت‌های انتشار به همه کاربران توصیه می‌کنند که فوراً ارتقا دهند. آخرین باینری پیش‌کامپایل‌شده مربوط به بیلد سپتامبر 2025 بود، بنابراین آن اصلاحیه را دریافت نکرد. این راهنما نسخه اکتبر را کامپایل می‌کند و از آنجا که مخزن آرشیو شده است، این آخرین اصلاحیه‌ای خواهد بود که نسخه Community دریافت می‌کند.

همین یک واقعیت، جهت‌گیری باقی این راهنما را تعیین می‌کند. به همین دلیل است که MinIO در اینجا روی 127.0.0.1 گوش می‌دهد و تنها از طریق پروکسی که شما کنترل می‌کنید به اینترنت دسترسی دارد.

نصب فایل باینری MinIO و تأیید دانلود

نرم‌افزار MinIO با زبان Go نوشته شده است و فایل README سازنده، آن را با یک دستور go install می‌سازد که به Go نسخه 1.24 یا جدیدتر نیاز دارد. ابتدا Go را از طریق فایل tarball رسمی نصب کنید. در تاریخ 20 اکتبر 2026، نسخه پایدار فعلی در go.dev/dl برابر با go1.27.3 است که در 19 اکتبر 2026 با یک اصلاح امنیتی برای بسته crypto/x509 منتشر شده است. هش زیر همان هشی است که در آن صفحه برای آرشیو linux-amd64 درج شده است. اگر نسخه جدیدتری از Go را انتخاب می‌کنید، هش آن را از همان صفحه بردارید. پرچم -f باعث می‌شود curl در صورت بروز خطای HTTP شکست بخورد، به‌جای آنکه صفحه خطا را با نام درخواستی شما ذخیره کند؛ این همان دلیلی است که باعث می‌شود کاربران در نهایت یک صفحه 404 را باز کنند و تعجب کنند که چرا فایل آرشیو نیست.

cd /tmp
GOVER=go1.27.3
curl -fsSL "https://go.dev/dl/$GOVER.linux-amd64.tar.gz" -o go.tar.gz

دو هش را با هم مقایسه کنید و فقط هش‌ها را بررسی کنید.

published=65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40
downloaded=$(sha256sum go.tar.gz | awk '{print $1}')
[ "$published" = "$downloaded" ] && echo "checksum ok"

دقیق باشید که این بررسی چه چیزی را اثبات می‌کند. تطابق هش‌ها ثابت می‌کند که دانلود کامل است و در حین انتقال آسیب ندیده یا تغییر نیافته است. این موضوع ثابت نمی‌کند که سازنده قابل اعتماد است. این یک مسئله متفاوت است و هیچ دستور sha256sum آن را حل نمی‌کند.

sudo rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version

اکنون نسخه نهایی community را به عنوان کاربر عادی خود بسازید. دستور go install هر ماژولی را که دانلود می‌کند، از جمله سورس کد خود MinIO، با پایگاه داده checksum عمومی Go در sum.golang.org مقایسه می‌کند؛ بنابراین اگر ماژولی دستکاری یا جایگزین شده باشد، فرآیند ساخت با یک خطای امنیتی متوقف می‌شود و فایل باینری تولید نخواهد شد.

go install github.com/minio/minio@RELEASE.2025-10-15T17-29-55Z
sudo install -o root -g root -m 755 ~/go/bin/minio /usr/local/bin/minio
minio --version
go version -m /usr/local/bin/minio | head -n 3

دستور minio --version به جای نام نسخه، DEVELOPMENT.GOGET را چاپ می‌کند، زیرا go install پرچم‌های build که سازنده برای مهر زدن روی باینری‌های خود استفاده کرده است را اعمال نمی‌کند. دستور go version -m اطلاعات ماژولی که Go در هر فایل باینری تعبیه می‌کند را می‌خواند و خط mod github.com/minio/minio آن، نام commit که ساخته‌اید را نشان می‌دهد. مشاهده Permission denied در اینجا به این معنی است که mode اشتباه است و command not found به این معنی است که /usr/local/bin در PATH شما وجود ندارد. اگر VPS برای کامپایل کردن حافظه کافی ندارد، همان دستور go install را روی یک ماشین لینوکسی دیگر با همان معماری اجرا کنید و فایل باینری را منتقل کنید.

ایجاد یک کاربر سیستمی و دایرکتوری داده

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 درون volume ایجاد می‌کند تا پیکربندی خود را در آن نگه دارد؛ بنابراین اگر مالکیت دایرکتوری متعلق به root باشد، MinIO هنگام شروع به کار با پیامی که به permission denied ختم می‌شود، متوقف خواهد شد. همین قاعده برای تمام سرویس‌هایی که به این شکل اجرا می‌کنید صدق می‌کند و کاربران سرویس با حداقل دسترسی در VPS این موضوع را به‌طور کامل بررسی می‌کند.

قرار دادن اعتبارنامه‌های root در یک فایل محیطی

اعتبارنامه‌های root دسترسی به تمام bucketها را ممکن می‌سازند، بنابراین نباید در فایل unit قرار بگیرند، زیرا آن فایل برای همه قابل خواندن است. ابتدا فایل را با مجوز دسترسی صحیح ایجاد کنید و سپس اطلاعات را در آن بنویسید تا رمز عبور حتی برای یک لحظه هم در فایلی که قابل خواندن است قرار نگیرد.

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 فایل موجود را به جای بازآفرینی، خالی (truncate) می‌کند، بنابراین مجوز دسترسی روی 600 و مالکیت آن روی root باقی می‌ماند. این کار عمدی است. systemd فایل EnvironmentFile را پیش از کاهش سطح دسترسی به User= با کاربر root می‌خواند؛ این یعنی حساب کاربری سرویس هرگز نیازی به خواندن اعتبارنامه‌های خود ندارد. پس از اجرای سرویس، آن را با sudo -u minio-user cat /etc/default/minio بررسی کنید. این دستور باید Permission denied را چاپ کند.

پیش از شروع کار با MinIO، دانستن دو رفتار آن ضروری است. اگر MINIO_ROOT_USER و MINIO_ROOT_PASSWORD در محیط آن تعریف نشده باشند، MinIO از شروع به کار امتناع نمی‌کند. این سرویس با اعتبارنامه‌های پیش‌فرض مستندشده یعنی minioadmin:minioadmin بالا می‌آید که اولین جفت‌نامی است که هر اسکنری امتحان می‌کند، و در حین انجام این کار کاملاً سالم به نظر می‌رسد. در مقابل، رمز عبور کمتر از 8 کاراکتر رد می‌شود: MinIO در زمان راه‌اندازی با خطایی مبنی بر نامعتبر بودن اعتبارنامه‌ها متوقف می‌شود، زیرا access key حداقل به 3 کاراکتر و secret key حداقل به 8 کاراکتر نیاز دارد.

MINIO_VOLUMES مسیر داده‌ها است و MINIO_OPTS شامل فلگ‌ها می‌باشد. اتصال به 127.0.0.1 به این معنی است که هنوز هیچ‌چیز خارج از این VPS نمی‌تواند به S3 API دسترسی داشته باشد، که این تنظیم پیش‌فرض درستی است. شما بعداً آن را به‌صورت آگاهانه و از طریق یک پروکسی که دارای گواهی است، باز خواهید کرد.

نوشتن unit فایل 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 وجود ندارد و این یک تصمیم آگاهانه است، نه یک اشتباه تایپی. با وجود خط تیره (dash)، systemd نبود فایل را نادیده می‌گیرد و MinIO را به هر حال اجرا می‌کند؛ بنابراین یک فایل حذف‌شده یا مسیر اشتباه، بی‌سروصدا باعث می‌شود سرور روی minioadmin:minioadmin اجرا شود. بدون خط تیره، نبود فایل باعث شکست unit پیش از اجرای MinIO می‌شود و journalctl -u minio وضعیت Failed to load environment files: No such file or directory را نشان می‌دهد. تشخیص unitای که از اجرا سر باز می‌زند، بسیار آسان‌تر از سروری است که بی‌سروصدا رمز عبور پیش‌فرض را می‌پذیرد.

متغیرهای $MINIO_VOLUMES و $MINIO_OPTS عمداً بدون کوتیشن (unquoted) رها شده‌اند، زیرا systemd متغیرهای بدون کوتیشن را بر اساس فضای خالی (whitespace) به آرگومان‌های جداگانه تقسیم می‌کند. به این ترتیب، چهار کلمه در MINIO_OPTS به چهار آرگومان برای minio server تبدیل می‌شوند. دستور LimitNOFILE=65536 محدودیت file descriptor را افزایش می‌دهد، زیرا هر اتصال باز و هر فایل دادهٔ باز، یک descriptor اشغال می‌کند و مقدار پیش‌فرض 1024 تحت بار کاری (load) به سرعت تمام می‌شود.

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 را چاپ کند و endpoint سلامت باید پاسخ 200 را برگرداند. دستور journalctl -u minio -n 20 --no-pager آدرس API که سرور روی آن در حال گوش دادن است را نشان می‌دهد. اگر unit مدام در حال restart شدن باشد، systemd پس از مدتی تسلیم شده و پیام Start request repeated too quickly را لاگ می‌کند؛ این یعنی MinIO در هر تلاش با خطا مواجه شده و خارج می‌شود: دلیل آن در خطوط بالای آن پیام چاپ شده است، پس لاگ‌ها را به سمت بالا بخوانید.

برای ایزولاسیون بیشتر، ProtectSystem=full و ProtectHome=true را به بخش [Service] اضافه کنید. هر دو به mount namespace از هسته میزبان (host kernel) نیاز دارند. در مجازی‌سازی کانتینری که هسته میزبان را به اشتراک می‌گذارد، مانند OpenVZ یا LXC، ممکن است این دستورات با شکست مواجه شوند و unit وضعیت status=226/NAMESPACE را گزارش دهد. در این صورت، آن دو خط را حذف کنید تا سرویس اجرا شود. این unit یک فایل معمولی است و سرویس‌ها و تایمرهای systemd روی VPS سایر دستورالعمل‌ها را پوشش می‌دهد.

نصب mc و انجام یک رفت و برگشت داده

کلاینت MinIO همان mc است. آن را با apt install mc نصب نکنید. آن بسته مربوط به Midnight Commander است، یک مدیر فایل که هیچ ارتباطی با MinIO ندارد.

dl.min.io همچنان یک باینری mc ارائه می‌دهد، اما نه نسخه جامعه (community). مسیر قدیمی جامعه، یعنی https://dl.min.io/client/mc/release/linux-amd64/mc، پاسخ 410 Gone را برمی‌گرداند. آنچه MinIO اکنون در آنجا ارائه می‌دهد، AIStor Client در https://dl.min.io/aistor/mc/release/linux-amd64/mc است که مستندات AIStor CLI به آن ارجاع می‌دهد و آن را دارای قابلیت‌های انحصاری برای استقرار سرورهای دارای مجوز AIStor توصیف می‌کند. آن مستندات هیچ اشاره‌ای به استفاده از آن در برابر یک سرور جامعه نمی‌کند، بنابراین این راهنما از کلاینت جامعه استفاده می‌کند. مخزن minio/mc از ژوئیه 2026 آرشیو شده است، بنابراین آخرین نسخه آن یعنی RELEASE.2025-08-13T08-35-41Z را با همان زنجیره ابزار Go بسازید. پایگاه داده checksum این دانلود را نیز پوشش می‌دهد.

go install github.com/minio/mc@RELEASE.2025-08-13T08-35-41Z
sudo install -o root -g root -m 755 ~/go/bin/mc /usr/local/bin/mc

سرور را به عنوان یک alias ثبت کنید، سپس یک شیء را از طریق آن جابه‌جا کنید.

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

این دستور باید با خطا مواجه شود. اگر موفقیت‌آمیز باشد، فایل محیطی (environment file) هرگز به پردازش نرسیده است و سرور شما با اعتبارنامه‌های پیش‌فرض در حال اجراست. پیش از آنکه هر چیز دیگری با ماشین تماس پیدا کند، این مورد را اصلاح کنید.

mc نام‌های مستعار (aliases) را در ~/.mc/config.json به صورت متن ساده ذخیره می‌کند، بنابراین آن اعتبارنامه‌ها در دایرکتوری home هر کسی که دستور را اجرا کرده است، باقی می‌مانند. اجرای mc با کاربر sudo، اعتبارنامه‌های root را در /root/.mc/config.json قرار می‌دهد. alias مربوط به root را فقط روی یک حساب کاربری مدیر نگه دارید و به هر برنامه، کلید اختصاصی خودش را بدهید.

ارائه یک شیء با استفاده از presigned URL

یک presigned URL در واقع یک لینک HTTPS معمولی است که یک امضا و زمان انقضا به آن پیوست شده است. هر کسی که این لینک را در اختیار داشته باشد، می‌تواند بدون نیاز به حساب کاربری و بدون کلاینت، آن شیء خاص را دریافت کند.

mc share download --expire 12h local/backups/hello.txt

خروجی این عملیات شامل X-Amz-Signature و X-Amz-Expires در رشته پرس‌وجو (query string) است. دو نکته در مورد آن ممکن است کاربران را غافلگیر کند. اول اینکه لینک بر اساس endpoint موجود در alias مورد استفاده شما ساخته می‌شود؛ بنابراین، یک alias روی 127.0.0.1 لینکی تولید می‌کند که فقط همان ماشین قادر به باز کردن آن است. برای لینک‌هایی که قصد ارسال آن‌ها را دارید، یک alias دوم روی hostname عمومی خود ایجاد کنید. دوم اینکه هیچ دکمه‌ای برای ابطال (revoke) هر لینک به‌صورت جداگانه وجود ندارد. امضا تا زمان انقضا یا تا وقتی که کلید امضاکننده حذف یا تغییر نکند، معتبر باقی می‌ماند. برای لینکی که با root credentials امضا شده باشد، این به معنای تغییر کلیدها (rotating) است؛ بنابراین، تعیین یک زمان انقضای کوتاه، تنها راه کنترل عملی است. 7 روز، حداکثر زمانی است که فرمت امضای S3 اجازه می‌دهد.

اختصاص یک کلید و باکت مجزا به restic

اعتبارنامه‌های root می‌توانند هر باکتی را بخوانند و حذف کنند، بنابراین یک job پشتیبان‌گیری نباید از آن‌ها استفاده کند. یک باکت، یک policy محدود به همان باکت و کاربری که دسترسی دیگری ندارد، ایجاد کنید.

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 دارای یک policy داخلی به نام readwrite است که اگرچه استفاده از آن یک دستور کوتاه‌تر است، اما دسترسی کامل به تمام باکت‌های سرور را اعطا می‌کند. policy بالا به عمد نام باکت را دو بار ذکر کرده است: یک بار به عنوان arn:aws:s3:::restic تا امکان لیست کردن باکت فراهم شود و یک بار به عنوان arn:aws:s3:::restic/* برای اشیاء داخل آن. در S3، باکت و اشیاء درون آن منابعی مجزا هستند؛ بنابراین policy که فقط یکی از آن‌ها را نام ببرد، با خطایی مواجه می‌شود که شبیه به خرابی کلاینت به نظر می‌رسد.

پیش از اعتماد به محدودیت، آن را تست کنید.

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 شکست می‌خورد. policy که تست نشده باشد، صرفاً یک حدس است.

اکنون restic را به سمت باکت هدایت کنید. 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 همیشه فقط متن رمزنگاری‌شده (ciphertext) را ذخیره می‌کند و گم کردن رمز عبور به معنای از دست رفتن پشتیبان است. اجرای یک job توسط systemd timer ترمینالی برای تایپ کردن ندارد، بنابراین برای پشتیبان‌گیری‌های زمان‌بندی‌شده، RESTIC_PASSWORD_FILE را روی فایلی با دسترسی 600 تنظیم کنید.

یک قاعدهٔ مکان‌یابی از هر دستور دیگری مهم‌تر است. مخزن restic روی همان VPS که داده‌ها را محافظت می‌کند، فقط شما را در برابر یک rm بد محافظت می‌کند و نه هیچ چیز دیگر. گره MinIO باید ماشینی متفاوت و در حالت ایده‌آل در منطقه‌ای (region) دیگر باشد. پشتیبان‌گیری‌های restic روی VPS علاوه بر این موضوع، زمان‌بندی و نگهداری (retention) را نیز پوشش می‌دهد.

خاتمه TLS با nginx

سرویس MinIO روی localhost قرار دارد، بنابراین nginx رابط عمومی سرور است. ابتدا گواهی را طبق توضیحات دریافت گواهی‌های Let's Encrypt با certbot و nginx صادر کنید و سپس از این server block استفاده نمایید.

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 مگابایتی بدنه درخواست را حذف می‌کند؛ در غیر این صورت، هر آپلود بزرگ‌تر با خطای 413 Request Entity Too Large رد می‌شود، پیش از آنکه MinIO اصلاً درخواست را دریافت کند. دستور proxy_request_buffering off آپلود را مستقیماً جریان می‌دهد (stream)، زیرا در حالت پیش‌فرض، کل درخواست ابتدا در یک فایل موقت ذخیره می‌شود و برای یک شیء بزرگ، نیاز به فضای دیسک دوبرابر ایجاد می‌گردد. دستور proxy_set_header Host $http_host نکته ظریفی دارد: امضای S3 هدر Host را پوشش می‌دهد، بنابراین پروکسی که آن را بازنویسی کند، باعث می‌شود هر درخواست با خطای SignatureDoesNotMatch شکست بخورد، در حالی که لاگ دسترسی، ورود یک درخواست عادی را نشان می‌دهد.

نام عمومی MinIO را نیز به آن اعلام کنید تا لینک‌هایی که تولید می‌کند به جای 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 واقعی نیاز دارید

منظور از تک‌گره در اینجا، استفاده از یک درایو است؛ بنابراین هیچ‌گونه parity یا نسخهٔ دومی در داخل deployment وجود ندارد و پایداری هر شیء، دقیقاً برابر با پایداری یک دیسک VPS است. مستندات خود MinIO که از زمان حذف مستندات جامعهٔ کاربری در اکتبر 2025، تنها به عنوان سورس در مخزن minio/docs موجود است، deployment مستقل (standalone) را برای مراحل اولیهٔ توسعه و ارزیابی مناسب می‌داند و تأکید می‌کند که MinIO آن را برای محیط‌های production توصیه نمی‌کند. قابلیت Object locking را می‌توان برای یک bucket فعال کرد، اما روی یک VPS، این قابلیت فقط حذف از طریق S3 API را مسدود می‌کند. هر کسی که دسترسی root روی ماشین داشته باشد، همچنان می‌تواند فایل‌ها را از روی دیسک حذف کند؛ بنابراین در این پیکربندی، به هیچ‌کس وعدهٔ یک سیاست نگهداری تغییرناپذیر (immutable retention policy) ندهید.

این مدل برای استفاده به عنوان مقصد restic در یک VPS دوم در منطقه‌ای دیگر، و همچنین به عنوان S3 endpoint برای کارهای توسعه و artifactهای CI که از دست دادن bucket فقط هزینهٔ rebuild مجدد را به همراه دارد، گزینهٔ مناسبی است. همچنین برای آپلودهای کاربر در یک برنامهٔ کوچک منطقی است، به شرطی که خودتان طرح بازیابی (recovery plan) را مدیریت کنید و عملاً یک عملیات restore را تست کرده باشید.

زمانی S3 مدیریت‌شده (managed) را انتخاب کنید که یک قرارداد یا نهاد نظارتی، قابلیت object lock یا پایداری چندمنطقه‌ای (multi-region) را الزامی کرده باشد، یا زمانی که ترجیح می‌دهید ساعت 03:00 صبح به دلیل پر شدن دیسک، تماسی برای رفع مشکل دریافت نکنید. کد منجمد شده (frozen code) دلیل صادقانهٔ دیگری است. از تاریخ 20 اکتبر 2026، نسخهٔ community آرشیو شده و دیگر نگهداری نمی‌شود و آخرین release آن یعنی RELEASE.2025-10-15T17-29-55Z، همان نسخه‌ای است که این راهنما بر اساس آن تدوین شده است. هیچ باگی پس از آن رفع نخواهد شد؛ بنابراین اجرای آن به معنای پذیرش این وضعیت یا مهاجرت به خط تولید تجاری AIStor از MinIO یا سایر سرویس‌های ذخیره‌سازی self-hosted است که در جایگزین‌های self-hosted برای MinIO مقایسه شده‌اند.

یک مرز مشخص وجود دارد که ارزش ذکر کردن دارد، زیرا زیاد مطرح می‌شود. ذخیره‌سازی شیء (Object storage) یک دیتابیس نیست. در یک bucket استاندارد، هر عملیات write کل یک شیء را جایگزین می‌کند و حتی فراخوانی append که آمازون برای S3 Express One Zone اضافه کرده است، فقط داده را به انتهای فایل می‌افزاید؛ بنابراین یک فایل SQL زنده روی یک bucket S3، کند و ناامن است. دیتابیس را روی دیسک محلی نگه دارید و از آن در bucket بک‌آپ بگیرید: اجرای SQLite در production روی یک 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 همچنان لاگین می‌کند. فایل محیطی (environment file) هرگز به پردازش نرسیده است. تأیید کنید که یونیت حاوی EnvironmentFile=/etc/default/minio است، دستور sudo systemctl daemon-reload را اجرا کنید و سپس سرویس را ری‌استارت کنید. MinIO اعتبارنامه‌های root خود را فقط یک‌بار در زمان راه‌اندازی می‌خواند، بنابراین ویرایش آن فایل بدون ری‌استارت، تغییری ایجاد نمی‌کند.

Address already in use در زمان راه‌اندازی. پردازش دیگری پورت 9000 را اشغال کرده است. پیش از تغییر پورت MinIO، آن را با sudo ss -ltnp | grep :9000 پیدا کنید.

آپلودهای بالای 1 مگابایت از طریق پروکسی شکست می‌خورند. nginx پاسخ 413 Request Entity Too Large را داده و MinIO هرگز درخواست را دریافت نکرده است. مقدار client_max_body_size 0 را در بلوک server تنظیم کنید.

SignatureDoesNotMatch. یا کلید مخفی (secret key) اشتباه است، یا چیزی بین کلاینت و MinIO هدر Host را که امضا آن را پوشش می‌دهد، بازنویسی کرده است.

RequestTimeTooSkewed. ساعت کلاینت یا سرور اشتباه است. هر درخواست امضاشده S3 دارای یک برچسب زمانی (timestamp) است و MinIO، مانند Amazon S3، درخواست‌های دارای هدر امضاشده‌ای را که برچسب زمانی آن‌ها بیش از 15 دقیقه با ساعت خودش اختلاف داشته باشد، رد می‌کند. لینک‌های پیش‌امضاشده (presigned links) بر اساس زمان انقضایشان بررسی می‌شوند. timedatectl را بررسی کنید و تأیید کنید که همگام‌سازی زمان فعال است.

Access Denied روی باکتی که می‌دانید وجود دارد. کلید به باکت دیگری محدود شده است. آنچه را که پالیسی واقعاً اجازه می‌دهد با mc admin policy info local restic-rw چاپ کنید و نام باکت را در خطوط resource مقایسه کنید.

FAQ

آیا MinIO تک‌گره برای پشتیبان‌گیری واقعی مناسب است؟

این سرویس برای استفاده به‌عنوان مقصد restic روی ماشینی جدا از داده‌هایی که محافظت می‌کند، مناسب است. اما به‌عنوان تنها نسخهٔ پشتیبان شما کافی نیست. استقرار روی یک درایو واحد هیچ‌گونه parity ندارد، بنابراین نسخهٔ دومی درون MinIO وجود ندارد و اگر دیسک آن VPS دچار خرابی شود، آبجکت‌ها از بین می‌روند. یک مقصد دوم در جای دیگری نگه دارید و حداقل یک‌بار از هر دو مقصد عملیات بازیابی را انجام دهید تا از صحت فرایند مطمئن شوید.

چرا sha256sum -c روی فایل checksum مربوط به MinIO با خطا مواجه می‌شود؟

شما تنها در صورتی با این فایل مواجه می‌شوید که آن را از قبل ذخیره کرده باشید، زیرا dl.min.io در تاریخ 20 October 2026 برای تمام باینری‌های کامیونیتی و فایل‌های checksum، به 410 Gone پاسخ داده است. برچسب بعد از هش در داخل آن فایل، نام نسخه (مانند 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 به‌عنوان یک S3 backend متصل کنم؟

مقادیر AWS_ACCESS_KEY_ID و AWS_SECRET_ACCESS_KEY را روی access key و secret مربوط به MinIO تنظیم کنید، سپس از یک رشته مخزن به فرمت s3:https://s3.example.com/restic استفاده کنید که در آن آخرین بخش مسیر، نام باکت است. ابتدا باکت را با دستور mc mb ایجاد کنید، زیرا کلیدی که دسترسی آن محدود به یک باکت خاص است، اجازهٔ ایجاد باکت جدید را ندارد. restic پیش از آپلود، همه چیز را با رمز عبور مخزن خود رمزنگاری می‌کند، بنابراین MinIO داده‌ها را به‌صورت ciphertext ذخیره می‌کند و هرگز فایل‌های شما را نمی‌بیند.

آیا باید MinIO را پشت nginx اجرا کنم؟

هر زمان که کلاینت روی همان ماشین نباشد، شما به TLS (امنیت لایه انتقال) نیاز دارید؛ زیرا بدون آن، تمام آبجکت‌ها به‌همراه access key ID و امضای درخواست، به‌صورت متن ساده در شبکه جابه‌جا می‌شوند. خودِ secret key هرگز کلاینت را ترک نمی‌کند، زیرا امضای S3 فقط به‌صورت محلی از آن برای محاسبهٔ امضا استفاده می‌کند، اما هر کسی در مسیر شبکه می‌تواند داده‌های شما را بخواند یا یک درخواست ضبط‌شده را تا زمانی که timestamp آن معتبر است، بازپخش (replay) کند. استفاده از یک پروکسی روی پورت 443 با گواهی certbot، ساده‌ترین راه برای دریافت TLS است و مدیریت تمدید گواهی را از MinIO جدا می‌کند. MinIO همچنین می‌تواند خودش TLS را terminate کند اگر --certs-dir را به دایرکتوری حاوی public.crt و private.key ارجاع دهید، اما در این صورت حساب کاربری سرویس نیاز به دسترسی خواندن به کلید خصوصی تمدیدشده دارد که برای رسیدن به همان نتیجه، کار اضافه‌ای است.

آیا این مقاله مفید بود؟