MinIO Object Storage บน VPS

เมื่อ application ของคุณต้องเก็บไฟล์ขนาดใหญ่ — รูปถ่าย วิดีโอ ไฟล์ log ข้อมูล backup — เลือกระหว่าง Amazon S3 (แพงมาก) หรือ storage บนเซิร์ฟเวอร์ local (ไม่ scalable) ต่างหากที่เกิด bottleneck การแก้ปัญหาทั่วไปคือ Object Storage ซึ่ง MinIO เป็นตัวเลือกที่ดีที่สุด — API compatible กับ S3 ราคาถูกกว่า แล้วรัน on-premise บน VPS ของคุณเอง

ทำไมต้องใช้ MinIO แทน S3

Amazon S3 บริการเก็บไฟล์บนคลาวด์ นิยมมากเพราะความน่าเชื่อถือ ความปลอดภัย และการออกแบบที่ยืดหยุ่น อย่างไรก็ตาม ค่า S3 คำนวณตาม per-GB/month (เรียก "pay-as-you-go") — หากอัปโหลด 10TB/เดือน ก็ต้องจ่าย ~$200 เพิ่มเติม นอกจากนั้น latency จาก Thailand ไปยัง AWS datacenter ใน Singapore เกิดความล่าช้า และไม่มีวิธีควบคุมอื่นนอกจากเสียเงิน ทุกการ call API ทุกข้อมูลที่ส่งออกมาต้องเสียค่า ซึ่งเป็นปัญหาสำคัญถ้า application ของคุณต้องการอ่านไฟล์บ่อยๆ หรือมี user จำนวนมากขณะเดียวกัน

สิ่งที่ต้องมีก่อนเริ่ม

ก่อนติดตั้ง MinIO ต้องเตรียมสิ่งต่อไปนี้ให้พร้อม ทั้งด้าน hardware, software, และการกำหนดค่าเครือข่าย

โครงสร้างไดเรกทอรี่

~/minio/
├── docker-compose.yml
├── .env
└── data/                    # โฟลเดอร์เก็บ object (แยกจาก Docker)

ขั้นที่ 1 — สร้างไดเรกทอรี่ MinIO

mkdir -p ~/minio/data
cd ~/minio
chmod 700 data

ขั้นที่ 2 — สร้าง .env Configuration

ไฟล์ .env เก็บรหัสผ่าน username และ environment variables ที่ใช้ใน Docker container ซึ่งเป็นข้อมูลที่ละเอียดอ่อน ต้องเก็บให้ปลอดภัย อย่าส่งไปยังที่ใดเด็ดขาด

cat > .env << 'EOF'
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=YourSecurePassword123!
MINIO_SERVER_URL=https://minio.example.com:9000
MINIO_BROWSER_REDIRECT_URL=https://minio.example.com:9001
EOF

แก้ไขให้เหมาะสม:

ขั้นที่ 3 — สร้าง docker-compose.yml

cat > docker-compose.yml << 'EOF'
version: '3.8'

services:
  minio:
    image: minio/minio:latest
    container_name: minio-server
    restart: unless-stopped
    env_file: .env
    ports:
      - "9000:9000"
      - "9001:9001"
    volumes:
      - ./data:/data
      - ./certs:/root/.minio/certs:ro
    command: server /data --console-address ":9001"
    networks:
      - minio-net

networks:
  minio-net:
    driver: bridge
EOF

ขั้นที่ 4 — ตั้งค่า SSL Certificate

MinIO ต้องการ SSL certificate ในรูปแบบ PEM เพื่อให้ HTTPS ทำงานได้ ใช้ Let's Encrypt ที่ฟรีและหมดอายุ 90 วัน ต้องต่ออายุอัตโนมัติ SSL certificate ทำให้ browser เชื่อถือ MinIO server ของคุณ และป้องกันข้อมูล username password จากการถูกดักจับใน network ก่อนเริ่มต้นตัวอย่างนี้ ให้ตรวจสอบว่า port 80 เปิดใน firewall เพื่อ Let's Encrypt verification

# ตรวจหา certificate ของ domain
ls -la /etc/letsencrypt/live/minio.example.com/

# ถ้ายังไม่มี ติดตั้ง certbot
sudo apt-get install certbot python3-certbot-nginx -y
sudo certbot certonly --standalone -d minio.example.com

หลังขอ certificate แล้ว ต้องส่ง path ให้ MinIO:

# สร้าง folder for MinIO certs
mkdir -p ~/minio/certs

