התקנת MinIO על שרת VPS עם Ubuntu 24.04
למדו להקים שרת אחסון אובייקטים תואם S3 בניהול עצמי. המדריך כולל הידור ממקור מאומת, הגדרת systemd, ניהול גישה עם mc, יצירת קישורים חתומים וגיבויים מאובטחים עם restic.
מה תקבלו מאחסון אובייקטים בניהול עצמי באמצעות MinIO
MinIO הוא פתרון אחסון אובייקטים בניהול עצמי התומך ב־API של Amazon S3. הגדירו את restic או כל S3 SDK מול השרת שלכם, שנו הגדרה אחת של endpoint, וזה כל מה שנדרש עבור פעולות קריאה, כתיבה, הצגת רשימות וקישורים חתומים (presigned links) בשימוש יומיומי. עם זאת, תאימות אינה זהות מוחלטת. MinIO אינו מיישם, למשל, את ה־ACLs של אובייקטים ב־Amazon, והמפתחים הצהירו שאין להם כוונה לעשות זאת; לכן, יישום התלוי בהתנהגות ACL יזדקק ליותר מאשר רק endpoint חדש. מדריך זה מקים צומת יחיד על Ubuntu 24.04: קובץ בינארי שעבר הידור ממקור מאומת, משתמש מערכת ייעודי, יחידת systemd ששומרת על פרטי הגישה של ה־root מחוץ לקובץ ה־unit, ו־bucket ש־restic מבצע אליו גיבויים.
S3 (Simple Storage Service) הוא API מבוסס HTTP ולא מערכת קבצים. אתם מבצעים PUT לאובייקט בתוך bucket תחת מפתח מסוים ומבצעים GET כדי לקבל אותו בחזרה; ב־bucket סטנדרטי אין כתיבה חלקית ואין שינוי שם (rename). ה־directory buckets מסוג S3 Express One Zone של Amazon הם היוצא מן הכלל, עם קריאות ייעודיות להוספה (append) ושינוי שם, אך זוהי מחלקת אחסון אחת בלבד ושום דבר במדריך זה אינו מסתמך עליה. כלי גיבוי מעדיפים את המודל הסטנדרטי, כיוון שאובייקט או שהגיע בשלמותו או שלא הגיע כלל.
צומת יחיד מחזיק עותק אחד של הנתונים שלכם. זו הפשרה שאתם מבצעים. אתם מקבלים endpoint מסוג S3 בשליטתכם במחיר של VPS, אך אתם גם יורשים את כל המטלות שספק הענן נהג לבצע, החל מהחלפת דיסק תקול ועד לעדכון תוכנת השרת. הסעיף לקראת הסוף מפרט בבירור מתי פשרה זו כדאית.
מצבה של מהדורת הקהילה של MinIO באוקטובר 2026
קראו חלק זה לפני שתתבססו על המערכת, כיוון שהדברים השתנו לאחרונה. במאי 2025 הסירה MinIO את תכונות הניהול מממשק הניהול בדפדפן במהדורת הקהילה. מה שנותר בדפדפן הוא דפדפן אובייקטים בלבד, ולכן ניהול של buckets ושל access keys מתבצע כעת באמצעות כלי שורת הפקודה mc.
בהמשך שנת 2025 הפסיקה MinIO להפיץ קבצים בינאריים מהודרים מראש עבור מהדורת הקהילה. קובץ ה-README של הפרויקט מציין כי מהדורת הקהילה מופצת כקוד מקור בלבד, ומאז אפריל 2026 מאגר ה-minio/minio הועבר לארכיון תחת ההודעה THIS REPOSITORY IS NO LONGER MAINTAINED. שרת ההורדות הישן הפסיק גם הוא להגיש את קובצי הקהילה. בבדיקה שנערכה ב-20 באוקטובר 2026, כל נתיב dl.min.io ששימש מדריך זה להורדות – הקובץ הבינארי של השרת, הקובץ הבינארי של הלקוח וקבצי ה-checksum שלהם – מחזיר 410 Gone, מה שמעיד על הסרה מכוונת ולא על תקלה זמנית. הקובץ הבינארי היחיד מסוג mc שעדיין נמצא על השרת הוא ה-AIStor Client תחת /aistor/mc/release/, השייך לקו המוצרים המסחרי. דף ההורדות באתר min.io מציג כעת את AIStor Server, AIStor Client, AIStor SDK ומספר תוספים ל-AIStor, לצד שכבת AIStor חינמית המוגדרת כמתאימה למפתחים, חוקרים וארגונים קטנים המריצים פריסות עצמאיות, ללא מהדורת קהילה.
קוד המקור עדיין זמין, והוא חדש יותר מהקובץ הבינארי האחרון. מהדורת הקהילה הסופית היא RELEASE.2025-10-15T17-29-55Z, שפורסמה ב-16 באוקטובר 2025 כמהדורת אבטחה: היא מתקנת פרצת הרשאות המאפשרת הסלמת הרשאות דרך עקיפת מדיניות session בחשבונות שירות וב-STS, והערות השחרור ממליצות לכל המשתמשים לשדרג באופן מיידי. הקובץ הבינארי המהודר האחרון היה גרסת ספטמבר 2025, ולכן הוא מעולם לא קיבל את התיקון הזה. מדריך זה מבצע הידור (compile) לגרסת אוקטובר, ומכיוון שהמאגר בארכיון, זהו גם התיקון האחרון שמהדורת הקהילה תקבל.
עובדה זו מעצבת את המשך המדריך. זו הסיבה ש-MinIO כאן מאזין ב-127.0.0.1 ומגיע לאינטרנט רק דרך proxy שבשליטתכם.
התקנת הקובץ הבינארי של MinIO ואימות ההורדה
MinIO כתוב ב־Go, וה־README של הספק מאפשר לבנות אותו באמצעות פקודת go install אחת, הדורשת Go 1.24 או גרסה חדשה יותר. התקינו תחילה את Go מתוך ה־tarball הרשמי. נכון ל־20 באוקטובר 2026, הגרסה היציבה הנוכחית ב־go.dev/dl היא go1.27.3, ששוחררה ב־19 באוקטובר 2026 עם תיקון אבטחה לחבילת crypto/x509. ה־hash המופיע מטה הוא זה שפורסם באותו עמוד עבור הארכיון linux-amd64. אם תבחרו בגרסת Go חדשה יותר, קחו את ה־hash שלה מאותו עמוד. הדגל -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השוו בין שני ה־hashes, והשוו אך ורק את ה־hashes.
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כעת בצעו את הבנייה של גרסת הקהילה הסופית כמשתמש רגיל. 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 3minio --version מדפיס DEVELOPMENT.GOGET במקום שבו אמור היה להופיע שם הגרסה, כיוון ש־go install לא מחיל את דגלי הבנייה שהספק השתמש בהם כדי להטביע את הקבצים הבינאריים שלו. go version -m קורא את פרטי המודול ש־Go מטמיע בכל קובץ בינארי, ושורת ה־mod github.com/minio/minio שלו מציינת את ה־commit שבניתם. Permission denied כאן מציין שהמצב (mode) שגוי, ו־command not found מציין ש־/usr/local/bin אינו נמצא ב־PATH שלכם. אם לשרת ה־VPS אין מספיק זיכרון עבור תהליך ההידור, הריצו את אותה פקודת go install על מכונת Linux אחרת בעלת אותה ארכיטקטורה והעתיקו את הקובץ הבינארי.
יצירת משתמש מערכת וספריית נתונים
MinIO מקבל העלאות מהרשת, לכן אין להריץ אותו כ-root. יש להקצות לו חשבון ללא ספריית בית וללא 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 מדלג על יצירת ספריית בית, כיוון שחשבון שלעולם אינו מתחבר למערכת אינו זקוק לה. בדקו את התוצאה בעזרת id minio-user, ובעזרת stat -c '%U %a' /var/lib/minio, שאמור להדפיס minio-user 750.
ספריית הנתונים חייבת להיות בעלת הרשאות כתיבה עבור משתמש זה, ולא רק קריאה. בהפעלה הראשונה, MinIO יוצר ספריית .minio.sys בתוך הנפח (volume) כדי לאחסן את התצורה שלו; לכן, ספרייה בבעלות root תגרום ל-MinIO להיסגר בזמן העלייה עם הודעה שמסתיימת ב-permission denied. אותו כלל חל על כל שירות שאתם מריצים בדרך זו, והמאמר משתמשי שירות בעלי הרשאות מינימליות ב-VPS מפרט זאת כראוי.
אחסון פרטי הגישה של root בקובץ סביבה
פרטי הגישה של root פותחים את כל ה-buckets, לכן אין להשאיר אותם בקובץ ה-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/miniotee מקצר קובץ קיים במקום ליצור אותו מחדש, כך שההרשאות נשארות 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 יבצע exit בעת העלייה עם שגיאה המציינת שפרטי הגישה אינם תקינים, כיוון שנדרשים לפחות 3 תווים ל-access key ולפחות 8 תווים ל-secret key.
MINIO_VOLUMES הוא נתיב הנתונים ו-MINIO_OPTS מכיל את ה-flags. קישור ל-127.0.0.1 אומר ששום גורם מחוץ ל-VPS הזה לא יכול להגיע ל-S3 API בשלב זה, וזו ברירת המחדל הנכונה. אתם תפתחו את הגישה באופן יזום מאוחר יותר, דרך proxy שמחזיק תעודה.
כתיבת ה-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, וזו החלטה מכוונת ולא טעות הקלדה. עם המקף, 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 מעלה את מגבלת ה-file descriptor, כיוון שכל חיבור פתוח וכל קובץ נתונים פתוח צורכים descriptor אחד, ומגבלת ברירת המחדל של 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, ונקודת הקצה של ה-health אמורה להשיב 200. הפקודה journalctl -u minio -n 20 --no-pager מציגה את כתובת ה-API שעליה השרת מאזין. אם היחידה ממשיכה לבצע restart, ה-systemd יוותר וירשום בלוג Start request repeated too quickly, מה שאומר ש-MinIO יוצא בכל ניסיון: הסיבה מודפסת בשורות שמעל להודעה זו, לכן יש לקרוא כלפי מעלה.
לצורך בידוד רב יותר, הוסיפו את ProtectSystem=full ו-ProtectHome=true למקטע [Service]. שניהם דורשים mount namespaces מליבת המארח. בווירטואליזציה של מכולות המשתפת את ליבת המארח, כגון OpenVZ או LXC, הם עלולים להיכשל, ואז היחידה תדווח על status=226/NAMESPACE. הסירו את שתי השורות הללו והיא תעלה. היחידה עצמה היא יחידה רגילה, והמאמר שירותים וטיימרים של systemd ב-VPS מכסה את יתר ההנחיות.
התקנת mc וביצוע בדיקת תקינות מקצה לקצה
הלקוח של MinIO הוא mc. אין להתקין אותו באמצעות apt install mc. חבילה זו היא Midnight Commander, מנהל קבצים שאינו קשור ל-MinIO.
dl.min.io עדיין מספק קובץ בינארי מסוג mc, אך לא את הגרסה הקהילתית. הנתיב הקהילתי הישן, 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, אשר התיעוד של ה-CLI שלו מציין כי הוא כולל פונקציונליות בלעדית עבור פריסות AIStor Server ברישיון. תיעוד זה אינו מזכיר שימוש מול שרת קהילתי, לכן מדריך זה נצמד ללקוח הקהילתי. מאגר ה-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פקודה זו חייבת להיכשל. אם היא מצליחה, קובץ הסביבה לא הגיע לתהליך והשרת שלכם פועל עם פרטי הגישה המוגדרים כברירת מחדל. תקנו זאת לפני שכל גורם אחר ניגש למכונה.
mc שומר alias ב-~/.mc/config.json בטקסט גלוי, לכן פרטי הגישה הללו נמצאים בתיקיית הבית של מי שהריץ את הפקודה. הרצת 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 בתוך מחרוזת השאילתה. שני דברים לגביו מפתיעים משתמשים. הקישור נבנה מנקודת הקצה (endpoint) בכינוי (alias) שבו השתמשת, לכן כינוי ב־127.0.0.1 ייצור קישור שרק מכונה זו יכולה לפתוח: צור כינוי שני על שם המארח הציבורי שלך עבור קישורים שאתה מתכוון לשלוח. כמו כן, אין כפתור ביטול לכל קישור בנפרד. החתימה נשארת תקפה עד שתפוג או עד שהמפתח שחתם עליה יוסר או ישונה; עבור קישור שנחתם עם פרטי הגישה של ה-root, המשמעות היא החלפתם, ולכן תאריך תפוגה קצר הוא אמצעי הבקרה המעשי. שבעה ימים הם פרק הזמן המקסימלי שפורמט החתימה של S3 מאפשר.
הקצאת מפתח ו-bucket ייעודיים עבור restic
הרשאות ה-root מאפשרות קריאה ומחיקה של כל ה-buckets, לכן משימת גיבוי אינה צריכה להחזיק בהן. צרו bucket, מדיניות (policy) המוגבלת ל-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-backupMinIO כוללת מדיניות מובנית מסוג readwrite שהייתה חוסכת פקודה אחת, אך היא מעניקה גישה מלאה לכל ה-buckets בשרת. המדיניות לעיל מציינת את ה-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. מדיניות שלא נבדקה היא בגדר ניחוש בלבד.
כעת הגדירו את ה-bucket עבור 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 תבקש סיסמה עבור ה-repository. סיסמה זו מצפינה את ה-repository, כך ש-MinIO מאחסנת רק טקסט מוצפן, ואובדן הסיסמה משמעו אובדן הגיבוי. הרצה שמתבצעת על ידי טיימר של systemd אינה כוללת מסוף להקלדת סיסמה, לכן הגדירו את RESTIC_PASSWORD_FILE לקובץ עם הרשאות 600 עבור גיבויים מתוזמנים.
כלל מיקום אחד חשוב יותר מכל פקודה לעיל. repository של restic שנמצא על אותו VPS שבו נמצא המידע המגובה מגן עליכם רק מפני rm שגוי, ולא משום דבר אחר. צומת ה-MinIO צריך להיות מכונה נפרדת, רצוי באזור גיאוגרפי אחר. גיבויי restic על גבי VPS מכסה תזמון ושמירת גרסאות מעבר לכך.
סיום TLS עם nginx
MinIO מאזין ב-localhost, לכן nginx מהווה את הממשק הציבורי. הנפיקו תחילה את התעודה, כמתואר ב-הנפקת תעודות Let's Encrypt עם certbot ו-nginx, ולאחר מכן השתמשו בבלוק ה-server הבא.
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 על גודל ה-body, שאלמלא כן תגרום לדחיית כל העלאה גדולה יותר עם 413 Request Entity Too Large עוד לפני שהבקשה מגיעה ל-MinIO. proxy_request_buffering off מעביר את ההעלאה בזרם ישיר (stream), שכן ברירת המחדל שומרת את כל הבקשה לקובץ זמני תחילה, מה שדורש שטח דיסק כפול עבור אובייקטים גדולים. proxy_set_header Host $http_host היא ההגדרה העדינה: חתימת S3 מכסה את ה-header מסוג Host, לכן proxy שמשכתב אותו יגרום לכל בקשה להיכשל עם SignatureDoesNotMatch, בעוד לוג הגישה יציג בקשה תקינה שהתקבלה.
הגדירו ל-MinIO את השם הציבורי שלו, כדי שהקישורים שהוא מייצר יצביעו על ה-proxy ולא על localhost.
echo 'MINIO_SERVER_URL=https://s3.example.com' | sudo tee -a /etc/default/minio
sudo systemctl restart minioה-firewall נשאר מצומצם. אפשרו גישת SSH ו-HTTPS, והשאירו את פורטים 9000 ו-9001 ללא כל חוק, כיוון שכתובת המאזינה ל-127.0.0.1 אינה נגישה ממכונה אחרת ללא קשר להגדרות ה-firewall. ב-יסודות ה-firewall מסוג ufw ב-VPS תמצאו את הפקודות הרלוונטיות.
מתי MinIO בשרת יחיד מספיק, ומתי דרוש S3 אמיתי
שרת יחיד בהקשר זה משמעו כונן אחד, לכן אין יתירות (parity) ואין עותק שני בתוך הפריסה, ושרידותו של כל אובייקט תלויה בשרידותו של דיסק ה-VPS בלבד. התיעוד של MinIO עצמו, שקיים רק כקוד מקור במאגר ה-minio/docs מאז שהתיעוד הקהילתי המקוון הוסר באוקטובר 2025, מתאר פריסה עצמאית ככזו המיועדת לשלבי פיתוח והערכה מוקדמים, ומציין כי MinIO אינה ממליצה עליה בסביבת ייצור. ניתן להפעיל נעילת אובייקטים (object locking) עבור bucket, אך ב-VPS יחיד הדבר מונע מחיקה רק דרך ה-API של S3. לכל בעל הרשאות root במכונה עדיין יש יכולת להסיר את הקבצים מהדיסק, לכן אל תבטיחו לאיש מדיניות שימור בלתי-ניתנת לשינוי (immutable) בתצורה זו.
זהו פתרון מתאים כיעד עבור restic ב-VPS שני באזור גיאוגרפי אחר, וכנקודת קצה (endpoint) של S3 עבור עבודות פיתוח וארטיפקטים של CI, שבהם אובדן של bucket משמעו בנייה מחדש בלבד. זהו פתרון סביר גם עבור העלאות משתמשים ביישום קטן, כל עוד אתם מחזיקים בתוכנית התאוששות ובדקתם בפועל תהליך שחזור.
בחרו ב-S3 מנוהל כאשר חוזה או רגולטור דורשים נעילת אובייקטים או שרידות רב-אזורית, או כאשר אתם מעדיפים לא להיות האדם שמוקפץ ב-03:00 בגלל שדיסק התמלא. קוד קפוא הוא סיבה כנה נוספת. נכון ל-20 באוקטובר 2026, מהדורת הקהילה מאורכבת ואינה מתוחזקת עוד, והגרסה האחרונה שלה, RELEASE.2025-10-15T17-29-55Z, היא זו שמדריך זה מהדר. שום דבר לא יתוקן לאחר גרסה זו, לכן הרצתה משמעה קבלת עובדה זו, או מעבר לקו המוצרים המסחרי AIStor של MinIO או לאחסון אחר בניהול עצמי, כפי שמשווה חלופות ל-MinIO בניהול עצמי.
גבול אחד ראוי לציון כיוון שהוא עולה לעיתים קרובות. אחסון אובייקטים אינו מסד נתונים. ב-bucket סטנדרטי כל כתיבה מחליפה אובייקט שלם, ואפילו פקודת ה-append ש-Amazon הוסיפה עבור S3 Express One Zone רק מוסיפה נתונים לסוף הקובץ, לכן קובץ SQL פעיל ב-bucket של S3 הוא איטי ולא בטוח. שמרו את מסד הנתונים על דיסק מקומי ובצעו גיבוי שלו לתוך ה-bucket במקום זאת: הרצת 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 חסר או שהנתיב אליו שגוי בקובץ ה-unit. הודעה שמסתיימת ב-permission denied משמעותה שתיקיית הנתונים אינה ניתנת לכתיבה על ידי חשבון השירות; ודאו ש-stat -c '%U' /var/lib/minio/data מציג minio-user.
minioadmin:minioadmin עדיין מתחבר. קובץ הסביבה לא הגיע לתהליך. ודאו שה-unit מכיל את EnvironmentFile=/etc/default/minio, הריצו את sudo systemctl daemon-reload, ולאחר מכן בצעו restart לשירות. MinIO קורא את פרטי הגישה של ה-root פעם אחת בלבד בעת העלייה, לכן עריכת הקובץ ללא restart לא תשנה דבר.
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 block.
SignatureDoesNotMatch. או שמפתח ה-secret שגוי, או שרכיב כלשהו בין הלקוח לבין MinIO שינה את ה-header מסוג Host, אשר נכלל בחתימה.
RequestTimeTooSkewed. השעון בלקוח או בשרת אינו מכוון. כל בקשת S3 חתומה נושאת חותמת זמן, ו-MinIO, בדומה ל-Amazon S3, דוחה בקשה חתומה שחותמת הזמן שלה רחוקה ביותר מ-15 דקות מהשעון המקומי שלו. קישורים חתומים מראש (presigned links) נבדקים מול זמן התפוגה שלהם. בדקו את timedatectl וודאו שסנכרון הזמן פעיל.
Access Denied על bucket שאתם יודעים שקיים. המפתח מוגבל ל-bucket אחר. הציגו את מה שהמדיניות מאפשרת בפועל בעזרת mc admin policy info local restic-rw והשוו את שם ה-bucket בשורות ה-resource.
FAQ
האם MinIO על צומת בודד מספיק לגיבויים אמיתיים?
הוא מספיק כיעד עבור restic כאשר הוא רץ על מכונה נפרדת מהנתונים אותם הוא מגבה. הוא אינו מספיק כעותק יחיד. פריסה על כונן בודד היא ללא יתירות (parity), לכן אין עותק שני בתוך MinIO, ואם הדיסק של ה-VPS יאבד נתונים, האובייקטים יאבדו. החזיקו יעד שני במקום אחר, ובצעו שחזור משניהם לפחות פעם אחת כדי לוודא שהתהליך עובד.
מדוע sha256sum -c נכשל בקובץ ה-checksum של MinIO?
תיתקלו בקובץ זה רק בהעתק שנשמר מוקדם יותר, כיוון ש-dl.min.io ענה על 410 Gone עבור כל קובץ בינארי וקובץ checksum קהילתי שנבדק ב-20 באוקטובר 2026. התווית שאחרי ה-hash בתוך הקובץ מציינת את ה-release, כגון minio.RELEASE.2025-09-07T16-13-09Z, בעוד שהקובץ שהורד נקרא בדרך כלל minio. sha256sum -c מחפש קובץ בשם שכתוב בתוך קובץ ה-checksum, לא מוצא אותו, ומדווח על No such file or directory ו-WARNING: 1 listed file could not be read. ההורדה תקינה. השוו את מחרוזות ה-hash ישירות והתעלמו מהתווית, שאין לה משמעות אבטחתית.
לאן נעלם ממשק הניהול של MinIO?
MinIO הסירה את תכונות הניהול מגרסת הקהילה של ה-console במאי 2025, והשאירה דפדפן אובייקטים בממשק האינטרנט. ניהול buckets ומשתמשים מתבצע כעת באמצעות הלקוח mc, תוך שימוש בפקודות כגון mc admin user add ו-mc admin policy attach. זהו הנתיב המיועד בגרסת הקהילה ולא פתרון עוקף, וזו הסיבה שמדריך זה מבצע את כל הפעולות משורת הפקודה.
כיצד מגדירים את restic לעבוד מול MinIO כ-S3 backend?
הגדירו את AWS_ACCESS_KEY_ID ו-AWS_SECRET_ACCESS_KEY ל-access key של MinIO ול-secret שלו, ולאחר מכן השתמשו במחרוזת repository בתבנית s3:https://s3.example.com/restic, כאשר רכיב הנתיב האחרון הוא שם ה-bucket. צרו את ה-bucket תחילה באמצעות mc mb, כיוון שלמפתח המוגבל ל-bucket אחד אין הרשאה ליצור buckets. restic מצפין את כל המידע עם סיסמת ה-repository שלו לפני ההעלאה, כך ש-MinIO מאחסן ciphertext ולעולם לא רואה את הקבצים שלכם.
האם אני חייב להריץ את MinIO מאחורי nginx?
אתם זקוקים ל-TLS (אבטחת שכבת תעבורה) בכל פעם שלקוח אינו נמצא על אותה מכונה, כיוון שללא TLS כל אובייקט עובר ברשת כטקסט גלוי, יחד עם ה-access key ID וחתימת הבקשה. ה-secret key עצמו לעולם לא עוזב את הלקוח, שכן חתימת S3 משתמשת בו מקומית בלבד כדי לחשב את החתימה, אך כל מי שנמצא בנתיב התעבורה עדיין יכול לקרוא את הנתונים שלכם ולבצע replay לבקשה שנתפסה כל עוד חותמת הזמן שלה בתוקף. proxy בפורט 443 עם תעודה מ-certbot הוא הדרך הפשוטה ביותר להשיג TLS, והוא מרחיק את חידוש התעודות מ-MinIO. MinIO יכול גם לבצע TLS termination בעצמו אם תפנו את --certs-dir לספרייה המכילה את public.crt ו-private.key, אך אז חשבון השירות זקוק להרשאת קריאה למפתח הפרטי המחודש, מה שמהווה עבודה נוספת עבור אותה תוצאה.