วิธีติดตั้ง MinIO บน Ubuntu 24.04 สำหรับทำ S3 Storage
เรียนรู้วิธีติดตั้ง MinIO บน Ubuntu 24.04 เพื่อใช้งาน S3 API ส่วนตัว ครอบคลุมการตั้งค่า systemd การจัดการผ่าน mc การสร้าง presigned URLs และการสำรองข้อมูลด้วย restic
สิ่งที่ท่านจะได้รับจาก self-hosted object storage ด้วย MinIO
MinIO คือระบบ object storage แบบ self-hosted ที่รองรับ Amazon S3 API ท่านสามารถชี้ restic หรือ S3 SDK ใดๆ ไปยังเซิร์ฟเวอร์ของท่านเองได้ เพียงแค่เปลี่ยนการตั้งค่า endpoint ตัว client ก็จะไม่พบความแตกต่างใดๆ คู่มือนี้จะสร้างโหนดเดี่ยวบน Ubuntu 24.04 โดยประกอบด้วย binary ที่คอมไพล์จากซอร์สโค้ดที่ผ่านการตรวจสอบ, การสร้าง system user เฉพาะ, systemd unit ที่แยกเก็บ root credentials ออกจากไฟล์ unit และ bucket สำหรับใช้สำรองข้อมูลด้วย restic
S3 (simple storage service) เป็น HTTP API ไม่ใช่ระบบไฟล์ ท่านสามารถ PUT object ลงใน bucket ภายใต้ key และ GET ข้อมูลกลับมาได้ โดยไม่มีการเขียนข้อมูลบางส่วนหรือการเปลี่ยนชื่อไฟล์ เครื่องมือสำรองข้อมูลมักใช้รูปแบบนี้เพราะ object จะถูกส่งมาอย่างครบถ้วนหรือส่งมาไม่ถึงเลย
โหนดเดียวจะเก็บข้อมูลของท่านไว้หนึ่งชุด นี่คือข้อแลกเปลี่ยนที่ท่านต้องยอมรับ ท่านจะได้ S3 endpoint ที่ควบคุมเองในราคาของ VPS แต่ท่านต้องรับภาระงานทั้งหมดที่ผู้ให้บริการ cloud เคยทำแทนท่าน ตั้งแต่การเปลี่ยนดิสก์ที่เสียหายไปจนถึงการแพตช์ซอฟต์แวร์เซิร์ฟเวอร์ ส่วนท้ายของคู่มือนี้จะอธิบายอย่างชัดเจนว่าเมื่อใดที่ข้อแลกเปลี่ยนนี้คุ้มค่า
สถานะของ MinIO รุ่น community edition ในเดือนตุลาคม 2026
โปรดอ่านส่วนนี้ก่อนเริ่มดำเนินการ เนื่องจากมีการเปลี่ยนแปลงเมื่อเร็วๆ นี้ ในเดือนพฤษภาคม 2025 MinIO ได้ถอดฟีเจอร์การจัดการออกจากเว็บคอนโซลในรุ่น community edition สิ่งที่เหลืออยู่ในเบราว์เซอร์มีเพียงตัวจัดการออบเจกต์เท่านั้น ดังนั้นการจัดการ bucket และ access key จึงต้องทำผ่าน mc command line client แทน
ต่อมาในช่วงปลายปี 2025 MinIO ได้หยุดเผยแพร่ไฟล์ binary ที่คอมไพล์ไว้ล่วงหน้าสำหรับรุ่น community โดย README ของโปรเจกต์ระบุว่ารุ่น community จะแจกจ่ายในรูปแบบซอร์สโค้ดเท่านั้น และตั้งแต่เดือนเมษายน 2026 เป็นต้นมา repository minio/minio ได้ถูกเก็บถาวรภายใต้ประกาศ THIS REPOSITORY IS NO LONGER MAINTAINED นอกจากนี้เซิร์ฟเวอร์ดาวน์โหลดเดิมยังหยุดให้บริการไฟล์สำหรับรุ่น community อีกด้วย จากการตรวจสอบเมื่อวันที่ 10 ตุลาคม 2026 พบว่าทุก dl.min.io path ที่คู่มือนี้เคยใช้ดาวน์โหลดไฟล์ binary ของเซิร์ฟเวอร์, binary ของไคลเอนต์ และไฟล์ checksum ต่างตอบกลับด้วย 410 Gone ซึ่งเป็นการจงใจถอดออกไม่ใช่เหตุขัดข้องทางเทคนิค หน้าดาวน์โหลดบน min.io ในปัจจุบันเสนอเพียง AIStor Server, AIStor Client และ AIStor SDK เท่านั้น
ซอร์สโค้ดยังคงมีอยู่และเป็นเวอร์ชันที่ใหม่กว่า binary รุ่นสุดท้าย รุ่น community สุดท้ายคือ RELEASE.2025-10-15T17-29-55Z ซึ่งเผยแพร่เมื่อวันที่ 16 ตุลาคม 2025 ในฐานะรุ่นปรับปรุงความปลอดภัย โดยแก้ไขช่องโหว่การยกระดับสิทธิ์ผ่านการข้าม session policy ใน service accounts และ STS ซึ่งบันทึกประจำรุ่นแนะนำให้ผู้ใช้ทุกคนอัปเกรดทันที ทั้งนี้ binary ที่คอมไพล์ไว้ล่วงหน้ารุ่นสุดท้ายคือรุ่นของเดือนกันยายน 2025 จึงไม่ได้รับแพตช์แก้ไขดังกล่าว คู่มือนี้จึงใช้วิธีคอมไพล์รุ่นเดือนตุลาคม และเนื่องจาก repository ถูกเก็บถาวรไปแล้ว นี่จึงเป็นการแก้ไขครั้งสุดท้ายที่รุ่น community จะได้รับ
ข้อเท็จจริงดังกล่าวส่งผลต่อเนื้อหาในส่วนที่เหลือของคู่มือนี้ และเป็นเหตุผลว่าทำไม MinIO ในที่นี้จึงฟังคำสั่งที่ 127.0.0.1 และเชื่อมต่ออินเทอร์เน็ตผ่าน proxy ที่คุณควบคุมเท่านั้น
ติดตั้งไฟล์ไบนารีของ MinIO และตรวจสอบไฟล์ที่ดาวน์โหลด
MinIO เขียนด้วยภาษา Go โดยใน README ของผู้พัฒนาได้ระบุคำสั่ง go install สำหรับการ build ซึ่งต้องใช้ Go 1.24 หรือใหม่กว่า ให้ติดตั้ง Go จากไฟล์ tarball อย่างเป็นทางการก่อน ณ วันที่ 10 ตุลาคม 2026 รุ่นเสถียรปัจจุบันบน go.dev/dl คือ go1.27.2 และค่าแฮชด้านล่างนี้คือค่าที่ประกาศไว้บนหน้าเว็บดังกล่าวสำหรับไฟล์ archive แบบ linux-amd64 หากคุณเลือกใช้ Go รุ่นที่ใหม่กว่า ให้ใช้ค่าแฮชจากหน้าเว็บเดียวกัน แฟล็ก -f จะทำให้ curl ล้มเหลวหากเกิดข้อผิดพลาดทาง HTTP แทนที่จะบันทึกหน้าแสดงข้อผิดพลาดเป็นชื่อไฟล์ที่คุณกำหนด ซึ่งเป็นสาเหตุที่ทำให้ผู้ใช้หลายคนเผลอแตกไฟล์ที่เป็นหน้า 404 แล้วสงสัยว่าเหตุใดจึงไม่ใช่ไฟล์ archive
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จากนั้นให้ build รุ่น community release ล่าสุดในฐานะผู้ใช้ทั่วไปของคุณ go install จะตรวจสอบทุกโมดูลที่ดาวน์โหลดมา รวมถึงซอร์สโค้ดของ MinIO เอง เทียบกับฐานข้อมูล checksum สาธารณะของ Go ที่ sum.golang.org ดังนั้นหากมีโมดูลใดถูกดัดแปลงหรือสลับไฟล์ กระบวนการ build จะหยุดทำงานพร้อมแจ้งข้อผิดพลาดด้านความปลอดภัย แทนที่จะสร้างไฟล์ไบนารีออกมา
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 แบบเดียวกับที่ผู้พัฒนาใช้ในการระบุเวอร์ชันของไบนารีที่พวกเขาแจกจ่าย go version -m จะอ่านข้อมูลโมดูลที่ Go ฝังไว้ในไฟล์ไบนารีทุกไฟล์ และบรรทัด mod github.com/minio/minio จะระบุ commit ที่คุณใช้ build หากพบ Permission denied แสดงว่าโหมดไม่ถูกต้อง และหากพบ command not found แสดงว่า /usr/local/bin ไม่ได้อยู่ใน PATH ของคุณ หาก VPS มีหน่วยความจำไม่เพียงพอสำหรับการ compile ให้รันคำสั่ง go install เดียวกันนี้บนเครื่อง Linux อื่นที่มีสถาปัตยกรรมเดียวกัน แล้วคัดลอกไฟล์ไบนารีมาใช้งานแทน
สร้างผู้ใช้ระบบและไดเรกทอรีข้อมูล
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 ไม่ได้ให้บริการ client นี้อีกต่อไป และ repository 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 ออกมา การรับส่งข้อมูลแบบ round trip นี้เป็นเครื่องพิสูจน์ที่แท้จริงว่าเซิร์ฟเวอร์ทำงานได้ เนื่องจากเป็นการส่งคำขอ S3 ที่มีการลงลายเซ็นแบบเดียวกับที่ client อื่นๆ จะใช้งาน mc admin info local จะพิมพ์สถานะของเซิร์ฟเวอร์หากคุณต้องการตรวจสอบเพิ่มเติม
รันการตรวจสอบอีกหนึ่งรายการในขณะที่ระบบยังว่างอยู่
mc alias set defaultcheck http://127.0.0.1:9000 minioadmin minioadminคำสั่งนี้ต้องล้มเหลว หากคำสั่งสำเร็จ แสดงว่าไฟล์ environment ไม่ถูกโหลดเข้าสู่กระบวนการ และเซิร์ฟเวอร์ของคุณกำลังทำงานด้วยข้อมูลประจำตัวเริ่มต้น (default credentials) ให้แก้ไขปัญหานี้ก่อนที่จะอนุญาตให้สิ่งอื่นใดเข้าถึงเครื่อง
mc จะจัดเก็บ alias ไว้ใน ~/.mc/config.json ในรูปแบบข้อความธรรมดา ดังนั้นข้อมูลประจำตัวเหล่านี้จะอยู่ใน home directory ของผู้ที่รันคำสั่ง การรัน mc ภายใต้ sudo จะนำข้อมูลประจำตัวของ root ไปไว้ใน /root/.mc/config.json ควรเก็บ root alias ไว้ในบัญชีผู้ดูแลระบบเพียงบัญชีเดียว และกำหนด key แยกต่างหากให้กับแต่ละแอปพลิเคชัน
แจกจ่ายออบเจ็กต์หนึ่งรายการด้วย presigned URL
presigned URL คือ HTTPS link ทั่วไปที่แนบลายเซ็นและวันหมดอายุไว้ ผู้ที่มี link นี้สามารถดึงออบเจ็กต์นั้นได้โดยไม่ต้องมี account และไม่ต้องใช้ client
mc share download --expire 12h local/backups/hello.txtผลลัพธ์จะมี X-Amz-Signature และ X-Amz-Expires อยู่ใน query string มี 2 ประเด็นที่มักทำให้ผู้ใช้ประหลาดใจ link นี้สร้างจาก endpoint ใน alias ที่คุณใช้ ดังนั้น alias บน 127.0.0.1 จะสร้าง link ที่เปิดได้เฉพาะจากเครื่องนี้เท่านั้น ให้สร้าง alias ที่สองบน hostname สาธารณะสำหรับ link ที่คุณต้องการส่งต่อ และไม่มีปุ่ม revoke ลายเซ็นจะยังใช้ได้จนกว่าจะหมดอายุ ดังนั้นการกำหนดวันหมดอายุให้สั้นจึงเป็นวิธีควบคุมเพียงอย่างเดียวที่มี รูปแบบลายเซ็น 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 ที่แท้จริง
การตั้งค่านี้เหมาะสำหรับการเป็นเป้าหมายของ restic บน VPS เครื่องที่สองในภูมิภาคอื่น และเหมาะสำหรับเป็น S3 endpoint สำหรับงานพัฒนาและ CI artifacts ซึ่งหาก bucket สูญหาย คุณก็แค่สร้างใหม่โดยไม่มีความเสียหายอื่นตามมา นอกจากนี้ยังสมเหตุสมผลสำหรับการอัปโหลดไฟล์ของผู้ใช้ในแอปพลิเคชันขนาดเล็ก ตราบใดที่คุณมีแผนการกู้คืนข้อมูลและได้ทดสอบการกู้คืนจริงแล้ว
ควรเลือกใช้ managed S3 เมื่อสัญญาหรือหน่วยงานกำกับดูแลกำหนดให้ต้องมี object lock หรือความทนทานของข้อมูลในหลายภูมิภาค หรือเมื่อคุณไม่ต้องการเป็นคนที่ถูกเรียกตัวตอนตี 3 เพียงเพราะดิสก์เต็ม อีกเหตุผลหนึ่งที่ตรงไปตรงมาคือเรื่องของซอฟต์แวร์ที่หยุดการพัฒนาแล้ว ณ วันที่ 10 ตุลาคม 2026 รุ่น community edition ได้ถูกเก็บถาวรและไม่มีการดูแลรักษาอีกต่อไป โดยรุ่นสุดท้ายคือ RELEASE.2025-10-15T17-29-55Z ซึ่งเป็นรุ่นที่คู่มือนี้ใช้ในการคอมไพล์ จะไม่มีการแก้ไขใดๆ หลังจากนี้ ดังนั้นการใช้งานรุ่นนี้หมายถึงคุณต้องยอมรับความเสี่ยงดังกล่าว หรือย้ายไปใช้ผลิตภัณฑ์เชิงพาณิชย์อย่าง AIStor ของ MinIO หรือเปลี่ยนไปใช้ที่เก็บข้อมูลแบบ self-hosted อื่นๆ ซึ่ง ทางเลือกอื่นแทน MinIO แบบ self-hosted ได้เปรียบเทียบไว้
มีขอบเขตหนึ่งที่ควรระบุไว้เพราะมักเป็นประเด็นบ่อยครั้ง นั่นคือ Object storage ไม่ใช่ฐานข้อมูล การเขียนข้อมูลทุกครั้งจะเป็นการแทนที่ออบเจกต์ทั้งชิ้น ดังนั้นการวางไฟล์ 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 ไม่มีอยู่ หรือระบุพาธไว้ผิดในหน่วย ข้อความที่ลงท้ายด้วย permission denied หมายความว่า service account ไม่มีสิทธิ์เขียนไดเรกทอรีข้อมูล ดังนั้นตรวจสอบว่า stat -c '%U' /var/lib/minio/data แสดงค่า minio-user
minioadmin:minioadmin ยังคงเข้าสู่ระบบได้ ไฟล์สภาพแวดล้อมไม่ถูกส่งไปถึงโพรเซส ตรวจสอบว่าในหน่วยมี EnvironmentFile=/etc/default/minio เรียกใช้ sudo systemctl daemon-reload จากนั้นรีสตาร์ต service MinIO จะอ่านข้อมูลประจำตัว root เพียงครั้งเดียวเมื่อเริ่มต้นระบบ ดังนั้นการแก้ไขไฟล์ดังกล่าวโดยไม่รีสตาร์ตจะไม่เปลี่ยนแปลงอะไร
Address already in use เมื่อเริ่มต้นระบบ มีโพรเซสอื่นใช้ port 9000 อยู่ ค้นหาโพรเซสนั้นด้วย sudo ss -ltnp | grep :9000 ก่อนเปลี่ยน port ของ MinIO
การอัปโหลดที่มีขนาดเกิน 1 MB ล้มเหลวผ่าน proxy nginx ตอบกลับด้วย 413 Request Entity Too Large และ MinIO ไม่ได้รับคำขอ กำหนด client_max_body_size 0 ใน server block
SignatureDoesNotMatch สาเหตุอาจเป็น secret key ไม่ถูกต้อง หรือมีสิ่งใดระหว่าง client กับ MinIO แก้ไข header Host ซึ่งอยู่ในขอบเขตที่ลายเซ็นครอบคลุม
RequestTimeTooSkewed นาฬิกาของ client หรือ server ไม่ถูกต้อง คำขอ S3 ทุกคำขอมีการประทับเวลา และจะถูกปฏิเสธหากอยู่นอกช่วง 15 นาที ตรวจสอบ timedatectl และยืนยันว่าการซิงโครไนซ์เวลาทำงานอยู่
Access Denied บน bucket ที่คุณทราบว่ามีอยู่ key นี้กำหนดขอบเขตไว้กับ bucket อื่น แสดงสิ่งที่ policy อนุญาตจริงด้วย mc admin policy info local restic-rw แล้วเปรียบเทียบชื่อ bucket ในบรรทัด resource
FAQ
การใช้งาน MinIO แบบโหนดเดียวเพียงพอสำหรับการสำรองข้อมูลจริงหรือไม่?
เพียงพอสำหรับการเป็นเป้าหมายของ restic หากรันอยู่บนเครื่องแยกต่างหากจากข้อมูลที่ต้องการปกป้อง แต่ไม่เพียงพอหากคุณมีสำเนาข้อมูลเพียงชุดเดียว การติดตั้งแบบดิสก์เดี่ยวไม่มี parity ดังนั้นจึงไม่มีสำเนาที่สองภายใน MinIO หากดิสก์ของ VPS นั้นสูญเสียข้อมูล ออบเจกต์ทั้งหมดจะหายไป ควรเก็บเป้าหมายสำรองไว้อีกแห่งหนึ่ง และทดสอบการกู้คืนจากทั้งสองแหล่งอย่างน้อยหนึ่งครั้งเพื่อให้มั่นใจว่ากระบวนการทำงานได้จริง
ทำไม sha256sum -c ถึงล้มเหลวเมื่อตรวจสอบไฟล์ checksum ของ MinIO?
คุณจะพบไฟล์นั้นเฉพาะในสำเนาที่บันทึกไว้ก่อนหน้าเท่านั้น เนื่องจาก dl.min.io ได้ตอบ 410 Gone สำหรับ binary และไฟล์ checksum ของชุมชนทั้งหมดแล้วเมื่อตรวจสอบ ณ วันที่ 10 ตุลาคม 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 ได้ถอดฟีเจอร์การจัดการออกจากคอนโซลรุ่น community edition ในเดือนพฤษภาคม 2025 โดยเหลือเพียงเครื่องมือเรียกดูออบเจกต์ในอินเทอร์เฟซเว็บ การจัดการ bucket และผู้ใช้งานในปัจจุบันต้องทำผ่านไคลเอนต์ mc โดยใช้คำสั่งเช่น mc admin user add และ mc admin policy attach นี่คือแนวทางที่ตั้งใจให้ใช้ในรุ่น community edition ไม่ใช่การแก้ปัญหาชั่วคราว ซึ่งเป็นเหตุผลว่าทำไมคู่มือนี้จึงดำเนินการทุกอย่างผ่านบรรทัดคำสั่ง
ฉันจะกำหนดให้ restic ใช้งาน MinIO เป็น S3 backend ได้อย่างไร?
ตั้งค่า AWS_ACCESS_KEY_ID และ AWS_SECRET_ACCESS_KEY ให้เป็น access key และ secret ของ MinIO จากนั้นใช้สตริง repository ในรูปแบบ s3:https://s3.example.com/restic โดยที่ส่วนท้ายของ path คือชื่อ bucket ให้สร้าง bucket ก่อนด้วย mc mb เนื่องจาก key ที่จำกัดสิทธิ์ไว้เฉพาะ bucket เดียวจะไม่มีสิทธิ์สร้าง bucket ใหม่ restic จะเข้ารหัสทุกอย่างด้วยรหัสผ่าน repository ของตนเองก่อนอัปโหลด ดังนั้น MinIO จะจัดเก็บเฉพาะข้อมูลที่เข้ารหัสและไม่สามารถเห็นไฟล์ของคุณได้
ฉันจำเป็นต้องรัน MinIO หลัง nginx หรือไม่?
คุณจำเป็นต้องใช้ TLS (transport layer security) ทุกครั้งที่ไคลเอนต์ไม่ได้อยู่บนเครื่องเดียวกัน เนื่องจากทั้งข้อมูลรับรอง S3 และข้อมูลออบเจกต์จะถูกส่งผ่านไปพร้อมกับคำขอ การใช้พร็อกซีที่พอร์ต 443 พร้อมใบรับรองจาก certbot เป็นวิธีที่ง่ายที่สุด และช่วยแยกการต่ออายุใบรับรองออกจาก MinIO ได้ MinIO สามารถทำ TLS termination ด้วยตนเองได้เช่นกันหากคุณชี้ --certs-dir ไปยังไดเรกทอรีที่เก็บ public.crt และ private.key ไว้ แต่ในกรณีนี้บัญชีผู้ใช้ที่รันเซอร์วิสจำเป็นต้องมีสิทธิ์อ่าน private key ที่ต่ออายุใหม่ ซึ่งเป็นการเพิ่มขั้นตอนโดยได้ผลลัพธ์เท่าเดิม