# Copy certificate files
sudo cp /etc/letsencrypt/live/minio.example.com/fullchain.pem ~/minio/certs/public.crt
sudo cp /etc/letsencrypt/live/minio.example.com/privkey.pem ~/minio/certs/private.key

# ตั้ง permission
sudo chown $USER:$USER ~/minio/certs/*
chmod 600 ~/minio/certs/*

ขั้นที่ 5 — เพิ่ม Reverse Proxy (Nginx)

MinIO เรียกใช้ port 9000 (API) และ port 9001 (Console UI) โดยตรง ถ้าเปิด port เหล่านี้ไปยัง internet จะมีความเสี่ยง ดีกว่าใช้ Nginx reverse proxy ทำให้เข้าถึง MinIO ผ่าน port 443 (HTTPS) ปกติแทน นอกจากนี้ Nginx ยังช่วยจัดการ SSL certificate, load balancing, caching ได้ด้วย

cat > /etc/nginx/sites-available/minio.conf << 'EOF'
upstream minio_s3 {
    server localhost:9000;
}

upstream minio_console {
    server localhost:9001;
}

server {
    listen 443 ssl http2;
    server_name minio.example.com;

    ssl_certificate /etc/letsencrypt/live/minio.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/minio.example.com/privkey.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    client_max_body_size 5000M;

    # S3 API endpoint
    location / {
        proxy_pass https://minio_s3;
        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 600;
        proxy_send_timeout 600;
        proxy_read_timeout 600;
    }

    # MinIO Console (Web UI)
    location /minio/ {
        proxy_pass https://minio_console/;
        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;
    }
}

server {
    listen 80;
    server_name minio.example.com;
    return 301 https://$server_name$request_uri;
}
EOF

# เปิดใช้งาน config
sudo ln -s /etc/nginx/sites-available/minio.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

ขั้นที่ 6 — เริ่มต้น MinIO

cd ~/minio
docker-compose up -d
docker-compose logs -f minio

ถ้าเห็น All go.min.js, go.min.css files were cached แปลว่าเริ่มต้นสำเร็จ

✅ ทดสอบ SSL: เปิด browser ไปที่ https://minio.example.com:9001 หรือ https://minio.example.com/minio จะเห็น login page ของ MinIO Console

ขั้นที่ 7 — เข้าสู่ MinIO Console และสร้าง Bucket

เปิด browser ไป https://minio.example.com:9001

หลังเข้า Console แล้ว คลิก "Buckets" → "Create Bucket"

# หรือ ใช้ mc (MinIO Client) จาก command line
mc alias set minio https://minio.example.com:9000 minioadmin YourSecurePassword123! --api S3v4
mc mb minio/mybucket
mc version enable minio/mybucket

ขั้นที่ 8 — ตั้งค่า CORS สำหรับ Web Application

หากต้องการให้ browser JavaScript upload ไฟล์ตรงไปยัง MinIO server (แบบ direct upload) ต้องเปิด CORS (Cross-Origin Resource Sharing) เพื่ออนุญาตให้ browser ของ user จากโดเมนของคุณ (เช่น example.com) ส่งคำขอไปยัง MinIO server (minio.example.com) โดยค่าเริ่มต้น browser จะบล็อก cross-origin request ด้วยเหตุผลความปลอดภัย ต้องตั้งค่า CORS headers อย่างชัดเจน

cat > cors.json << 'EOF'
{
  "CORSRules": [
    {
      "AllowedOrigins": ["https://yourapp.com"],
      "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
      "AllowedHeaders": ["*"],
      "MaxAgeSeconds": 3000
    }
  ]
}
EOF

mc cors set --config-file cors.json minio/mybucket

เชื่อมต่อจาก Application

หลังตั้ง MinIO เสร็จแล้ว ขั้นตอนสุดท้ายคือเชื่อมต่อจาก application ของคุณ ขั้นนี้ง่ายมาก เพราะ MinIO รองรับ S3 API ทุกประการ ไม่ว่าจะเป็น PHP Laravel, Python, Node.js, Ruby, Go สามารถใช้ library S3 ของตัวเองได้ผลเลย ต้องแค่เปลี่ยน endpoint ชี้ไปยัง MinIO server ของคุณแทน AWS

PHP + Laravel

Laravel มี built-in support สำหรับ S3 ผ่าน AWS SDK สามารถใช้กับ MinIO ได้เลย ต้องเพิ่มการกำหนดค่า disk ใหม่ใน config/filesystems.php และตั้งค่า environment variables ให้ชี้ไปยัง MinIO endpoint ของคุณ

// config/filesystems.php
'minio' => [
    'driver' => 's3',
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => 'us-east-1',
    'bucket' => env('AWS_BUCKET'),
    'url' => env('AWS_URL'),
    'endpoint' => env('AWS_ENDPOINT'),
    'use_path_style_endpoint' => true,
];
// .env
AWS_ACCESS_KEY_ID=minioadmin
AWS_SECRET_ACCESS_KEY=YourSecurePassword123!
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=mybucket
AWS_ENDPOINT=https://minio.example.com:9000
AWS_URL=https://minio.example.com:9000

Python

Python มี minio-py library ซึ่งเป็น official MinIO client สำหรับ Python โหลดผ่าน pip แล้วสามารถใช้งาน object storage ได้ เหมือนกับ AWS S3 library

from minio import Minio

client = Minio(
    "minio.example.com:9000",
    access_key="minioadmin",
    secret_key="YourSecurePassword123!",
    secure=True
)

# Upload file ไปยัง MinIO
client.fput_object("mybucket", "myobject", "local_file.txt")

# Download file จาก MinIO
client.fget_object("mybucket", "myobject", "downloaded_file.txt")

Node.js

Node.js developer สามารถใช้ minio package จาก npm เพื่อเชื่อมต่อกับ MinIO server ได้ง่ายๆ ผ่าน callback หรือ Promise ตัวอย่างด้านล่างแสดงวิธีการ upload file โดยใช้ callback function

const Minio = require('minio');

const minioClient = new Minio.Client({
    endPoint: 'minio.example.com',
    port: 9000,
    useSSL: true,
    accessKey: 'minioadmin',
    secretKey: 'YourSecurePassword123!'
});

// Upload
minioClient.fPutObject('mybucket', 'myobject', 'local_file.txt', (err, etag) => {
    if (err) return console.log(err);
    console.log('File uploaded successfully!');
});

Troubleshooting และการแก้ปัญหา

ระหว่างการตั้ง MinIO อาจพบปัญหา อย่างไรก็ตาม ปัญหาส่วนใหญ่สามารถแก้ไขได้ด้วยการตรวจสอบ log ปรับการตั้งค่า และรีสตาร์ท container ได้ บทนี้จะอธิบายปัญหาทั่วไปที่อาจพบกับวิธีการแก้ไข

MinIO ไม่เริ่มต้น — error เกี่ยวกับ data directory

ปัญหานี้เกิดขึ้นเมื่อ Docker container ไม่มีสิทธิ์เขียนถึงโฟลเดอร์ data หรือมีไฟล์ที่เสียหาย

# ตรวจสิทธิ์
ls -la ~/minio/data
chmod 700 ~/minio/data

# ตรวจ log
docker-compose logs minio

# รีสตาร์ท
docker-compose restart minio

SSL certificate error เมื่อ connect จาก application

ปัญหาทั่วไป คือ application ไม่ยอมรับ SSL certificate ของ MinIO ส่วนใหญ่เกิดจากการ certificate expire ไม่ถูกต้อง หรือการ copy ไฟล์ certificate ไปยัง MinIO container ไม่เรียบร้อย ขั้นตอนแก้ไขคือ renew certificate จากLet's Encrypt, copy ไฟล์ใหม่ให้ MinIO, แล้ว restart container ให้โหลด certificate ใหม่

# Renew certificate จาก Let's Encrypt (ถ้ากำลังจะหมดอายุ)
sudo certbot renew --force-renewal

# Copy ไฟล์ certificate ใหม่ให้ MinIO
sudo cp /etc/letsencrypt/live/minio.example.com/fullchain.pem ~/minio/certs/public.crt
sudo cp /etc/letsencrypt/live/minio.example.com/privkey.pem ~/minio/certs/private.key

# Restart MinIO container เพื่อโหลด certificate ใหม่
docker-compose down
docker-compose up -d

Nginx error 413 (Request Entity Too Large)

# เพิ่ม client_max_body_size ใน nginx config
client_max_body_size 5000M;  # ตั้งเป็นขนาดที่ต้องการ

ต้องการ VPS สำหรับตั้ง MinIO Object Storage?

AsiaGB มี VPS Linux พร้อม SSD storage และ Full Root Access เหมาะสำหรับรัน MinIO production-ready เริ่มต้น 500 บาท/เดือน ได้ 20GB SSD storage

สมัครใช้งาน AsiaGB

ดูแพ็กเกจ VPS ไทย ราคาถูกทั้งหมด →