SSD Nodes Learn Hosting plans →
راهنماها Matt Connorتوسط Matt Connor

راهنمای نصب و راه‌اندازی 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 را ارائه نمی‌دهد. در بررسی انجام‌شده در 12 اکتبر 2026، تمام مسیرهای dl.min.io که این راهنما قبلاً برای دانلود باینری سرور، باینری کلاینت و فایل‌های checksum آن‌ها استفاده می‌کرد، پاسخ 410 Gone را برمی‌گردانند که نشان‌دهنده حذف عمدی است و نه یک قطعی موقت. صفحه دانلود در min.io اکنون لیست AIStor Server، AIStor Client، AIStor SDK و چند افزونه AIStor را نمایش می‌دهد و هیچ اثری از نسخه 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 رسمی نصب کنید. در تاریخ 12 اکتبر 2026، نسخه پایدار فعلی در go.dev/dl برابر با go1.27.2 است و هش زیر، همان هشی است که در آن صفحه برای آرشیو linux-amd64 منتشر شده است. اگر نسخه جدیدتری از Go را انتخاب کردید، هش آن را از همان صفحه بردارید. فلگ -f باعث می‌شود curl در صورت بروز خطای HTTP شکست بخورد، به جای اینکه صفحه خطا را با نام درخواستی شما ذخیره کند؛ این همان دلیلی است که باعث می‌شود کاربران در نهایت یک صفحه 404 را استخراج کنند و تعجب کنند که چرا فایل آرشیو نیست.

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

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

published=ecbadb99091a3f46e31f5f934b068b1864eafa7995211b39eaddf76996045fe5
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 release) را به عنوان کاربر عادی خود بسازید. دستور go install هر ماژولی را که دانلود می‌کند، شامل سورس کد خود MinIO، با دیتابیس هش‌های عمومی 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 flags) مورد استفاده سازنده برای درج مشخصات در باینری‌های خود را اعمال نمی‌کند. دستور 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 نیز دیگر این کلاینت را ارائه نمی‌دهد و مخزن minio/mc از ژوئیه 2026 آرشیو شده است، بنابراین آخرین نسخه آن یعنی RELEASE.2025-08-13T08-35-41Z را با همان toolchain زبان 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 نام‌های مستعار (alias) را در ~/.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 مستقل را برای توسعه اولیه و ارزیابی مناسب می‌داند و تأکید می‌کند که MinIO آن را برای محیط production توصیه نمی‌کند. قابلیت Object locking را می‌توان برای یک bucket فعال کرد، اما روی یک VPS، این قابلیت فقط حذف از طریق S3 API را مسدود می‌کند. هر کسی که دسترسی root روی ماشین داشته باشد همچنان می‌تواند فایل‌ها را از روی دیسک حذف کند، بنابراین در این تنظیمات به کسی وعده سیاست نگهداری غیرقابل‌تغییر (immutable) ندهید.

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

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

یک مرز ارزش بیان کردن دارد زیرا اغلب مطرح می‌شود. ذخیره‌سازی شیء (Object storage) دیتابیس نیست. در یک bucket استاندارد، هر عملیات نوشتن، کل یک شیء را جایگزین می‌کند و حتی فراخوانی 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 در تاریخ 12 اکتبر 2026 به 410 Gone برای تمام باینری‌های نسخه community و فایل‌های checksum پاسخ داده است. برچسب بعد از هش در داخل آن فایل، نام نسخه (مانند 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 در مه 2025 ویژگی‌های مدیریتی را از کنسول نسخه community حذف کرد و تنها یک مرورگر آبجکت در رابط وب باقی گذاشت. باکت‌ها و کاربران اکنون با کلاینت mc و با استفاده از دستوراتی مانند mc admin user add و mc admin policy attach مدیریت می‌شوند. این مسیرِ در نظر گرفته شده در نسخه community است و نه یک راهکار موقت؛ به همین دلیل است که این راهنما تمام کارها را از طریق خط فرمان انجام می‌دهد.

چگونه restic را به MinIO به‌عنوان یک backend S3 متصل کنم؟

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

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

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