วิธีติดตั้ง MinIO บน Ubuntu 24.04 สำหรับทำ S3 Storage
เรียนรู้วิธีติดตั้ง MinIO บน Ubuntu 24.04 เพื่อใช้งาน S3 API ส่วนตัว ครอบคลุมการตั้งค่า systemd การจัดการผ่าน mc การสร้าง presigned URLs และการสำรองข้อมูลด้วย restic
สิ่งที่ท่านจะได้รับจาก object storage แบบ self-hosted ด้วย MinIO
MinIO คือ object storage แบบ self-hosted ที่รองรับ Amazon S3 API ท่านสามารถชี้ restic หรือ S3 SDK ไปยังเซิร์ฟเวอร์ของท่านเอง เปลี่ยนการตั้งค่า endpoint เพียงจุดเดียว ก็สามารถอ่าน เขียน แสดงรายการ object และสร้าง presigned links ได้ตามปกติ อย่างไรก็ตาม ความเข้ากันได้ไม่ได้หมายถึงเหมือนกันทุกประการ ตัวอย่างเช่น MinIO ไม่ได้รองรับ object ACLs ของ Amazon และผู้พัฒนาได้ระบุว่าจะไม่เพิ่มฟีเจอร์นี้ ดังนั้นแอปพลิเคชันที่ต้องพึ่งพาพฤติกรรมของ ACL จึงต้องการการตั้งค่ามากกว่าแค่การเปลี่ยน endpoint คู่มือนี้จะแนะนำการสร้างโหนดเดี่ยวบน Ubuntu 24.04 โดยใช้ binary ที่คอมไพล์จากซอร์สโค้ดที่ผ่านการตรวจสอบ, การสร้าง system user เฉพาะ, การใช้ systemd unit ที่แยก root credentials ออกจากไฟล์ unit และการสร้าง bucket สำหรับใช้สำรองข้อมูลด้วย restic
S3 (simple storage service) เป็น HTTP API ไม่ใช่ระบบไฟล์ ท่านสามารถ PUT object ลงใน bucket โดยระบุ key และ GET ข้อมูลกลับมาได้ ใน bucket มาตรฐานจะไม่มีการเขียนข้อมูลบางส่วน (partial write) หรือการเปลี่ยนชื่อไฟล์ (rename) ยกเว้นกรณีของ Amazon S3 Express One Zone directory buckets ที่มีการเรียกใช้งานแบบ append และ rename ได้ แต่เนื่องจากเป็นเพียง storage class ประเภทหนึ่งและคู่มือนี้ไม่ได้พึ่งพาฟีเจอร์ดังกล่าว เครื่องมือสำรองข้อมูลจึงนิยมใช้โมเดลมาตรฐานนี้ เพราะ object จะต้องมาถึงอย่างสมบูรณ์หรือถือว่าไม่มาถึงเลย
โหนดเดียวจะเก็บข้อมูลของท่านไว้หนึ่งชุด นี่คือข้อแลกเปลี่ยนที่ท่านต้องยอมรับ ท่านจะได้ S3 endpoint ที่ควบคุมเองในราคาค่าเช่า VPS แต่ท่านต้องรับหน้าที่ทุกอย่างที่ผู้ให้บริการคลาวด์เคยทำแทนท่าน ตั้งแต่การเปลี่ยนดิสก์ที่เสียหายไปจนถึงการแพตช์ซอฟต์แวร์เซิร์ฟเวอร์ ส่วนท้ายของคู่มือนี้จะอธิบายอย่างชัดเจนว่าเมื่อใดที่ข้อแลกเปลี่ยนนี้คุ้มค่าที่จะทำ
สถานะของ MinIO รุ่น community edition ในเดือนตุลาคม 2026
โปรดอ่านส่วนนี้ก่อนเริ่มดำเนินการ เนื่องจากมีการเปลี่ยนแปลงเมื่อเร็วๆ นี้ ในเดือนพฤษภาคม 2025 MinIO ได้ถอดฟีเจอร์การจัดการออกจากเว็บคอนโซลในรุ่น community edition สิ่งที่เหลืออยู่ในเบราว์เซอร์คือเครื่องมือสำหรับเรียกดูออบเจกต์เท่านั้น ดังนั้นการจัดการ bucket และ access key จึงต้องทำผ่านเครื่องมือบรรทัดคำสั่ง mc แทน
ต่อมาในช่วงปลายปี 2025 MinIO ได้หยุดเผยแพร่ไฟล์ binary รุ่น community ที่คอมไพล์ไว้ล่วงหน้า โดย README ของโปรเจกต์ระบุว่ารุ่น community จะแจกจ่ายในรูปแบบซอร์สโค้ดเท่านั้น และตั้งแต่เดือนเมษายน 2026 เป็นต้นมา repository minio/minio ได้ถูกเก็บถาวรภายใต้ประกาศ THIS REPOSITORY IS NO LONGER MAINTAINED เซิร์ฟเวอร์สำหรับดาวน์โหลดแบบเดิมได้หยุดให้บริการไฟล์รุ่น community แล้ว จากการตรวจสอบเมื่อวันที่ 20 ตุลาคม 2026 ทุก path ของ dl.min.io ที่คู่มือนี้เคยใช้ดาวน์โหลดไฟล์ binary ของเซิร์ฟเวอร์, ไฟล์ binary ของไคลเอนต์ และไฟล์ checksum ต่างตอบกลับด้วย 410 Gone ซึ่งเป็นการจงใจลบออกไม่ใช่เหตุขัดข้องของระบบ ไฟล์ binary mc เพียงรายการเดียวที่ยังคงอยู่บนเซิร์ฟเวอร์นั้นคือ AIStor Client ภายใต้ /aistor/mc/release/ ซึ่งเป็นส่วนหนึ่งของผลิตภัณฑ์เชิงพาณิชย์ หน้าดาวน์โหลดบน min.io ในปัจจุบันแสดงรายการ AIStor Server, AIStor Client, AIStor SDK และส่วนเสริมของ AIStor อีกจำนวนหนึ่ง รวมถึง AIStor รุ่นฟรีที่ระบุว่ามุ่งเน้นไปที่นักพัฒนา นักวิจัย และองค์กรขนาดเล็กที่ใช้งานแบบ standalone โดยไม่มีรุ่น community ให้บริการ
ซอร์สโค้ดยังคงมีอยู่และเป็นเวอร์ชันที่ใหม่กว่าไฟล์ binary รุ่นสุดท้าย รุ่น community สุดท้ายคือ RELEASE.2025-10-15T17-29-55Z ซึ่งเผยแพร่เมื่อวันที่ 16 ตุลาคม 2025 ในฐานะรุ่นปรับปรุงความปลอดภัย โดยแก้ไขช่องโหว่การยกระดับสิทธิ์ผ่านการข้าม session policy ใน service account และ STS ซึ่งบันทึกประจำรุ่นแนะนำให้ผู้ใช้ทุกคนอัปเกรดทันที ไฟล์ binary รุ่นคอมไพล์ล่วงหน้าล่าสุดคือรุ่นเดือนกันยายน 2025 ดังนั้นจึงไม่ได้รับแพตช์แก้ไขดังกล่าว คู่มือนี้จึงใช้วิธีคอมไพล์รุ่นเดือนตุลาคม และเนื่องจาก repository ถูกเก็บถาวรไปแล้ว นี่จึงเป็นการแก้ไขครั้งสุดท้ายที่รุ่น community จะได้รับ
ข้อเท็จจริงดังกล่าวเป็นตัวกำหนดแนวทางของคู่มือนี้ทั้งหมด จึงเป็นเหตุผลว่าทำไม MinIO ในที่นี้จึงฟังการเชื่อมต่อที่ 127.0.0.1 และเข้าถึงอินเทอร์เน็ตผ่าน proxy ที่คุณควบคุมเท่านั้น
ติดตั้ง MinIO binary และตรวจสอบไฟล์ที่ดาวน์โหลด
MinIO เขียนด้วยภาษา Go และ README ของผู้พัฒนาใช้คำสั่ง go install เพียงคำสั่งเดียวในการ build ซึ่งต้องใช้ Go 1.24 หรือใหม่กว่า ให้ติดตั้ง Go จาก tarball อย่างเป็นทางการก่อน ณ วันที่ 20 ตุลาคม 2026 รุ่น stable ปัจจุบันบน go.dev/dl คือ go1.27.3 ซึ่งปล่อยออกมาเมื่อวันที่ 19 ตุลาคม 2026 พร้อมการแก้ไขความปลอดภัยในแพ็กเกจ crypto/x509 และค่า hash ด้านล่างนี้คือค่าที่ประกาศบนหน้านั้นสำหรับไฟล์ archive แบบ linux-amd64 หากคุณเลือกใช้ Go รุ่นที่ใหม่กว่า ให้ใช้ค่า hash จากหน้านั้นแทน แฟล็ก -f จะทำให้ curl ล้มเหลวหากเกิดข้อผิดพลาด HTTP แทนที่จะบันทึกหน้าแสดงข้อผิดพลาดด้วยชื่อไฟล์ที่คุณกำหนด ซึ่งเป็นสาเหตุที่ทำให้หลายคนแตกไฟล์ 404 ออกมาแล้วสงสัยว่าทำไมถึงไม่ใช่ไฟล์ archive
cd /tmp
GOVER=go1.27.3
curl -fsSL "https://go.dev/dl/$GOVER.linux-amd64.tar.gz" -o go.tar.gzเปรียบเทียบค่า hash ทั้งสองค่า โดยให้เปรียบเทียบเฉพาะค่า hash เท่านั้น
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ตอนนี้ให้ build รุ่น community release ล่าสุดในฐานะผู้ใช้ทั่วไปของคุณ go install จะตรวจสอบทุกโมดูลที่ดาวน์โหลด รวมถึงซอร์สโค้ดของ MinIO เอง เทียบกับฐานข้อมูล checksum สาธารณะของ Go ที่ sum.golang.org ดังนั้นหากโมดูลถูกแก้ไขหรือสลับไฟล์ กระบวนการ build จะหยุดทำงานพร้อมแจ้งข้อผิดพลาดด้านความปลอดภัยแทนที่จะสร้าง binary ออกมา
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 ไม่ได้ใช้ build flags เดียวกับที่ผู้พัฒนาใช้ในการประทับตรา binary ของตนเอง go version -m จะอ่านข้อมูลโมดูลที่ Go ฝังไว้ในทุก binary และบรรทัด mod github.com/minio/minio จะระบุ commit ที่คุณใช้ build หากพบ Permission denied แสดงว่าโหมดไม่ถูกต้อง และถ้าพบ command not found แสดงว่า /usr/local/bin ไม่อยู่ใน PATH ของคุณ หาก VPS มีหน่วยความจำไม่เพียงพอสำหรับการ compile ให้รันคำสั่ง go install เดียวกันบนเครื่อง Linux อื่นที่มีสถาปัตยกรรมเดียวกัน แล้วคัดลอกไฟล์ binary มาใช้งานแทน
สร้างผู้ใช้ระบบและไดเรกทอรีข้อมูล
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/miniotee จะล้างเนื้อหาของไฟล์ที่มีอยู่แทนการสร้างไฟล์ใหม่ ดังนั้นโหมดจึงยังคงเป็น 600 และเจ้าของยังคงเป็น root การทำเช่นนี้เป็นความตั้งใจ systemd จะอ่าน EnvironmentFile ในฐานะ root ก่อนลดสิทธิ์เป็น User= ซึ่งหมายความว่าบัญชีบริการไม่จำเป็นต้องอ่านข้อมูลรับรองของตนเอง เมื่อบริการทำงานแล้ว ให้ตรวจสอบด้วย sudo -u minio-user cat /etc/default/minio คำสั่งนี้ต้องแสดงผลเป็น Permission denied
ควรทราบพฤติกรรม 2 ประการของ MinIO ก่อนเริ่มบริการ หากไม่มี MINIO_ROOT_USER และไม่มี MINIO_ROOT_PASSWORD ในสภาพแวดล้อมของ MinIO โปรแกรมจะไม่ปฏิเสธการเริ่มทำงาน แต่จะเริ่มทำงานด้วยข้อมูลรับรองเริ่มต้นที่ระบุไว้ในเอกสาร คือ minioadmin:minioadmin ซึ่งเป็นข้อมูลรับรองคู่แรกที่เครื่องมือสแกนใดลองใช้ และบริการจะดูเหมือนทำงานปกติ ในทางกลับกัน หากรหัสผ่านมีความยาวน้อยกว่า 8 ตัวอักษร MinIO จะปฏิเสธและออกจากโปรแกรมขณะเริ่มทำงาน พร้อมแสดงข้อผิดพลาดว่าข้อมูลรับรองไม่ถูกต้อง เนื่องจาก access key ต้องมีอย่างน้อย 3 ตัวอักษร และ secret key ต้องมีอย่างน้อย 8 ตัวอักษร
MINIO_VOLUMES คือเส้นทางข้อมูล และ MINIO_OPTS ใช้เก็บ flags การผูกบริการกับ 127.0.0.1 หมายความว่าในขณะนี้ไม่มีสิ่งใดภายนอก VPS นี้สามารถเข้าถึง S3 API ได้ ซึ่งเป็นค่าเริ่มต้นที่เหมาะสม ภายหลังคุณจะเปิดให้เข้าถึงโดยตั้งใจผ่าน proxy ที่มี certificate
เขียน 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 ต่อไป ดังนั้นไฟล์ที่ถูกลบหรือ path ที่พิมพ์ผิดจะทำให้มี server ที่ทำงานบน minioadmin:minioadmin โดยไม่มีการแจ้งเตือน หากไม่มีขีด ไฟล์ที่ไม่มีอยู่จะทำให้ unit ล้มเหลวก่อนที่ MinIO จะเริ่มทำงาน และ journalctl -u minio จะแสดง Failed to load environment files: No such file or directory unit ที่ปฏิเสธการเริ่มทำงานตรวจพบได้ง่ายกว่า server ที่ยอมรับรหัสผ่านเริ่มต้นโดยไม่มีการแจ้งเตือน
$MINIO_VOLUMES และ $MINIO_OPTS ไม่ใส่เครื่องหมายอัญประกาศโดยตั้งใจ เพราะ systemd จะแยกตัวแปรที่ไม่ใส่เครื่องหมายอัญประกาศตามช่องว่างออกเป็นอาร์กิวเมนต์แยกกัน นี่คือสาเหตุที่คำ 4 คำใน MINIO_OPTS กลายเป็นอาร์กิวเมนต์ 4 รายการของ minio server LimitNOFILE=65536 เพิ่มขีดจำกัด file descriptor เพราะการเชื่อมต่อแต่ละรายการและไฟล์ข้อมูลแต่ละไฟล์ที่เปิดอยู่ใช้ descriptor 1 รายการ และค่าเริ่มต้น 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/liveis-active ควรแสดง active และ health endpoint ควรตอบกลับ 200 journalctl -u minio -n 20 --no-pager แสดงที่อยู่ API ที่ server กำลัง listening อยู่ หาก unit เริ่มทำงานซ้ำอย่างต่อเนื่อง systemd จะยอมแพ้และบันทึก Start request repeated too quickly ซึ่งหมายความว่า MinIO ออกจากการทำงานทุกครั้ง สาเหตุจะแสดงอยู่ในบรรทัดก่อนหน้าข้อความดังกล่าว ดังนั้นให้อ่านย้อนขึ้นไป
หากต้องการแยกการทำงานเพิ่มเติม ให้เพิ่ม ProtectSystem=full และ ProtectHome=true ในส่วน [Service] ทั้งสองรายการต้องใช้ mount namespace จาก kernel ของ host เมื่อใช้ container virtualisation ที่ใช้ kernel ร่วมกับ host เช่น OpenVZ หรือ LXC รายการเหล่านี้อาจล้มเหลว และ unit จะแจ้ง status=226/NAMESPACE จากนั้นลบ 2 บรรทัดดังกล่าว แล้ว unit จะเริ่มทำงาน ตัว unit เองเป็น unit ทั่วไป และ บริการและตัวตั้งเวลาของ systemd บน VPS อธิบาย directive อื่นๆ ที่เหลือ
ติดตั้ง mc และทดสอบการรับส่งข้อมูล
MinIO client คือ 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 Server เวอร์ชันที่ได้รับอนุญาตเท่านั้น คู่มือดังกล่าวไม่ได้ระบุถึงการใช้งานกับเซิร์ฟเวอร์ชุมชน ดังนั้นคู่มือนี้จึงใช้ไคลเอนต์สำหรับชุมชนต่อไป ที่เก็บ minio/mc ถูกเก็บถาวรตั้งแต่เดือนกรกฎาคม 2026 ดังนั้นให้ build เวอร์ชันล่าสุดคือ RELEASE.2025-08-13T08-35-41Z ด้วย Go toolchain ชุดเดียวกัน ฐานข้อมูล 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.txtmc 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 ไม่ถูกโหลดเข้าสู่กระบวนการ และเซิร์ฟเวอร์ของคุณกำลังทำงานด้วยข้อมูลรับรองเริ่มต้น (default credentials) ให้แก้ไขปัญหานี้ก่อนที่จะดำเนินการอื่นใดกับเครื่อง
mc จัดเก็บ alias ไว้ใน ~/.mc/config.json ในรูปแบบข้อความธรรมดา ดังนั้นข้อมูลรับรองเหล่านั้นจะอยู่ในโฮมไดเรกทอรีของผู้ที่รันคำสั่ง การรัน mc ภายใต้ sudo จะทำให้ข้อมูลรับรองระดับ root ไปอยู่ใน /root/.mc/config.json ให้เก็บ root alias ไว้ในบัญชีผู้ดูแลระบบเพียงบัญชีเดียว และกำหนดคีย์แยกต่างหากให้กับแต่ละแอปพลิเคชัน
การแจกจ่ายออบเจกต์ด้วย 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 สาธารณะสำหรับลิงก์ที่คุณต้องการส่งให้ผู้อื่น ประการที่สอง ไม่มีปุ่มสำหรับยกเลิกการเข้าถึงรายลิงก์ ลายเซ็นจะยังคงมีผลจนกว่าจะหมดอายุ หรือจนกว่าคีย์ที่ใช้ลงนามจะถูกลบหรือเปลี่ยนแปลง สำหรับลิงก์ที่ลงนามด้วย root credentials การยกเลิกหมายถึงการต้องหมุนเวียน (rotate) คีย์เหล่านั้น ดังนั้นการกำหนดวันหมดอายุให้สั้นจึงเป็นวิธีควบคุมที่ใช้งานได้จริง โดยรูปแบบลายเซ็น S3 อนุญาตให้กำหนดอายุได้สูงสุดเพียง 7 วันเท่านั้น
สร้าง key และ bucket สำหรับ restic โดยเฉพาะ
ข้อมูลรับรองของ root สามารถอ่านและลบ bucket ได้ทุก bucket ดังนั้นงานสำรองข้อมูลต้องไม่ใช้ข้อมูลรับรองเหล่านี้ ให้สร้าง bucket, policy ที่จำกัดขอบเขตไว้เฉพาะ bucket นั้น และ user ที่ไม่มีสิทธิ์อื่น
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 มี policy ในตัวชื่อ readwrite ซึ่งจะทำให้สั้นลง 1 คำสั่ง แต่ policy นี้ให้สิทธิ์เข้าถึงทุก bucket บน server อย่างเต็มรูปแบบ policy ด้านบนระบุชื่อ bucket 2 ครั้งโดยตั้งใจ: ครั้งแรกเป็น arn:aws:s3:::restic เพื่อให้สามารถแสดงรายการ bucket ได้ และอีกครั้งเป็น arn:aws:s3:::restic/* สำหรับ object ภายใน bucket ใน S3 bucket และ object เป็น resource แยกกัน ดังนั้น policy ที่ระบุเพียงอย่างใดอย่างหนึ่งจะทำงานล้มเหลวในลักษณะที่ดูเหมือน client เสีย
ทดสอบข้อจำกัดก่อนนำไปใช้งานจริง
mc alias set resticuser http://127.0.0.1:9000 restic-backup "$RESTIC_KEY"
mc ls resticuser/restic
mc ls resticuser/backupsls รายการแรกทำงานสำเร็จ และรายการที่สองล้มเหลวโดยแสดง Access Denied policy ที่ยังไม่ได้ทดสอบเป็นเพียงการคาดเดา
จากนั้นกำหนดค่า 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 snapshotsrestic init จะขอรหัสผ่านของ repository รหัสผ่านนี้ใช้เข้ารหัส repository ดังนั้น MinIO จะจัดเก็บเฉพาะ ciphertext เท่านั้น และหากสูญเสียรหัสผ่าน ก็จะสูญเสียข้อมูลสำรองไปด้วย งานที่เริ่มโดย systemd timer ไม่มี terminal สำหรับป้อนรหัสผ่าน ดังนั้นให้กำหนด RESTIC_PASSWORD_FILE เป็นไฟล์ mode 600 สำหรับงานสำรองข้อมูลตามกำหนดเวลา
มีกฎสำคัญเกี่ยวกับตำแหน่งจัดเก็บซึ่งสำคัญกว่าคำสั่งใดๆ ข้างต้น การมี repository ของ restic อยู่บน VPS เดียวกับข้อมูลที่ปกป้องจะช่วยป้องกันได้เฉพาะกรณี rm ที่ไม่ดีเท่านั้น และไม่ช่วยป้องกันเหตุอื่น MinIO node ควรอยู่คนละเครื่อง และควรอยู่คนละ region หากเป็นไปได้ การสำรองข้อมูล restic บน VPS อธิบายการตั้งเวลาและการเก็บรักษาข้อมูลต่อจากขั้นตอนนี้
ยุติ 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 ลบขีดจำกัดขนาด body เริ่มต้นที่ 1 MB ซึ่งหากไม่ตั้งค่า การอัปโหลดที่มีขนาดใหญ่กว่านั้นจะถูกปฏิเสธด้วย 413 Request Entity Too Large ก่อนที่ MinIO จะได้รับคำขอ proxy_request_buffering off ทำให้การอัปโหลดถูกส่งต่อโดยตรง เนื่องจากค่าเริ่มต้นจะเขียนคำขอทั้งหมดลงในไฟล์ชั่วคราวก่อน และออบเจ็กต์ขนาดใหญ่จะต้องใช้พื้นที่ดิสก์ซ้ำ 2 เท่า proxy_set_header Host $http_host เป็นค่าที่มักมองข้าม ลายเซ็น S3 ครอบคลุม header Host ดังนั้นพร็อกซีที่เขียนค่าใหม่จะทำให้ทุกคำขอล้มเหลวด้วย SignatureDoesNotMatch แม้ access log จะแสดงว่ามีคำขอปกติเข้ามาถึง
กำหนดชื่อสาธารณะของ MinIO ด้วย เพื่อให้ลิงก์ที่ MinIO สร้างชี้ไปยังพร็อกซีแทน localhost
echo 'MINIO_SERVER_URL=https://s3.example.com' | sudo tee -a /etc/default/minio
sudo systemctl restart minioกฎไฟร์วอลล์ควรมีเพียงไม่กี่รายการ อนุญาต SSH และ HTTPS และไม่ต้องสร้างกฎสำหรับพอร์ต 9000 และ 9001 เนื่องจาก address ที่ bind กับ 127.0.0.1 จะไม่สามารถเข้าถึงจากเครื่องอื่นได้ ไม่ว่าไฟร์วอลล์จะกำหนดไว้อย่างไร พื้นฐาน ufw firewall บน VPS มีคำสั่งที่ต้องใช้
เมื่อใดที่ MinIO แบบโหนดเดียวเพียงพอ และเมื่อใดที่คุณต้องการ S3 จริงๆ
โหนดเดียวในที่นี้หมายถึงการใช้ดิสก์เพียงลูกเดียว ดังนั้นจึงไม่มีการทำ parity และไม่มีสำเนาชุดที่สองภายในระบบ ความทนทานของทุกออบเจกต์จึงขึ้นอยู่กับความทนทานของดิสก์บน VPS เพียงลูกเดียว เอกสารของ MinIO เองซึ่งปัจจุบันมีอยู่เพียงในรูปแบบซอร์สโค้ดใน repository minio/docs เท่านั้น (หลังจากที่เอกสารสำหรับชุมชนถูกถอดออกในเดือนตุลาคม 2025) ระบุว่าการติดตั้งแบบ standalone นั้นมีไว้เพื่อการพัฒนาในช่วงเริ่มต้นและการประเมินผลเท่านั้น และ MinIO ไม่แนะนำให้ใช้ในสภาพแวดล้อมการผลิต คุณสามารถเปิดใช้งาน Object locking สำหรับ bucket ได้ แต่บน VPS เพียงเครื่องเดียว ฟีเจอร์นี้จะป้องกันได้เพียงการลบผ่าน S3 API เท่านั้น ใครก็ตามที่มีสิทธิ์ root บนเครื่องยังคงสามารถลบไฟล์บนดิสก์ได้ ดังนั้นอย่าให้คำมั่นสัญญากับใครว่าการตั้งค่านี้มีนโยบายการเก็บรักษาข้อมูลแบบแก้ไขไม่ได้ (immutable retention policy)
การตั้งค่านี้เหมาะสำหรับการเป็นเป้าหมายของ restic บน VPS เครื่องที่สองในอีกภูมิภาคหนึ่ง และเหมาะสำหรับเป็น S3 endpoint สำหรับงานพัฒนาและ CI artifacts ซึ่งการสูญเสีย bucket ไปนั้นมีผลเพียงแค่ต้องสร้างข้อมูลใหม่เท่านั้น นอกจากนี้ยังสมเหตุสมผลสำหรับการอัปโหลดไฟล์ของผู้ใช้ในแอปพลิเคชันขนาดเล็ก ตราบใดที่คุณมีแผนการกู้คืนข้อมูลและได้ทดสอบการกู้คืนจริงแล้ว
ให้เลือกใช้ managed S3 เมื่อสัญญาหรือหน่วยงานกำกับดูแลกำหนดให้ต้องมี object lock หรือความทนทานของข้อมูลในหลายภูมิภาค หรือเมื่อคุณไม่ต้องการเป็นคนที่ถูกเรียกตัวตอนตี 3 เพียงเพราะดิสก์เต็ม อีกเหตุผลหนึ่งที่ตรงไปตรงมาคือเรื่องของโค้ดที่หยุดการพัฒนาแล้ว ณ วันที่ 20 ตุลาคม 2026 รุ่น community edition ได้ถูกจัดเก็บถาวรและไม่มีการดูแลรักษาอีกต่อไป โดยรุ่นสุดท้ายคือ RELEASE.2025-10-15T17-29-55Z ซึ่งเป็นรุ่นที่คู่มือนี้ใช้ในการรวบรวม หลังจากรุ่นนี้จะไม่มีการแก้ไขใดๆ อีก ดังนั้นการใช้งานรุ่นนี้หมายถึงการยอมรับเงื่อนไขดังกล่าว หรือย้ายไปใช้ผลิตภัณฑ์ AIStor เชิงพาณิชย์ของ MinIO หรือโซลูชันจัดเก็บข้อมูลแบบ self-hosted อื่นๆ ซึ่งเปรียบเทียบไว้ใน ทางเลือกแทน MinIO แบบ self-hosted
มีขอบเขตหนึ่งที่ควรระบุไว้เพราะมักเป็นประเด็นบ่อยครั้ง คือ Object storage ไม่ใช่ฐานข้อมูล ใน bucket มาตรฐาน การเขียนข้อมูลทุกครั้งจะเป็นการแทนที่ออบเจกต์ทั้งชิ้น และแม้แต่คำสั่ง append ที่ Amazon เพิ่มเข้ามาสำหรับ S3 Express One Zone ก็ทำได้เพียงเพิ่มข้อมูลต่อท้ายเท่านั้น ดังนั้นการวางไฟล์ SQL ที่มีการใช้งานจริงไว้บน S3 bucket จึงทำงานช้าและไม่ปลอดภัย ให้เก็บฐานข้อมูลไว้บนดิสก์ภายในเครื่องแล้วสำรองข้อมูลลงใน 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 หายไปหรือระบุ path ผิดในยูนิต หากข้อความลงท้ายด้วย permission denied แสดงว่า service account ไม่มีสิทธิ์เขียนในไดเรกทอรีข้อมูล ให้ตรวจสอบว่า stat -c '%U' /var/lib/minio/data แสดงผลเป็น minio-user
minioadmin:minioadmin ยังคงล็อกอินได้ ไฟล์ environment ไม่ถูกโหลดเข้าสู่กระบวนการทำงาน ให้ยืนยันว่ายูนิตมี EnvironmentFile=/etc/default/minio อยู่ จากนั้นรัน sudo systemctl daemon-reload แล้วรีสตาร์ทเซอร์วิส MinIO จะอ่าน root credentials ครั้งเดียวตอนเริ่มทำงาน ดังนั้นการแก้ไขไฟล์โดยไม่รีสตาร์ทจะไม่มีผลใดๆ
Address already in use ตอนเริ่มทำงาน มีกระบวนการอื่นใช้งานพอร์ต 9000 อยู่ ให้ค้นหาด้วย sudo ss -ltnp | grep :9000 ก่อนที่คุณจะเปลี่ยนพอร์ตของ MinIO
การอัปโหลดไฟล์ขนาดเกิน 1 MB ล้มเหลวผ่านพร็อกซี nginx ตอบกลับด้วย 413 Request Entity Too Large และ MinIO ไม่ได้รับคำขอนั้น ให้ตั้งค่า client_max_body_size 0 ใน server block
SignatureDoesNotMatch อาจเป็นไปได้ว่า secret key ไม่ถูกต้อง หรือมีบางอย่างระหว่างไคลเอนต์กับ MinIO เขียนทับ header Host ซึ่งเป็นส่วนที่รวมอยู่ในลายเซ็น (signature)
RequestTimeTooSkewed เวลาบนไคลเอนต์หรือเซิร์ฟเวอร์ไม่ตรงกัน คำขอ S3 ที่มีการลงลายเซ็นทุกรายการจะมี timestamp กำกับอยู่ และ MinIO เช่นเดียวกับ Amazon S3 จะปฏิเสธคำขอที่ลงลายเซ็นใน header หาก timestamp ห่างจากเวลาของเซิร์ฟเวอร์เกิน 15 นาที สำหรับลิงก์แบบ presigned จะตรวจสอบกับเวลาหมดอายุแทน ให้ตรวจสอบ 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 ป้ายกำกับหลังค่าแฮชภายในไฟล์นั้นจะระบุชื่อรุ่น เช่น 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 โดยเหลือเพียงเบราว์เซอร์สำหรับจัดการออบเจกต์ในอินเทอร์เฟซเว็บ การจัดการบัคเก็ตและผู้ใช้ในปัจจุบันต้องทำผ่านไคลเอนต์ 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 โดยที่ส่วนสุดท้ายของ path คือชื่อบัคเก็ต ให้สร้างบัคเก็ตก่อนด้วย mc mb เนื่องจากคีย์ที่จำกัดสิทธิ์ไว้เฉพาะบัคเก็ตเดียวจะไม่มีสิทธิ์สร้างบัคเก็ตใหม่ restic จะเข้ารหัสทุกอย่างด้วยรหัสผ่านของ repository ก่อนการอัปโหลด ดังนั้น MinIO จะจัดเก็บเฉพาะข้อมูลที่เข้ารหัสและไม่สามารถเข้าถึงไฟล์ของคุณได้
ฉันจำเป็นต้องรัน MinIO หลัง nginx หรือไม่?
คุณจำเป็นต้องใช้ TLS (transport layer security) ทุกครั้งที่ไคลเอนต์ไม่ได้อยู่บนเครื่องเดียวกัน เพราะหากไม่มี TLS ข้อมูลทุกออบเจกต์จะถูกส่งผ่านเครือข่ายในรูปแบบข้อความธรรมดา รวมถึง access key ID และลายเซ็นของคำขอด้วย ตัว secret key เองจะไม่ถูกส่งออกจากไคลเอนต์เนื่องจากการลงนาม S3 จะใช้คีย์นั้นในเครื่องเพื่อคำนวณลายเซ็นเท่านั้น แต่บุคคลที่อยู่ระหว่างทางยังคงสามารถอ่านข้อมูลของคุณและทำซ้ำคำขอที่ดักจับได้ตราบเท่าที่ timestamp ยังคงมีผล การใช้พร็อกซีบนพอร์ต 443 พร้อมใบรับรองจาก certbot เป็นวิธีที่ง่ายที่สุดในการเปิดใช้งาน TLS และช่วยให้การต่ออายุใบรับรองแยกออกจาก MinIO ได้ นอกจากนี้ MinIO ยังสามารถทำ TLS termination ได้ด้วยตนเองหากคุณชี้ --certs-dir ไปยังไดเรกทอรีที่เก็บ public.crt และ private.key แต่ในกรณีนี้ service account จำเป็นต้องมีสิทธิ์อ่าน private key ที่ต่ออายุใหม่ ซึ่งเป็นการเพิ่มขั้นตอนการทำงานเพื่อให้ได้ผลลัพธ์เดียวกัน